CLI tool
remy/nodemon avatar
remy/nodemon

nodemon is a wrapper for the word node, and its Dockerfile has every runtime line commented out

Monitor for any changes in your node.js application and automatically restart the server - perfect for development

26,662 stars1,738 forksJavaScriptMIT

At a glance

What is it?
A MIT-licensed development tool that restarts a Node.js process on file changes, with a three-level config precedence, a user-extensible executable map, and a container file that ends at WORKDIR /src. Its own documentation links still point at a master branch the project no longer defaults to.
Who is it for?
nodemon fits a developer who wants one word changed on the command line and a wrapper that keeps watching after the app exits. It does not fit a team that needs a container image from this repository, or documentation links that point at the default branch.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 12 days ago.
What is it written in?
Mainly JavaScript, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on November 13, 2026, and from our analysis. They are not legal advice.

From daily snapshots

Star history

  • remy/nodemon26,662 ★ · +4
Star history
Repository2026-09-282026-11-13
remy/nodemon26.7k26.7k

4 Stars in the last 46 days, measured from the daily GitHub snapshot. Compare with other projects

Editorial analysis

The whole contract is replacing the word node, and a local install takes it off your path

nodemon is a wrapper, not a runtime. It requires no changes to your code or to how you develop, and you use it by putting it where node would have gone on the command line. The global install is the recommended one:

bash
npm install -g nodemon # or using yarn: yarn global add nodemon

Installed globally it lands on your system path, so `nodemon [your node app]` works from anywhere and every argument you would have passed to your app still goes through, including `nodemon --inspect ./server.js 80`.

The development dependency is the other route, and it has a consequence that catches people:

bash
npm install --save-dev nodemon # or using yarn: yarn add nodemon -D

With a local install nodemon is not on your system path, so you cannot type it directly. You have to call it from inside an npm script, such as `npm start`, or go through `npx nodemon`. That is why the same command works on one machine and reports command not found on another with an identical package.json.

Two conveniences are built in. If package.json exists you can omit the main script entirely, because nodemon reads the `main` property for it, and it also looks for `scripts.start`. Output from the tool itself is prefixed with `[nodemon]` so it is distinguishable from your application's own output, including errors.

A local nodemon.json silently discards your package.json settings

There are two places to put settings and a rule that decides between them. Specificity runs command line arguments, then local config, then global config, so a flag always wins over a file. Config files are usually named `nodemon.json` and can sit in the current working directory or in your home directory, and `--config <file>` points at an alternative one. Any command line argument can be a JSON key in that file.

The trap is the second configuration home. The same keys can go under `nodemonConfig` in package.json, which is convenient for keeping everything in one place. But the note that follows is unambiguous: if you specify a `--config` file or provide a local `nodemon.json`, any `package.json` config is ignored. Not overridden, ignored. So adding a local file to set one option silently disables the block a colleague wrote in package.json, and the only symptom is settings that stopped applying.

This is also the one part of the file that admits its own weakness. The section carrying the rule says it needs better documentation and points you at `nodemon --help config` instead, with the option list in doc/cli/config.txt. A precedence rule that decides whether your settings apply at all is not the place to be the least documented part of a tool people put in front of their whole team.

execMap is the extension point, and the default table is one file you can patch

nodemon is not only for JavaScript. It reads the file extension of the script it is running and monitors that extension instead of `.js`, provided there is no `nodemon.json` to override it:

bash
nodemon --exec "python -v" ./app.py

That runs app.py under python in verbose mode and watches for `.py` files. When the extension alone is not enough, `execMap` in nodemon.json names the executable, so a Perl project can add `"pl": "perl"` and then run `nodemon script.pl` and be understood. The README's own example config does this for ruby and for processing, adding `"pde": "processing --sketch={{pwd}} --run"` so that `nodemon demo.pde` works with no built-in support for processing at all.

The division of responsibility is explicit. Your own execMap entries are recommended for the global `nodemon.json`, on your machine, and if a default is genuinely missing for everyone, the route is to change `lib/config/defaults.js` and send a pull request. So a language nodemon does not know is either a two-line file in your home directory or a contribution. Watching is the other half of the mechanism, and `--watch` narrows it:

bash
nodemon --watch app --watch libs app/server.js

Sub-directories are traversed by default so there is no need to list them, and unix globbing works too, for example `--watch './lib/*'`, with the pattern quoted.

The Dockerfile ends at WORKDIR /src, with its COPY, its EXPOSE and its CMD commented out

The repository ships a Dockerfile, and it cannot produce a runnable image. It starts `FROM ubuntu:16.04`, installs curl and locales, generates the en_US.UTF-8 locale, and sets `ENV LANG en_US.utf8`. It then installs Node.js by piping the NodeSource setup_10.x script into bash, installs nodejs and build-essential, and runs `npm install -g npx`, which by this point is already part of Node. The last live line is `WORKDIR /src`.

Everything that would make it an image is commented out. The copy of the application source is disabled with a link to a Stack Overflow question about COPY from a URL above it. The port line reads `# EXPOSE 8080` and the command line reads `#CMD ["node", "/src/http.js"]`, both with explanatory comments. A comment in the middle explains that those two kinds of line behave differently during a build, which is true and is not the problem here.

The practical result is that anyone looking for a containerised nodemon to copy finds a file that installs a toolchain and stops. There is no application, no port and no process, so the file cannot be used as a base image for anything without being rewritten.

The default branch is main and every documentation link still points at master

