Nodemon: How to Auto-Restart Node.js Apps on Save

Table of Contents

Introduction

nodemon is a CLI utility that watches files and restarts your Node.js process on save. Set it up with npm, add package.json scripts, and tune watch, ignore, and delay flags for a tighter dev loop. This article walks through installation, setup, and configuration with examples using Express, plus cross-platform terminals on Linux, macOS, and Windows.

What is ?

Prerequisites

If you want to follow along with this article, you will need Node.js installed on your own machine, so you can try everything right where you work.

To set this up without relying on another guide, download the official installer for your operating system or use a package manager to install Node.js and create a local development environment that includes npm and the Node.js runtime. Common options include:

  • apt on Ubuntu
  • Homebrew on macOS
  • Chocolatey on Windows

After installation, confirm everything is ready by running simple version checks such as node -v and npm -v .

 $ node -v $ npm -v 

I tested this tutorial with Node.js v17.1.0, npm v8.1.2, nodemon v2.0.15, and express v4.17.1, so that is the baseline I used.

Component Version tested
Node.js v17.1.0
npm v8.1.2
nodemon v2.0.15
express v4.17.1

These specific versions show the setup used during testing; newer stable versions usually work as well, but checking your local versions helps make sure behavior stays consistent while you follow the steps.

These steps work for the most recent releases of Ubuntu:

  • Ubuntu 24.04
  • Ubuntu 22.04
  • Ubuntu 20.04

If you are on Ubuntu version 18.04 or older, I recommend you upgrade to a newer release, since the older versions no longer get support.

Rather than linking to another set of upgrade instructions, keep in mind that moving to a supported release helps you keep receiving security updates and compatibility with modern tools; you can perform the upgrade using your distribution’s standard release upgrade tools or by following the official Ubuntu upgrade workflow appropriate to your current version.

Learn more in the Official Node.js Installation Guide.

Install nodemon

Step 1: Installing Nodemon

First, you will need to install nodemon on your machine, because that is a simple way to get going quickly on your own setup. Install the utility either globally or locally on your project using npm or yarn , and pick the option that feels right for how you like to work.

Global Nodemon Installation

You can install nodemon globally with npm :

$ npm install nodemon –global

so it is available everywhere on your system without extra setup. Or with yarn :

$ yarn global add nodemon

if you prefer using yarn for your tools.

Local Nodemon Installation

You can also install nodemon locally, which keeps it right inside your project so it travels with your code. When performing a local installation, you can install nodemon as a dev dependency with --save-dev (or --dev ), which helps keep it out of production builds while you develop.

Install nodemon locally with npm :

$ npm install nodemon –save-dev

when you want to use npm and keep things consistent. Or with yarn :

$ yarn add nodemon –dev

when yarn is your go to package manager.

With a local install you will not be able to use the nodemon command directly at first.


Output
command not found: nodemon

You can execute the locally installed package:

$ ./node_modules/.bin/nodemon.js [your node app]

which runs the project scoped binary directly without needing a global install. You can also use it in npm scripts or with npx , which is handy for keeping commands short and easy to remember.

Choosing Between Global and Local

To add clarity when choosing between installation methods: a global installation makes the nodemon command available system-wide, which can be convenient for quick experiments across multiple projects, however, it ties your workflow to a single machine level version. A local installation, by contrast, keeps nodemon inside your project’s dependencies, ensuring teammates and CI environments use the exact same version, which improves reproducibility and avoids “works on my machine” issues, and that seems like a big win for team projects.

Troubleshooting PATH and Verifying Installation

After a global install, if the nodemon command is still not recognized, open a new terminal session so your shell reloads its PATH, or check that the global package directory is included in your environment’s PATH variable, just in case that path update did not stick. You can confirm availability at any time by running a quick version check such as nodemon -v , this helps make sure that your shell can find the executable before you proceed, which can save you a bit of head scratching later.

Everyday Development

When working with a local install, the provided direct path invocation ( ./node_modules/.bin/nodemon.js [your node app] ) guarantees that the project scoped binary runs even if the global command is unavailable, which is a nice safety net. For everyday development, it is often more convenient to call the local binary through package scripts, for example, by defining a dev script in package.json that invokes nodemon , or to rely on npx to resolve and execute the locally installed version automatically, which keeps your workflow smooth. Both approaches keep commands short while maintaining consistency across different environments, and they help everyone on the team run the same setup without extra effort.

