irm is an alias, not a program: four Windows install errors and the shell each one names

  • Yunik Maharjan
  • 14 min read

irm is not a program. It’s a PowerShell alias for the Invoke-RestMethod cmdlet, and that one fact is the whole of the Claude Code install failure on Windows.

Command Prompt defines no command called irm. So cmd.exe searches PATH for a program by that name, finds none, and prints 'irm' is not recognized as an internal or external command. The installer was never reached. Run the PowerShell line in PowerShell, or the Command Prompt line, which starts with curl.

The second question is the better one. Once Claude Code is installed, which shell does it run commands through, and does it need Git Bash or WSL 2 at all? The answer changed when the PowerShell tool shipped, and it is not the one I’d have given six months ago.

Why does irm not work in Command Prompt?

irm is a PowerShell alias for the Invoke-RestMethod cmdlet, and Command Prompt has no command by that name. So cmd.exe treats irm as an executable, searches PATH, and fails.

Where Microsoft writes that alias down has moved, which is most of the reason nobody knows it. The reference pages are authored Markdown, whose line numbers a reader can check, and every file cited below is pinned to commit 3bcc275, read on 29 October 2026. The Windows PowerShell 5.1 source runs to 754 lines, and the alias arrives at line 46, inside DESCRIPTION: “This cmdlet is introduced in Windows PowerShell 3.0. This command can be run using the irm alias.” That is 46 ÷ 754 = 6.1% down the file. First screen.

The current file dropped the second half of that sentence. The 7.6 file keeps “This cmdlet is introduced in Windows PowerShell 3.0.” and stops, and the alias survives in the body exactly once, at line 1,518 of 1,552: 1,518 ÷ 1,552 = 97.8%, inside NOTES, below a parameter table of 1,149 lines — line 340 to line 1,488, 74.0% of the document.

Nothing about the alias changed. The place a reader would find it did.

Anthropic turns the same mechanism into a diagnosis, two paragraphs below the three install blocks on its Advanced setup page: “If you see The token '&&' is not a valid statement separator, you’re in PowerShell, not CMD. If you see 'irm' is not recognized as an internal or external command, you’re in CMD, not PowerShell.” The message reports on the reader, not on the software.

cmd.exe is not aliasless, before somebody writes in to correct me: it has doskey macros, they last one console session, and none is called irm.

The install command for each Windows shell

PowerShell takes one line, Command Prompt takes another, and both fetch the same binary.

powershell

irm https://claude.ai/install.ps1 | iex

batch

curl -fsSL https://claude.ai/install.cmd -o install.cmd && install.cmd && del install.cmd

Both sit on the Advanced setup page under Native Install (Recommended), in blocks headed Windows PowerShell and Windows CMD. They install the same thing. Only the shell differs.

Telling them apart takes one glance at the prompt, and the page gives the test: “On Windows, your prompt shows PS C:\ when you’re in PowerShell and C:\ without the PS when you’re in CMD.” Windows Terminal opens either, and the default profile differs between machines. That is how a careful person pastes the wrong line into the right terminal.

The Command Prompt line opens with a bare curl, and on Windows that is a real executable rather than a borrowed name. Keep the distinction in view. It decides a subtraction three sections down.

Read the error message and it names your shell

All four Windows install errors Anthropic catalogues are shell-identification messages rather than installer faults. The four strings and the shell each one means you are in, from the Wrong install command on Windows section of the installation troubleshooting page, read on 29 October 2026. That page prints the first short, as 'irm' is not recognized; the full string below is the setup page’s.

Error text Shell you are actually in
'irm' is not recognized as an internal or external command Command Prompt
The token '&&' is not a valid statement separator PowerShell, with the CMD line
A parameter cannot be found that matches parameter name 'fsSL' Windows PowerShell 5.1, with the macOS or Linux line
'bash' is not recognized as the name of a cmdlet PowerShell, with the macOS or Linux installer

In every case the fix is the install line for that shell. Two of the four name something that is not there, irm in cmd.exe and bash on Windows. The other two are PowerShell refusing a line written for somewhere else: the && separator cmd.exe understands and Windows PowerShell 5.1 does not, and curl’s -fsSL flags. None mentions Claude Code, because Claude Code is not involved yet.

A fifth failure in the same section carries no error string: if the command prints the script’s text and installs nothing, you ran irm https://claude.ai/install.ps1 without | iex, or curl -fsSL https://claude.ai/install.cmd without -o.

A sixth belongs with them, on another page. Claude Code does not support 32-bit Windows sits in the terminal guide’s Windows troubleshooting section: “On a 64-bit machine, this error means you opened Windows PowerShell (x86) instead of Windows PowerShell.” Two Start-menu entries, one silently wrong, and the only visible difference is the (x86).

curl in Windows PowerShell 5.1 is not curl

In Windows PowerShell 5.1, curl is an alias for the Invoke-WebRequest cmdlet, so the macOS and Linux install line dies on a flag it cannot parse rather than on the network.

