Breaking
Fix nodemon: command not found

Fix nodemon: command not found

A locally installed nodemon is not on your PATH, and it is not supposed to be. Your shell looking for a global binary is the bug, not the missing global install.

How this was written

Drafted in plain Markdown by Ethan Laurent and edited against current Node.js, framework and tooling docs. Every command, code block and benchmark in this article was run on Node.js 24 LTS before publish; if a step does not work on your machine the post is wrong, not you — email and I will fix it.

AI is used as a research and outline assistant only — never as a single-source author. Full editorial policy: About / How nodewire is written.

Tested on Node.js 24 LTS · last reviewed June 2026

You cloned a repo, ran npm install, typed nodemon like you always do, and the shell answers nodemon: command not found. The package.json clearly lists nodemon as a dependency. It installed without complaint. And yet the command doesn’t exist. The nodemon command not found error trips up people who’ve used Node for years, because the instinct — npm install -g nodemon — works but is the wrong lesson, and it papers over what’s actually going on.

Quick fix

A locally installed nodemon lives in node_modules/.bin/, which is not on your shell’s PATH, so typing nodemon directly can’t find it. Run it through npx nodemon, or — better — add it to a package.json script and run npm run dev, where npm puts node_modules/.bin on PATH automatically:

JSON
{
  "scripts": {
    "dev": "nodemon src/index.js"
  }
}
bash
npm run dev        # works: npm adds node_modules/.bin to PATH
npx nodemon src/index.js   # also works, runs the local binary

You don’t need a global install. If you’re on a recent Node, you may not need nodemon at all — node --watch is built in.

The error:

text
zsh: command not found: nodemon
# or
bash: nodemon: command not found

Mac, zsh, bash, and Windows wording

The message looks different per shell, but it’s the same problem. On macOS you’ll usually see zsh: command not found: nodemon. On older Linux shells or some terminal setups, it’s bash: nodemon: command not found. In the VS Code integrated terminal it follows whichever shell you’ve configured, so it shows up as either of those. On Windows it reads 'nodemon' is not recognized as an internal or external command. In every case the cause is identical: your terminal can’t see the local nodemon binary unless you run it through npm run or npx.

Why the local binary isn’t on your PATH

When you npm install nodemon, npm puts the package in node_modules/nodemon and drops an executable shim in node_modules/.bin/nodemon. Your shell resolves bare commands by searching the directories in $PATH, and your project’s node_modules/.bin is not one of them. So nodemon typed at the prompt fails, exactly the way Cannot find module fails when Node can’t resolve a package — same root idea, different resolver. The binary exists; nothing told your shell where to look.

This is by design. Per-project binaries shouldn’t leak into your global shell, because two projects might pin different nodemon versions and you’d never know which one you’re running. The local install is correct. The expectation that a bare nodemon works is the bug.

The wrong fix everyone tries first

npm install -g nodemon makes the command work, so it feels like the answer. It isn’t, for two reasons. First, a teammate who clones the repo still hits command not found because the global install lives on your machine, not in the project — so the fix doesn’t travel. Second, the global nodemon is a different version from the one in the project’s lockfile, so you can get behavior that nobody else can reproduce. Global dev tools are how “works on my machine” starts. Keep nodemon local and reach it properly.

Fix 1: npm scripts (the right default)

First, make sure nodemon is a dev dependency — it’s needed during development, not by the running production app:

bash
npm install --save-dev nodemon

Then lean on how npm scripts work: npm runs them with node_modules/.bin prepended to PATH, so any locally installed binary is callable by its bare name inside a script. Put your dev command there:

JSON
{
  "scripts": {
    "dev": "nodemon --watch src src/index.js",
    "dev:ts": "nodemon --watch src --exec tsx src/index.ts"
  }
}

Now npm run dev just works, for you and for anyone who clones the repo. This is the convention every project should follow — commands live in scripts, contributors run npm run <name>, and nobody needs anything installed globally. The TypeScript variant pairs nodemon with tsx; see the TypeScript setup guide for the full dev loop.

Fix 2: npx for one-offs

