npm global packages are just regular npm packages, but instead of being installed locally within a project’s node_modules directory, they’re installed in a central, system-wide location. This makes their executables available on your system’s PATH, so you can run them directly from any directory in your terminal.

Let’s see it in action. Imagine you want to use http-server to quickly spin up a web server for static files.

First, you install it globally:

npm install -g http-server

The -g flag is the magic. It tells npm to put http-server in that system-wide location. Now, from anywhere in your terminal, you can run it:

http-server . --port 8080

This command starts a server in the current directory (.) and listens on port 8080. You’ll see output like this:

Available on:
  http://192.168.1.100:8080
  http://127.0.0.1:8080
Hit CTRL-C to stop

The beauty here is that http-server isn’t tied to any specific project. You can use it for any project, or no project at all, just by having it installed globally.

This system solves the problem of having to install common CLI utilities repeatedly for every project, or worse, relying on system-installed versions that might be outdated or incompatible with your Node.js environment. It provides a consistent, project-agnostic way to access developer tools.

Internally, npm maintains a global directory for packages and another for executables. When you install globally, npm places the package’s code in its global node_modules folder and creates symbolic links to the executables in a directory that’s part of your system’s PATH. This is why you can run http-server without typing node_modules/.bin/http-server or specifying its full path.

The exact location of these global directories can vary by operating system and npm configuration. You can find them using:

npm root -g
npm bin -g

The first command shows where global packages are installed, and the second shows where the executables (symlinks) are placed. On macOS and Linux, npm root -g often points to /usr/local/lib/node_modules and npm bin -g to /usr/local/bin. On Windows, it might be something like C:\Users\<YourUsername>\AppData\Roaming\npm\node_modules and C:\Users\<YourUsername>\AppData\Roaming\npm.

When you install a package globally, npm adds its executable’s directory to your PATH environment variable. This is why the commands become available system-wide. If you ever find a global command isn’t working, the first thing to check is if the output of npm bin -g is actually in your PATH.

A common point of confusion is when you have multiple Node.js versions installed (e.g., via nvm). Each Node.js version managed by nvm has its own set of global packages. When you switch Node.js versions with nvm use <version>, you’re also switching to that version’s isolated set of global packages. This prevents conflicts and allows you to have different toolchains for different Node.js environments.

You can list all your globally installed packages with npm list -g --depth=0. The --depth=0 flag prevents npm from listing every single dependency of your global packages, giving you a clean list of the top-level tools you’ve installed.

To update a global package, you use the same install command, but npm will fetch the latest version. For example, to update http-server:

npm update -g http-server

If you want to remove a global package and its associated executable, you use the uninstall command:

npm uninstall -g http-server

This removes the package from the global node_modules directory and unlinks its executables.

The most surprising thing about global packages is how their executables are made available. It’s not that the package code itself is magically accessible everywhere, but rather that npm, upon global installation, creates symbolic links (symlinks) pointing to the executables within the global package directory. These symlinks are placed in a directory that is already listed in your system’s PATH environment variable. So, when you type a command like http-server, your shell searches through the directories in your PATH and finds the symlink, which then points to the actual executable script within the global node_modules structure.

The next step is understanding how to manage different versions of Node.js and their associated global packages.

Want structured learning?

Take the full Npm course →