Microsoft’s own reference says so, and its two version monikers disagree. The 5.1 source file runs to 797 lines, alias block at line 783:

Windows PowerShell includes the following aliases for Invoke-WebRequest:

  • iwr
  • curl
  • wget

The 7.6 source file runs to 1,544 lines, same block at line 1,502:

PowerShell includes the following aliases for Invoke-WebRequest:

  • All platforms:
    • iwr

Same cmdlet, same block. One alias where there were three. Anthropic names the mechanism for the third error in the table above: “you ran the macOS/Linux curl -fsSL ... | bash installer in Windows PowerShell, where curl is an alias for Invoke-WebRequest and rejects the -fsSL flags.”

I can’t tell you which release dropped curl and wget. The same block carries “Beginning with PowerShell 6.0.0 Invoke-WebRequest supports basic parsing only”, a different change to the same cmdlet, and the aliases might have gone out with it. Microsoft’s reference states what each version has, never when anything went, so that is an inference rather than a fact. Run Get-Alias curl on the box in front of you and it settles in a second.

Real curl.exe has shipped since Insider build 17063, which Microsoft’s Windows Command Line blog announced on 18 January 2018: “Windows 10 Insider build 17063 and later now include the real-deal curl and tar executables”. The retail floor is one version higher, because the Windows 10 release information page puts 1709 at OS build 16299, below 17063, and 1803 at 17134, above it. Four letters, then: an alias in one window and an executable in the other, on one machine.

Claude Code’s Windows system requirements, build by build

Anthropic’s system requirements give the Windows line as “Windows 10 1809+ or Windows Server 2019+”, with “Shell: Bash, Zsh, PowerShell, or CMD.” one bullet below. Version 1809 is a marketing name; the build behind it decides whether a machine qualifies, and the release information page gives the ladder as 1803 at OS build 17134, 1809 at 17763, 1903 at 18362, 2004 at 19041.

Now the subtraction. curl.exe reached retail Windows at 17134 and Claude Code’s floor is 17763, so 17763 − 17134 = 629. Every machine that meets the minimum shipped with curl on PATH, 629 builds before that minimum existed, which is why the Command Prompt installer opens with a bare curl and never checks for it.

But the last bullet is a trap. “Shell: Bash, Zsh, PowerShell, or CMD” reads like a list of shells the agent can drive, and it is not one. Those are the four shells you can paste an install command into. What the agent uses afterwards is settled by the account you sign in with, which is where the obvious estimate goes wrong. With Git for Windows installed, the setup page puts the PowerShell tool “on by default for claude.ai and Console accounts, and enabled with CLAUDE_CODE_USE_POWERSHELL_TOOL=1 in Amazon Bedrock, Google Cloud’s Agent Platform, and Microsoft Foundry sessions”. Two engineers on identical laptops get different primary shells because one signs in through Console and the other through Bedrock. Set that variable to 0 or 1 and the account stops mattering.

Does Claude Code need Git Bash or WSL on Windows?

No, and it hasn’t since the PowerShell tool shipped. On a native Windows machine with no Git for Windows, the tools reference is flat about it: “Windows without Git Bash: the tool is enabled automatically.”

With Git for Windows present, the default inverts from what the name suggests. From the same page: “When the tool is enabled, Claude treats PowerShell as the primary shell. The Bash tool remains available for POSIX scripts when Git Bash is installed.” An install without Git Bash is not degraded. It is a different shell tool.

I had this one wrong going in.

Two things Git for Windows buys are named in the setup page’s native Windows section: “It provides Git Bash, which the Bash tool and the Monitor tool need.” I’d add a third the docs don’t spell out, as my inference rather than their claim: any script in the repository that starts with a shebang needs the Bash tool to run as written.

My third item sets a threshold, so it needs a tolerance first. Mine is zero repositories where the agent hits a hard stop, because a shebang script that cannot run is not a slow path, it is a refusal. The count of shebang files across one developer’s repositories runs from none to all of them, and Git for Windows installs once per machine rather than once per repository. So the threshold is one repository, not a fraction of the fleet. Halve it: if only half the repositories someone touches hold a shebang file, the benefit halves and one repository still clears it. People scope Git Bash per project, and it never was a per-project decision.

Two sharp edges live here. The error Claude Code on Windows requires either Git for Windows (for bash) or PowerShell fires on the condition the terminal guide states: “Neither PowerShell nor Git Bash was found. Claude Code needs at least one shell.” Its first fix is getting powershell.exe onto PATH, not installing Git. For the other case, Git installed but not found, point CLAUDE_CODE_GIT_BASH_PATH at C:\Program Files\Git\bin\bash.exe.

And the deny rules carry a side effect that caught me out. From the tools reference: “On Windows with Git Bash installed, denying Bash also turns the PowerShell tool off for the session.” A scoped rule is the worse case, because Claude Code “turns PowerShell off without a warning” and leaves Bash available. Deny Bash on a Windows box and you have narrowed the agent in one place and disarmed it in another.