The repository's default branch is main. The README's own links do not agree. The FAQ, the sample options file in doc/sample-nodemon.md, the config option list in doc/cli/config.txt, and the file you are told to change when a default executable is missing all use /blob/master/ paths.

That is a documentation rot that a reader hits within the first ten minutes, because the FAQ is the first place the file sends you when you want more. Links into a branch that is no longer the default either fail outright or, if master still exists as a stale branch, quietly describe code that is not what you installed. And the stale branch is a real hazard in a tool whose behaviour is entirely a function of which defaults it holds.

The release history has a similar shape. The three most recent tags are v3.1.12 and v3.1.13 on 2026-02-19 and v3.1.14 on 2026-02-20, and the last push to the default branch was 2026-11-02. So there is development after the newest release and no tag for it, which is normal for an actively changed repository but does mean the version on npm and the code on main are not the same thing.

The lint script only reads lib/**/*.js, and a jshintrc sits beside it unused

Two linter configurations sit at the root, `.eslintrc.json` and `.jshintrc`, alongside a `.prettierrc.json` and a jsconfig.json. Only one of them is wired to anything. The lint script is `eslint lib/**/*.js`, so every other JavaScript in the repository, the bin/ entry point, the tests, the doc examples and the website directory, is outside the glob the linter looks at.

That script is on the critical path twice. `test` is `npm run lint && npm run spec`, so the tests do not start if lib/ fails lint, and `prepush` runs the same lint before a push. What that buys you is a linted core and unchecked edges, and the file that would lint the edges, `.jshintrc`, is not invoked by any script in package.json.

A third small mismatch sits next to it. The `web` script is `node web`, and the repository has a `website/` directory at the top level rather than a `web/` one, so that script has no target as the tree stands. The `killall` script is the outlier in the other direction: it pipes `ps auxww` through a grep for node and an awk print of the second field into `xargs kill -9`, which force-kills every Node.js process on the machine rather than nodemon's own child.

One mocha process per test file, a sleep between them, and a clean step afterwards

The test runner is a shell loop rather than a single invocation. For each file matching test/**/*.test.js it echoes the name, runs `mocha --exit --timeout 30000` against that one file, exits 1 on the first failure, and sleeps one second before the next file. The consequence is that the suite is serial and pays a process start per file, and that a failure stops the run at the file that produced it instead of collecting the rest.

The one-second pause has an obvious purpose and an obvious cost. mocha is started with `--exit`, so each process forces its way out rather than waiting for handles to close, and the pause gives the filesystem watcher and the spawned child processes a moment to die before the next file starts. Coverage is a separate script, `istanbul cover _mocha` with a 30 second timeout and a list reporter, so a coverage run is not the same run as the test run.

There is a cleanup step, wired as `postspec`, and it is worth knowing about because it deletes files: `rm -rf test/fixtures/test*.js test/fixtures/test*.md`. Fixtures with those two prefixes are created by the suite and removed afterwards, so any file you keep there under a matching name is temporary. Everything else in the file follows from the same toolchain: commitlint enforces conventional commits on commitmsg, husky installs the hooks, and semantic-release with a `.releaserc` cuts the tags, which is how three of them landed on consecutive days in February.

Editorial conclusion

nodemon fits a developer who wants one word changed on the command line and a wrapper that keeps watching after the app exits. It does not fit a team that needs a container image from this repository, or documentation links that point at the default branch. Before depending on it, read the engines field and the Dockerfile yourself, move your settings into one config home because a local nodemon.json silently discards package.json config, and check whether the execMap default you need exists in lib/config/defaults.js or has to be patched.

Frequently asked questions

What is nodemon used for?

It restarts a Node.js application automatically when file changes are detected in the directory being watched, so you do not stop and start the process by hand. It is a replacement wrapper for `node`, so you use it by putting it where node would have gone on the command line, and it needs no changes to your code.

Is nodemon still used?

The repository is not abandoned. The default branch was last pushed on 2026-11-02, after v3.1.14 was published on 2026-02-20 following v3.1.12 and v3.1.13 on 2026-02-19. The MIT licence, the `engines` field of node >=10 and the use of it in the project's own README examples all point at an actively maintained tool.

How do I start a server using nodemon?

Replace node with nodemon and keep your arguments, for example `nodemon ./server.js localhost 8080`, or pass `nodemon --inspect ./server.js 80` for the debugger. If you have a package.json you can leave the main script out, because nodemon reads the `main` property, and it also looks for `scripts.start`.

How do I use nodemon in package.json?

Put the settings under a `nodemonConfig` key in the same JSON shape a config file uses, for example with `ignore` and `delay` values. The catch is that if you pass `--config` or create a local `nodemon.json`, any package.json config is ignored rather than merged, so pick one place and keep it there.

How to install nodemon?

The global install is the recommended one, `npm install -g nodemon`, which puts it on your system path. `npm install --save-dev nodemon` puts it in the project instead, and a local nodemon is not on your path, so you have to call it from an npm script such as `npm start` or run it through `npx nodemon`.

Official sources

  1. License: MIT
  2. Project website
  3. README
  4. Releases
  5. remy/nodemon on GitHub
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/remy-nodemon.svg)](https://hysenlabs.com/projects/remy-nodemon)

Star history chart for your README

markdown
[![Star history](https://hysenlabs.com/chart/remy-nodemon.svg)](https://hysenlabs.com/projects/remy-nodemon)

Was this useful?