cheat sheet
nodemon
Daily-driver reference for nodemon — watch flags, exec patterns, config files, lifecycle events.
nodemon — CLI
What it is
nodemon watches files and restarts a wrapped command when something changes. Default-target is Node, but --exec makes it run anything. It's the long-time default dev-loop tool for Node servers. The native node --watch flag (Node 18.11+) covers the simple case, but nodemon's globs, debounce, config file, and event hooks are still worth the dependency.
For the package overview, see packages-npm/npm-nodemon. This page focuses on the CLI.
Install
npm install -D nodemon
# or
npm install -g nodemon
Output: nodemon binary in node_modules/.bin/ or on user $PATH.
Day-to-day commands
| Command | What it does |
|---|---|
nodemon src/server.js | Watch *.js,*.mjs,*.cjs,*.json in cwd; restart server on save |
nodemon --watch src src/server.js | Watch only the src/ directory |
nodemon --ext ts,tsx --exec "tsx src/server.ts" | Run a TS server, restart on .ts/.tsx change |
nodemon --delay 500ms src/server.js | Debounce restarts |
nodemon --legacy-watch src/server.js | Polling watcher (WSL/Docker compatibility) |
nodemon --inspect src/server.js | Pass --inspect to Node (debugger port) |
nodemon -e py --exec "python main.py" | Use as a generic file-watcher for any command |
nodemon --ignore "**/*.test.ts" src/server.ts | Ignore certain files |
nodemon (no args, with nodemon.json) | Load config from nodemon.json |
rs<Enter> in the terminal forces a manual restart.
Common scenarios
Watch a TS server
nodemon --watch src --ext ts,tsx,json --exec "tsx src/server.ts"
Output:
[nodemon] 3.1.0
[nodemon] watching path(s): src
[nodemon] watching extensions: ts,tsx,json
[nodemon] starting `tsx src/server.ts`
Server listening on :3000
[nodemon] file changed: src/api/users.ts
[nodemon] restarting due to changes...
Use nodemon.json to keep CLI short
{
"watch": ["src", "config"],
"ext": "ts,tsx,json,yaml",
"ignore": ["src/**/*.test.ts"],
"delay": "500ms",
"exec": "tsx src/server.ts",
"env": {
"NODE_ENV": "development",
"LOG_LEVEL": "debug"
}
}
nodemon
Output:
[nodemon] config: nodemon.json
[nodemon] watching extensions: ts,tsx,json,yaml
[nodemon] starting `tsx src/server.ts`
Pass arguments through to the script
nodemon src/server.js -- --port 3001 --verbose
Output:
[nodemon] starting `node src/server.js --port 3001 --verbose`
server listening on http://localhost:3001
Everything after -- is forwarded to the wrapped process. Without --, nodemon swallows them as its own flags.
Lifecycle hooks (run shell commands on events)
{
"exec": "node src/server.js",
"events": {
"start": "echo '🚀 starting'",
"restart": "curl -s http://localhost:3000/health",
"crash": "say 'Server crashed'"
}
}
Useful for: warmup pings, desktop notifications on crash, Slack webhooks.
Debug mode
nodemon --exec "node --inspect-brk src/server.js"
Output:
[nodemon] starting `node --inspect-brk src/server.js`
Debugger listening on ws://127.0.0.1:9229/...
The --inspect-brk flag belongs to Node, not nodemon — pass via --exec. Then attach VS Code or Chrome DevTools.
Polling watcher for WSL / Docker / NFS
nodemon --legacy-watch --polling-interval 500 src/server.js
Output:
[nodemon] starting `node src/server.js`
[nodemon] using polling (500ms)
Native file events don't always propagate across virtual filesystems. Polling is slower but reliable.
Generic command-runner
# Re-build Go on .go changes
nodemon -e go --exec "go run ./cmd/server"
# Rebuild docker stack
nodemon --watch ./docker --ext yml --exec "docker compose up -d --build"
Output:
[nodemon] watching extensions: go
[nodemon] starting `go run ./cmd/server`
Useful flags
| Flag | What it does |
|---|---|
--watch <path> | Add a path to watch (default: cwd) |
--ignore <pattern> | Ignore matching files |
--ext <list> | Comma-separated extensions to watch |
--exec <cmd> | Command to run on each restart |
--delay <time> | Debounce restarts (500ms or 2) |
--legacy-watch | Use polling instead of native FS events |
--polling-interval <ms> | Tune polling interval |
--no-restart-after | Don't restart after a crash |
--signal <SIGNAL> | Signal sent on restart (default SIGTERM) |
--quiet | Suppress nodemon's own log lines |
--verbose | Extra logging |
--config <path> | Use a non-default config file |
--inspect | Convenience pass-through to Node (without --exec) |
--dump | Print resolved config and exit |
Configuration
nodemon.json (in project root) or nodemonConfig block in package.json:
{
"name": "my-app",
"scripts": {
"dev": "nodemon"
},
"nodemonConfig": {
"watch": ["src"],
"ext": "ts,tsx,json",
"exec": "tsx src/server.ts",
"delay": "500ms",
"env": {
"NODE_ENV": "development"
}
}
}
Schema summary:
| Key | Type | Purpose |
|---|---|---|
watch | string[] | Paths to watch |
ignore | string[] | Patterns to skip |
ext | string | Comma-separated extensions |
exec | string | Command to run |
delay | string/number | Debounce duration |
env | object | Extra env vars for the wrapped process |
events | object | Shell commands keyed by event name |
signal | string | Signal sent on restart |
legacyWatch | boolean | Force polling |
Common pitfalls
--inspectflag goes to nodemon, not Node. Use--exec "node --inspect src/server.js"instead.- WSL/Docker volumes miss changes. Switch to
--legacy-watch. - Linux inotify watch limit exhausted.
ENOSPCerror — raisefs.inotify.max_user_watchesor narrow the watch scope. .gitignoreis NOT honoured by default. Use explicitignorepatterns.- Editor atomic-write fires multiple events. Bump
--delayto debounce. Cannot find moduleafter a restart. Probably restarted before npm install finished — wait thenrs.- Restart on irrelevant file (e.g.
.log). Tightenextandignore.
See also
- Packages: npm-nodemon — versioning, ecosystem
- JavaScript: node-runtime — native
--watchalternative - JavaScript: tsx —
tsx watchfor TS-only watch