Migrate to RunxBuild and earn up to $50 in hosting credit on your first deposit.

Calculate your savings
unxBuild

npm list Global Packages: Seeing What You Installed and Cleaning It Up

Sean

Platform Writer

Aug 26, 2026
7 min read

npm list -g --depth=0 lists globally installed packages without their dependency trees. The --depth=0 is the part that matters — without it you get thousands of lines of transitive dependencies. Note that global packages live per Node version under nvm, so switching versions changes the answer.

npm list Global Packages: Seeing What You Installed and Cleaning It Up

Global packages accumulate. A CLI installed for one project two years ago, three versions of a scaffolding tool, and a package that shadows a command you actually want. This is how to see what is there, work out what is still needed, and remove the rest.

Table of contents

Listing what is installed

npm list -g --depth=0        # top-level global packages
npm ls -g --depth=0          # ls is an alias for list
npm list -g --depth=0 --json # machine-readable
npm list -g --long           # with descriptions

Typical output:

/usr/local/lib
├── [email protected]
├── [email protected]
├── [email protected]
└── [email protected]

That first line is the global root, and it is worth noting because it tells you which installation you are looking at.

npm root -g          # where global packages are installed
npm prefix -g        # the global prefix
npm bin -g           # where global binaries are linked (older npm)

For local project dependencies the same command without -g:

npm list --depth=0           # direct dependencies of this project
npm list --prod --depth=0    # excluding devDependencies
npm list some-package        # why is this installed, and which version

That last form is genuinely useful for tracing a transitive dependency — it prints the path through the tree that pulled the package in.

Version managers change the answer

This surprises people and it is the source of most “the package is installed but the command is not found” reports.

With nvm, global packages are installed per Node version:

nvm ls
node --version
npm root -g
# /home/you/.nvm/versions/node/v22.5.1/lib/node_modules

Switch to Node 20 and your globals from Node 22 are simply not there. That is deliberate isolation, and it means a global install is scoped to one runtime version.

nvm can carry them across when installing a new version:

nvm install 22 --reinstall-packages-from=20

To audit across versions, iterate:

for v in $(nvm ls --no-colors | grep -oE 'v[0-9]+\.[0-9]+\.[0-9]+'); do
  echo "=== $v"
  nvm exec "$v" npm list -g --depth=0 2>/dev/null
done

fnm and volta behave similarly. Volta in particular pins tools per project, which is a different and arguably better model — the tool version is recorded in package.json rather than depending on what is globally installed.

Updating and removing

npm outdated -g --depth=0     # what is out of date
npm update -g                 # update everything
npm update -g typescript      # update one
npm uninstall -g package-name # remove
npm rm -g package-name        # same thing

npm outdated -g --depth=0 is worth running occasionally. Global CLIs are frequently several major versions behind, because nothing prompts you to update them the way a project’s lockfile does.

Be cautious with a blanket npm update -g. It can move CLIs across major versions with breaking changes, and unlike a project there is no lockfile to roll back to. Update deliberately.

Auditing global packages for vulnerabilities is possible but limited:

cd $(npm root -g)/.. && npm audit

It works imperfectly because the global directory is not a normal project. Worth running; not worth relying on.

When a command is not found despite the package appearing in the list, the bin directory is not on your PATH:

npm bin -g
echo $PATH | tr ':' '\n' | grep -i node

Add the global bin directory to PATH in your shell profile if it is absent.

Installing globally less often

Most global installs are unnecessary now, and avoiding them removes a whole class of version-conflict problem.

npx runs a package without installing it:

npx create-react-app my-app
npx cowsay hello
npx --yes [email protected] --version   # a specific version, no install

For anything you run occasionally — scaffolding tools especially — this is strictly better. You get the current version, and nothing is left behind.

Project-local dev dependencies for anything a project needs:

npm install --save-dev typescript eslint prettier

npm scripts resolve node_modules/.bin automatically, so "build": "tsc" works with no global TypeScript. The advantage is that the version is recorded in the lockfile, so every developer and the CI build use the same one — which a global install cannot guarantee.

The remaining legitimate cases for a global install are genuinely small:

  • Tools used constantly and independently of any project — a deployment CLI, pm2.
  • npm and corepack themselves.
  • Something whose startup cost through npx is annoying at the frequency you use it.

If a tool is used by a project, it belongs in that project’s devDependencies. The version mismatch between a developer’s global install and CI’s is a real and recurring source of “works on my machine”.

Permission errors, and not fixing them with sudo

EACCES on a global install means npm’s default prefix is a directory you do not own:

npm ERR! Error: EACCES: permission denied, access '/usr/local/lib/node_modules'

The common response is sudo npm install -g, which works and creates problems. Root-owned files appear in your cache and config, subsequent non-sudo commands fail on them, and any install script in the package runs as root.

The correct fix is a global prefix in your home directory:

mkdir -p ~/.npm-global
npm config set prefix ~/.npm-global
echo 'export PATH=~/.npm-global/bin:$PATH' >> ~/.profile
source ~/.profile

Global installs now need no elevation and nothing root-owned ends up in your home directory.

Better still, use a version manager. nvm, fnm and volta all place Node and its global packages under your home directory by default, so the permission problem never arises. That is the reason most guides recommend a version manager even for people who only ever use one Node version.

How this fits the rest of the stack

Global packages are convenient and they are also state on one machine that nothing records. A build that depends on a globally installed CLI works for whoever installed it and fails for everyone else, which is the same failure mode as a shell alias nobody else has.

The fix is to put the dependency in the project, where the lockfile pins it and every environment resolves the same version. RunxBuild builds Node services and static sites from your repository, installing from the lockfile with a build log per deploy — so what the build used is recorded rather than inherited from a machine. The RunxBuild hosting calculator shows the service, database and bandwidth as separate figures.

Useful related references:

FAQ

How do I list globally installed npm packages?

npm list -g --depth=0. The depth flag is essential — without it npm prints the full dependency tree of every global package, which runs to thousands of lines. Add --json for machine-readable output.

Why are my global packages missing after switching Node versions?

Version managers such as nvm install global packages per Node version, so switching runtimes changes which globals exist. Use nvm install 22 --reinstall-packages-from=20 to carry them across, or check npm root -g to see which installation you are looking at.

Should I install packages globally or use npx?

Use npx for anything you run occasionally — you get the current version and nothing is left behind. Use project devDependencies for anything a project needs, so the version is pinned in the lockfile. Reserve global installs for tools used constantly and independently of any project.

How do I fix npm EACCES permission errors?

Do not use sudo — it leaves root-owned files in your cache and runs install scripts as root. Set a global prefix in your home directory with npm config set prefix ~/.npm-global and add its bin to PATH, or use a version manager, which avoids the problem entirely.

Why is a globally installed command not found?

The global bin directory is not on your PATH. Check where it is with npm bin -g or npm root -g, then confirm with echo $PATH. Add it in your shell profile if missing. Under a version manager, also confirm you are on the Node version you installed it under.

#npm list global packages#npm#node.js#package management#cli