OpusMill

‘rm’ is not recognized as an internal or external command

Verified on Windows 11, Node 24.20.0 · OpusMill

'rm' is not recognized as an internal or external command,
operable program or batch file.
The fix
npm install --save-dev rimraf
- "clean": "rm -rf dist"
+ "clean": "rimraf dist"

For commands other than rm, shx gives you a cross-platform version of most of them: shx cp, shx mkdir -p, shx cat.

Why it happens

npm runs scripts through cmd.exe on Windows, and cmd.exe has none of the Unix commands. There is no rm, no cp, no sed. Windows has del and rmdir, which take different flags and behave differently, so the answer is not to translate the command — it is to use something that works everywhere.

Instead ofUse
rm -rf distrimraf dist
cp a bshx cp a b, or copyfiles
mkdir -p a/bmkdirp a/b, or shx mkdir -p a/b
mv a bshx mv a b
cat a b > ca small Node script — redirection differs too
sed -i ...a Node script. There is no honest one-liner.

The part that wastes an afternoon

It may work on your Windows machine and fail in CI, or work in one terminal and fail in another on the same machine. Git for Windows ships rm, cp, sed, grep, ps and more in C:\Program Files\Git\usr\bin. Git Bash puts that directory on PATH; the system PATH does not have it.

So the same command succeeds from Git Bash and fails from cmd, PowerShell, a service, or a CI runner. Checked on this machine:

PS> (Get-Command rm).Source            -> nothing (PowerShell aliases rm to Remove-Item)
PS> (Get-Command sed).Source           -> C:\Program Files\Git\usr\bin\sed.exe

PS> [Environment]::GetEnvironmentVariable('Path','Machine') -match 'usr.bin'
False
PS> [Environment]::GetEnvironmentVariable('Path','User')    -match 'usr.bin'
False

That directory was on PATH only because the shell had been launched from Git Bash. If a colleague says “it works for me,” this is usually why — and it is why the fix belongs in package.json rather than in a PATH setting nobody else has.

A trap in PowerShell specifically

PowerShell aliases rm to Remove-Item, so rm -rf build there does not say “not recognized” at all. It says this:

PS> rm -rf build
A parameter cannot be found that matches parameter name 'rf'.

Same cause, different message, and one that sends people looking for a PowerShell problem rather than a portability one. The alias is why (Get-Command rm).Source is empty above — there is no rm.exe being found, just a built-in alias with different flags.

What about the shell-syntax scripts?

If your script is for FILE in test/*.js; do ...; done, or uses $(...), or pipes into sed, there is no package that fixes it. That is a shell program, and cmd.exe cannot run shell programs. Move it into a .mjs file and call it with node, which runs anywhere. That is more work than swapping in rimraf, and it is the only honest answer.

Check your own project for the rest of this class of bug. Paste your code or your package.json into the browser checker — nothing is uploaded, it runs on your machine — or run npx github:Hackierz/winbreak over the whole repository. --fix repairs the npm scripts that have one obvious answer and refuses the ones that need a human.

Other errors in the same family:

Background: I scanned the 600 most-downloaded npm CLI packages — 17.4% have a package.json script that cannot run on Windows.