If you just want to run it once without editing package.json, npx finds the local binary (and falls back to fetching it if it’s not installed):

bash
npx nodemon src/index.js

npx (npm exec) runs the command with the project’s node_modules/.bin on PATH, the same context npm run uses. It’s the right tool for ad-hoc runs. For anything you’ll type more than twice, make it a script.

If nodemon is installed but still not found

If npm run and npx both fail, confirm the project actually has nodemon installed:

bash
npm ls nodemon

If the repo has a lockfile, reinstall dependencies cleanly:

bash
npm ci

If npx nodemon still can’t find it, you’re likely outside the project root (your terminal’s working directory is wrong), or you’re in a monorepo workspace where nodemon is installed in a different package than the one you’re standing in. cd to the package that lists nodemon and try again.

Fix 3: skip nodemon entirely on recent Node

Node has had a built-in watch mode since Node 18. Node’s built-in watch mode is stable now, so for simple projects it’s worth trying before adding nodemon at all:

bash
node --watch src/index.js
# TypeScript:
node --watch src/index.ts

On recent Node 24 releases, that second command can work for simple TypeScript files because Node can strip erasable TypeScript syntax. It is not a full TypeScript toolchain: Node does not apply tsconfig.json paths, does not type-check your code, and still fails on syntax that requires transformation (enums, decorators, namespaces). For a full TypeScript dev loop, keep tsx. See the Node --watch docs for what it does and doesn’t track.

When nodemon is still better than node –watch

node --watch covers the common case — restart the server when a file changes — with zero dependencies. nodemon still earns its place when you need its richer config: watching non-JS files, custom --ext lists, debounce/delay, ignore rules, or running a non-node command on change (--exec). Reach for node --watch first; add nodemon back when you hit one of those limits, not before.

Development vs production: nodemon is not PM2

nodemon is a development restart tool, not a production process manager. Don’t run your deployed service under it. For production restarts, clustering across CPU cores, log management, and startup scripts, use a process manager such as PM2 — covered in the PM2 in production guide. nodemon watches files and restarts on edits; PM2 keeps a crashed process alive and starts it on boot. Different jobs.

Which to use

Use an npm script for everything you run regularly — it’s the convention and it travels with the repo. Use npx nodemon for a one-off. On a recent Node, try node --watch first and only add nodemon back if you hit its limits. Whatever you pick, the global install is the one option to avoid, because the entire problem was a tool that wasn’t pinned to the project.

FAQ

Why does nodemon: command not found happen after npm install?

Because a local install puts nodemon in node_modules/.bin/, which is not on your shell’s PATH. Typing nodemon directly can’t find it. Run it with npx nodemon or via a package.json script (npm run dev), where npm adds node_modules/.bin to PATH automatically.

Should I install nodemon globally to fix command not found?

No. A global install works on your machine but not for teammates who clone the repo, and it can be a different version than the project’s lockfile, causing irreproducible behavior. Keep nodemon as a local dev dependency and run it through an npm script or npx.

How do I run a locally installed nodemon?

Either npx nodemon src/index.js, or add "dev": "nodemon src/index.js" to package.json scripts and run npm run dev. Both resolve the binary in node_modules/.bin without needing it on your global PATH.

Why does nodemon: command not found happen on Mac (zsh) but not in npm run?

On macOS the default shell is zsh, which only searches $PATH — and node_modules/.bin isn’t on it, so you get zsh: command not found: nodemon. npm run and npx add that directory to PATH for the command they launch, so the same binary resolves there. It’s the shell, not nodemon.

Do I still need nodemon on recent Node?

Often not. node --watch src/index.js is built in and restarts on file changes. Keep nodemon when you need its advanced options — watching non-JS files, custom extensions, debounce, ignore rules, or running a non-node command via --exec.

Why does npm run dev work but typing nodemon doesn’t?

npm runs scripts with node_modules/.bin prepended to PATH, so locally installed binaries are callable by name inside a script. Your interactive shell doesn’t add that directory, so the same bare command fails at the prompt but succeeds inside npm run.