Skip to content

/commands/npm/npm-explain-why-package-installed

npm explain / npm ls PACKAGE: why is this package installed?

verified onenvironmentlocal · windows 10.0.26200 arm64 · GNU bash 5.3.15 (Git Bash) · 11.19.0updated
tool
npm
versions
npm 7+ (npm explain), npm ls: all versions
os
any

npm explain PACKAGE (alias npm why) prints every dependency path that caused PACKAGE to be installed, from the package up to your project, with the version range each parent requested. npm ls PACKAGE shows the same information as a tree from the root down. Use them to find out which direct dependency brings in a transitive package, for example before fixing a vulnerability report.

Example

The project depends only on chalk; color-name arrives through three levels of dependencies:

bash
npm init -y >/dev/null
npm install --silent --no-audit --no-fund chalk@4.1.2 >/dev/null 2>&1
echo "--- npm explain color-name"
npm explain color-name
echo "--- npm ls color-name"
npm ls color-name | tail -n +2

Output

--- npm explain color-name
color-name@1.1.4
node_modules/color-name
  color-name@"~1.1.4" from color-convert@2.0.1
  node_modules/color-convert
    color-convert@"^2.0.1" from ansi-styles@4.3.0
    node_modules/ansi-styles
      ansi-styles@"^4.1.0" from chalk@4.1.2
      node_modules/chalk
        chalk@"^4.1.2" from the root project
--- npm ls color-name
└─┬ chalk@4.1.2
  └─┬ ansi-styles@4.3.0
    └─┬ color-convert@2.0.1
      └── color-name@1.1.4

Read npm explain from top to bottom: color-name@1.1.4 is needed by color-convert@2.0.1 (which asked for ~1.1.4), which is needed by ansi-styles, which is needed by chalk, which the root project requires. On Windows npm ls draws the tree with ASCII characters as shown; on Linux and macOS it uses line-drawing characters.

Useful variants

CommandShows
npm explain PKGAll paths that require PKG, bottom-up, with requested ranges
npm ls PKGTree paths from the root to every installed copy of PKG
npm ls PKG --allSame, including deeper levels (npm ls without a name stops at depth 0)
npm ls --allThe whole dependency tree
npm ls PKG --jsonMachine-readable tree
npm explain node_modules/a/node_modules/PKGExplain one specific nested copy

Fixing what you find

  • Upgrade the direct dependency at the top of the chain, so it pulls a newer transitive version.
  • Or force a version of the transitive package with overrides in package.json (npm 8.3+):
package.json
{
  "overrides": {
    "color-name": "1.1.4"
  }
}

Sources