Choosing between native Windows, Git Bash and WSL 2

Pick native Windows when the toolchain is Windows, add Git for Windows the moment a repository holds a shebang file, and move to WSL 2 only for a Linux toolchain or sandboxing.

Anthropic’s three-row table in the Set up on Windows section differs in one column — sandboxing, Not supported on native Windows and Supported on WSL 2. The sandboxing page is blunter: “On native Windows, Claude Code runs commands unsandboxed.” For a fleet with sandbox.failIfUnavailable set, “Claude Code exits at startup on those machines”.

Count the gap from the capability side first. Against WSL 2, native Windows gives up the sandbox, the Bash tool and the Monitor tool. Git for Windows recovers two of the three for one installer, so 2 ÷ 3 = 0.67 of the gap closes without a hypervisor. The version side tells the same story twice over. On Microsoft’s Comparing WSL Versions page the floor is “Windows 11 or Windows 10, Version 1903, Build 18362 or later”, which is 18362 − 17763 = 599 builds above Claude Code’s own floor. Route it through the higher floor on the Install WSL page — “You must be running Windows 10 version 2004 and higher (Build 19041 and higher) or Windows 11” — and 19041 − 17763 = 1,278, less the 19041 − 18362 = 679 above WSL 2’s own floor, leaves 1,278 − 679 = 599 again, and exactly one Windows version sits in that band.

Don’t reach for WSL 2 because it sounds like the serious choice. Read the feature table rather than the sentence under it: WSL 2 loses on two rows, Performance across OS file systems and Runs with current versions of VMware and VirtualBox. Microsoft’s prose directly beneath says WSL 2 “outperforms WSL 1 in several ways, with the exception of performance across OS file systems” — singular, on the same screen as its own table. On the row they agree about, Microsoft tells you to move the files, not the distribution: “Your project files must be stored in the Windows file system.” A repository that has to stay on C:\ is the one case where I would not reach for WSL 2 at all.

Derate the sandbox fourfold and the decision splits. For a Linux toolchain it doesn’t flip, because WSL 2 was chosen for the kernel and never for the sandbox. For a Windows-native team it does. Take three quarters off the sandbox and the advantage left is paid for on the file-system row. We settle this in week one of an applied AI engagement, because an unsandboxed agent on a laptop is a different risk from one in a WSL 2 distribution — the same argument that runs through agents that should have been plain workflows one layer down.

Installing with npm on Windows costs more than it saves

The npm package declares a Node version it does not enforce, fetches the same native binary the standalone installer does, and adds a .ps1 launcher that PowerShell’s execution policy blocks. The npm registry record carries "engines": {"node": ">=22.0.0"}, and the setup page’s install-with-npm section says what that does in practice: “On an older Node.js version, npm prints an EBADENGINE warning during install rather than failing; the install completes and claude still runs, since the package downloads a native binary that doesn’t use your Node.js at runtime.” A requirement nothing enforces, for a runtime the program never touches.

Two minutes with curl -s https://registry.npmjs.org/@anthropic-ai/claude-code/latest turns up something odder in the same record. Version 2.1.312 lists eight platform packages under optionalDependencies — darwin, linux and win32, x64 and arm64, plus two musl builds — above a single bin field reading {"claude": "bin/claude.exe"} for all of them. One .exe path, eight platforms. Read on 29 October 2026.

The failure that actually bites arrives later. An npm install writes .ps1 launcher scripts, and the first claude gives you npm : File C:\Program Files\nodejs\npm.ps1 cannot be loaded because running scripts is disabled on this system. The troubleshooting page has the reason the native installer never hits it: “The policy applies to script files, so it doesn’t affect the PowerShell installer irm https://claude.ai/install.ps1 | iex, which runs the downloaded text directly.” The policy stops the local launcher and waves the piped remote script through.

A fleet manager should read one paragraph further down the tools reference: “Claude Code spawns PowerShell with -ExecutionPolicy Bypass at process scope only … Process-scope bypass doesn’t override Group Policy MachinePolicy or UserPolicy, so enterprise policies still apply.” Setting CLAUDE_CODE_POWERSHELL_RESPECT_EXECUTION_POLICY=1 gives the machine’s effective policy back.

So I would not install Claude Code on Windows through npm. It buys nothing the native installer doesn’t, and adds a failure mode with its own documentation section. Verify either route with claude --version, which prints a version number, and claude doctor, which “prints read-only installation and settings diagnostics without starting a session”. Install problems are cheap because the error strings are exact. Agent behaviour isn’t, which is why we build the evaluation set first on anything we ship.

Tell us what’s broken.

Twenty minutes, no deck. We’ll tell you straight whether this is work we should be doing, and if it isn’t, we usually know who should.

We come back within one business day.