What Nodemon Does

Finally, remember that nodemon itself does not change your application code or Node.js, it simply monitors your files and restarts your process when changes are detected, which is exactly what you want during active development. Ensuring that it is properly installed, discoverable by your shell, and version aligned with your team’s setup will make the rest of your workflow smoother and more predictable, and you will feel the difference as you iterate faster.

Explore installation methods, usage commands, and configuration in the nodemon official documentation.

Set up Express project with nodemon

Step 2, Setting Up an Example Express Project with nodemon , just so we are moving together with a clear plan.

You can use nodemon to start a Node script, and you will see it feels straightforward once you try it yourself.

In practice, nodemon works like a small helper that sits on top of the Node runtime: it launches your script, it keeps an eye on the file system for any changes, and it automatically restarts the process whenever a watched file is edited, which saves you from stopping and starting the app by hand over and over again.

For example, if you have an Express server set up in a server.js file, you can start nodemon and watch for changes like this:

$ nodemon server.js

and you can think of this as flipping on live monitoring for your app.

This command should run from your project’s root directory (where server.js lives), and nodemon will invoke Node under the hood to execute that file while enabling live reload behavior so your edits show up fast.

You can pass in arguments the same way as if you were running the script with Node :

$ nodemon server.js 3006

and that keeps the experience familiar. This means any additional values you include after the script name are forwarded to your application and can be accessed via process.argv inside your code, which is handy when you need quick flags or ports.

If you later add nodemon specific flags, remember that script arguments and nodemon options are different; nodemon forwards only the extra values that appear after the script path to your program, so keep that order in mind.

Every time you make a change to a file with one of the default watched extensions ( .js , .mjs , .json , .coffee , or .litcoffee ) in the current directory or a subdirectory, the process will restart, and that is the magic that keeps your feedback loop tight.

This default behavior covers most Node.js back end use cases; if you organize your code into nested folders, nodemon continues to monitor those subdirectories recursively, ensuring edits to route handlers, utility modules, or configuration files immediately trigger a restart.

Let’s write an example server.js file that outputs the message: Dolphin app listening on port ${port}! , and you will see the log message pop up when things are wired correctly.

const express = require(‘express’) const app = express() const port = 3000 app.listen(port, ()=> console.log(Dolphin app listening on port ${port}!))

This minimal server creates an Express application, binds it to a specific port, and prints a confirmation message once the app begins listening for incoming HTTP requests, so you know it is alive.

Run the example with nodemon :

$ nodemon server.js

and give it a try to see the automatic restarts in action. When you execute this command, nodemon starts your Node process and keeps it running in the foreground, watching for changes so you can iterate quickly without breaking your flow.

The terminal output will display the following output:

Output

Output
[nodemon] 2.0.15 [nodemon] to restart at any time, enter rs [nodemon] watching path(s): . [nodemon] watching extensions: js,mjs,json [nodemon] starting node server.js Dolphin app listening on port 3000!

Each line in this output shares useful status information: the installed nodemon version, the explicit hint for manual restarts using rs , the set of path patterns and file extensions being observed, the exact command nodemon is running behind the scenes, and finally the application’s own startup log confirming that your server is active, which is reassuring.

While nodemon is still running, let’s make a change to the server.js file, and we will watch what happens next. Change the output to a different message: Shark app listening on port ${port}! , and save the file to trigger a restart.

The terminal output will display the following output:

Output

Output
[nodemon] restarting due to changes… [nodemon] starting node server.js Shark app listening on port 3000!

This shows the automatic reload cycle at work: after you save the file, nodemon detects the change, it restarts the Node process cleanly, and your updated log line appears, which confirms the new code path is live without any extra commands. The terminal output from the Node.js app is displaying the new changes, so you can be pretty sure your edit landed.

You can restart the process at any time by typing rs and hitting ENTER, which is a quick way to reset things on demand. This manual trigger is helpful when you change environment variables or want to reset state without editing a file, and rs tells nodemon to perform an immediate, clean restart so you can get back to testing.

Alternatively, nodemon will also look for a main file specified in your project’s package.json file:

{ // … “main”: “server.js”, // … }

which gives it a clear entry point even if you do not pass a file on the command line. Here, the main field indicates the entry point of your application; if nodemon starts without an explicit file and it finds this field, it will use the specified path as the default script to run, which keeps things simple.

If a main file is not specified, nodemon will search for a start script:

package.json

{ // … “scripts”: { “start”: “node server.js” }, // … }

and that is another common and friendly convention. In this configuration, the scripts.start entry defines how your app is usually launched with the package manager; nodemon can notice this convention and use it to figure out the correct entry script when none is provided on the command line, which helps keep commands short.

Once you make the changes to package.json , you can then call nodemon to start the example app in watch mode without having to pass in server.js , which tidies things up. This makes your workflow more concise: running nodemon from the project root is enough, and it will figure out the right file to execute based on the main field or start script, letting you focus on coding rather than on typing the launch command each time, which feels nicer.

For a quick Express setup and hello world example, visit the Express Hello World guide.

Nodemon options and usage

Step 3, nodemon Options, you can change the configuration settings available to nodemon. This means you can shape how nodemon watches your project files, how it restarts your app, and which runner it uses to execute your code, all while leaving your actual application logic alone so you can focus on building. Let’s go over some of the main options, and we will keep it simple and clear.

  • --exec : Use the --exec switch to point to a binary that should run the file. For example, when you pair it with the ts-node binary, --exec becomes handy to watch for changes and run TypeScript files without extra steps. In practical terms, --exec swaps the default Node runtime for another compatible command, making sure that every automatic restart uses the exact toolchain you want, for example a TypeScript runtime during development.

  • --ext : Specify different file extensions to watch. For this switch, provide a comma separated list of file extensions, for example --ext js,ts . Customizing extensions helps when your project includes multiple source types, and by listing them clearly, you make sure nodemon restarts only when relevant files change, which boosts performance and cuts down on unnecessary restarts.

  • --delay : By default, nodemon waits for one second to restart the process when a file changes, but with the --delay switch, you can pick a different wait time. For example:

    $ nodemon –delay 3.2

    for a 3.2 second delay. A delay helps debounce rapid, successive file writes, for example those triggered by code formatters or build tools, so your server restarts once per change set instead of many times in quick bursts.

  • --watch : Use the --watch switch to specify multiple directories or files to watch. Add one --watch switch for each directory you want to watch. By default, the current directory and its subdirectories are watched, so with --watch you can narrow that to only specific subdirectories or files. Targeted watching is especially useful in monorepos or larger projects where you want to limit restarts to a small set of paths, which keeps the feedback loop fast.

  • --ignore : Use the --ignore switch to skip certain files, file patterns, or directories. Leaving out paths such as temporary build outputs or large dependency folders prevents needless restarts and helps reduce CPU usage during active development.

  • --verbose : A more detailed output with information about what file or files changed to trigger a restart. Verbose mode is helpful for figuring out why nodemon restarted, and it helps you check that your ignore and watch patterns are set up correctly.

You can view all the available options with the following command:

$ nodemon –help

When you run this help command, nodemon prints a comprehensive, version specific list of flags and defaults so you can quickly check behavior without leaving your terminal.

Using these options, let’s create the command to satisfy the following scenario, watching the server directory, specifying files with a .ts extension, ignoring files with a .test.ts suffix, executing the file ( server/server.ts ) with ts-node , waiting for three seconds to restart after a file changes,

$ nodemon –watch server –ext ts –exec ts-node –ignore ‘.test.ts’ –delay 3 server/server.ts

In this single command, --watch server limits observation to the server folder, --ext ts makes sure only TypeScript source changes trigger restarts, --exec ts-node runs the program with a TypeScript aware executor, --ignore '.test.ts' stops unit test updates from restarting the app, and --delay 3 slows restarts by three seconds to avoid thrashing during rapid edits.

The terminal output will display the following output,

Output
[nodemon] 2.0.15 [nodemon] to restart at any time, enter rs [nodemon] watching path(s): server [nodemon] watching extensions: ts [nodemon] starting ts-node server/server.ts

This output confirms the active configuration, it shows the installed nodemon version, it reminds you that typing rs forces a manual restart, it lists the exact paths and extensions being monitored, and it displays the precise command nodemon is running on each start.

This command combines --watch , --ext , --exec , --ignore , and --delay options to meet the conditions for our scenario. Bringing these options together gives you a predictable development loop where only meaningful changes in the specified TypeScript sources trigger controlled restarts, which improves productivity and keeps your runtime steady during development.

Explore flags, watch patterns, ignores, delays, and workflows in the Nodemon Usage and CLI Options.

Nodemon configuration (nodemon.json or package.json)

Step 4, nodemon Configurations, in the previous example, adding configuration switches when you run nodemon can get a bit tedious, you know. Repeatedly typing long command line flags increases the chance of typos, makes scripts harder to remember, and can lead to small differences between people’s environments that are easy to miss.

A better fix for projects that require complicated configurations is to define these options in a nodemon.json file so everything stays in one clear place. This file can live at the root of your project, it is easy to commit to version control, and it allows every teammate and any automation environment to rely on the same behavior without extra setup, which helps a lot.

For example, here are the same configurations as the previous command line example, but placed in a nodemon.json file:


{
  “watch”: [“server”],
  “ext”: “ts”,
  “ignore”: [“*.test.ts”],
  “delay”: “3”,
  “execMap”: {
    “ts”: “ts-node”
  }
}

This JSON mirrors the corresponding command line flags one to one: "watch" limits which folders trigger restarts, "ext" defines the file types to observe, "ignore" excludes patterns that would otherwise cause unnecessary reloads, and "delay" debounces rapid edits so restarts happen in a controlled way.

Take note of the use of execMap instead of the --exec switch, just to keep the idea clear. execMap lets you specify binaries for certain file extensions, which is helpful and straightforward. In practice, this means you can associate ".ts" files with a TypeScript-friendly executor such as "ts-node" so that any TypeScript entry point runs through the correct runtime during development, without having to remember to pass the --exec flag each time, which is a nice time saver.

This approach is especially helpful when different teams work with mixed file types since the execution mapping is captured in configuration rather than in ad hoc shell commands, which keeps things simple.

Alternatively, if you would rather not add a nodemon.json config file to your project, you can add these configurations to the package.json file under a nodemonConfig key:


{
  “name”: “nodemon-example”,
  “version”: “1.0.0”,
  “description”: “”,
  “nodemonConfig”: {
    “watch”: [“server”],
    “ext”: “ts”,
    “ignore”: [“*.test.ts”],
    “delay”: “3”,
    “execMap”: {
      “ts”: “ts-node”
    }
  },
  // …
}

Keeping configuration inside package.json can simplify project maintenance by centralizing settings in a single file that most developers already edit regularly, and that makes life easier. It also ensures your nodemon behavior travels with the project wherever package.json goes, for example in shared repositories or continuous integration systems, so everyone stays in sync.

Be sure that the JSON remains valid and that commas and brackets are correctly placed, since malformed JSON will prevent tools from reading it properly, and that can slow you down.

Once you make the changes to either nodemon.json or package.json , you can then start nodemon with the desired script:


$ nodemon server/server.ts

nodemon will pick up the configurations and use them, and you can check that quickly in the output. This way, your configurations can be saved, shared, and repeated to avoid copy and pasting or typing errors in the command line, which helps keep things tidy.

In practical day-to-day use, this means you launch nodemon with a short, memorable command while still benefiting from all the custom behavior defined in your configuration files; as your project grows, you can update these settings in one place to refine watch paths, add or remove extensions, or adjust delays without rewriting your CLI commands.

Learn how to structure nodemon.json and package.json settings in the Nodemon Config Files reference.

Conclusion

Nodemon makes local development faster by auto-restarting Node.js apps on save, and you now know how to install it, launch projects, and fine-tune watch, ignore, and delay settings through package.json or nodemon.json. Use nodemon to auto-restart Node.js on save for a faster dev loop.

Keep configurations versioned with your code, and adjust them as your stack evolves with TypeScript, ESM, and test runners. For larger services, consider pairing watch mode with logs, environment variables, and CI to keep feedback quick and reliable. As Node.js tooling advances, expect lighter file watchers and smarter reloads to make nodemon even more seamless in modern workflows.

Install and Use Yarn Package Manager with Node.js for Efficient Development (2025)

Caasify
Privacy Overview

This website uses cookies so that we can provide you with the best user experience possible. Cookie information is stored in your browser and performs functions such as recognising you when you return to our website and helping our team to understand which sections of the website you find most interesting and useful.