cheat sheet

npm-check-updates

Package-level reference for npm-check-updates on npm — install, Node support, the ncu binary, doctor mode, workspaces, and where it fits next to npm outdated, taze, and bun update.

npm-check-updates

What it is

npm-check-updates is a CLI that scans your package.json for dependency versions and rewrites them to the latest available — within or beyond the existing semver range. The CLI binary is ncu. Unlike npm update, which respects the ^/~ caret/tilde ranges already pinned in package.json, ncu rewrites the file itself, including across major versions if you ask. After it edits package.json, you still run npm install (or pnpm install / yarn install / bun install) to apply the changes.

Reach for ncu when you want a deliberate batch dependency refresh — quarterly cleanup, post-incident triage, or pre-LTS-cutover audit. For day-to-day patching, npm update (or pnpm update) is usually enough. The alternatives — npm outdated + manual editing, Renovate / Dependabot bots, taze, pnpm update --latest, bun update --latest — overlap with ncu to different degrees; ncu is the most established "edit package.json in place" tool.

Install

npm-check-updates is a CLI. Install globally for ad-hoc use; per-project keeps the version pinned to your CI.

bash
npm install -g npm-check-updates

Output: added 1 package; ncu on PATH

bash
pnpm add -g npm-check-updates

Output: added npm-check-updates globally

bash
yarn global add npm-check-updates

Output: added npm-check-updates globally

bash
bun add -g npm-check-updates

Output: installed npm-check-updates as a global tool

One-off run without installing:

bash
npx npm-check-updates

Output: prints the upgrade table (does NOT modify package.json without -u).

Per-project install (preferred for CI parity):

bash
npm install -D npm-check-updates

Output: added npm-check-updates to devDependencies

Verify:

bash
ncu --version

Output: prints installed ncu version (currently the 17.x line — hedge against drift)

Versioning & Node support

Current line is npm-check-updates@17.x (2026). Releases roughly every 1–2 weeks, mostly tracking npm registry behaviour and bug fixes.

  • Node 18.18+ required on the 17.x line. Older majors supported Node 14/16.
  • ESM-first since 17.x — the package exports an ESM entrypoint. CJS shims are still published for legacy programmatic use, but the CLI is ESM.
  • TypeScript types ship for the programmatic API (import { run } from "npm-check-updates").
  • Semver is followed but the output formatting and default behaviours (e.g. how peer deps are reported) drift across minors — pin if you parse the output.

Package metadata

  • Maintainer: Raine Revere (raineorshine/npm-check-updates on GitHub) + community
  • Project home: github.com/raineorshine/npm-check-updates
  • Docs: github.com/raineorshine/npm-check-updates#readme
  • npm: npmjs.com/package/npm-check-updates
  • License: Apache-2.0
  • First released: 2013 (one of the oldest tools in this niche)
  • Downloads: ~2–3 million weekly — among the most-installed dev tools on npm.

Peer dependencies & extras

npm-check-updates declares no peer dependencies. It is self-contained but heavy: pulls in ~30–50 transitive packages including semver, ini (for npmrc parsing), chalk, prompts (for interactive mode), cli-table, and various registry-query helpers (fast-memoize, pacote).

Companion packages / cousin tools (use one, not several):

  • taze — newer Bun-friendly alternative with similar surface area
  • syncpack — for monorepos; enforces consistent dep versions across packages
  • pnpm update --latest — built into pnpm; same behaviour as ncu -u for pnpm-managed repos
  • bun update --latest — built into Bun; rewrites package.json (Bun 1.1+)
  • renovate / dependabot — bot-driven version bumps via PRs; superset of ncu for CI workflows
  • updates — minimalist alternative, fewer features and faster

Alternatives

ToolWhen to choose it
npm outdatedJust look at what's outdated — no rewriting. Read-only.
npm updatePatch updates within existing semver range. No major bumps.
tazeNewer, faster startup, Bun-aware. Active development.
syncpackMonorepo dep-consistency enforcement, not pure upgrades.
pnpm update --latestIf you're already on pnpm — built-in, no extra tool.
bun update --latestIf you're on Bun — built-in.
renovateCI-driven PRs per dep, with config for grouping / scheduling.
dependabotGitHub-native version of renovate.

ncu remains popular because it works across npm / pnpm / yarn / bun lockfiles uniformly, has a long history, and the -i interactive mode and --doctor rollback flow are genuinely useful patterns that competitors copy.

Common gotchas

  1. ncu without -u doesn't change anything. It just prints the upgrade table. New users sometimes run ncu, see the report, run npm install, and are confused nothing changed. You need ncu -u (or ncu --upgrade) to rewrite package.json.
  2. ncu -u does NOT run npm install. After ncu -u your package.json is updated but node_modules and the lockfile aren't. Always follow with npm install (or the equivalent for your package manager).
  3. Pinned versions (no ^ or ~) are preserved by default but still bumped. A "react": "18.2.0" stays an exact pin but becomes "19.0.0" after ncu -u. If you want to skip exact pins entirely, use --target minor or --reject.
  4. --workspaces flag is required for monorepos. Without it, only the root package.json is scanned. With -ws, all workspace package.json files are upgraded uniformly.
  5. Peer-dep warnings on install != broken upgrade. After ncu -u && npm install, you'll often see peer-dep warnings (e.g. React 19 incompatible with X). They're warnings — actual breakage shows up in your test suite. Use --peer to make ncu consider peer constraints.
  6. ncu --filter and --reject accept glob OR regex. A bare string is treated as a substring match. /^@types\// is a regex (slashes mark it). Confusion here leads to "why didn't it match @types/*?" reports.
  7. ncu queries the npm registry per-package. Hundreds of deps mean hundreds of HTTP requests. The --concurrency flag controls fan-out (default 8). Slower networks should use --registry to point at a closer mirror.
  8. Custom registries / private packages. ncu reads .npmrc for registry + auth. If a private registry isn't configured, those packages silently skip with a warning. Always re-check the report.

Real-world recipes

Minor + patch upgrade (safe)

The safest mode — upgrade within existing semver ranges only.

bash
ncu --target minor

Output: prints the upgrade table — only minor/patch bumps suggested.

bash
ncu --target minor -u

Output: rewrites package.json with the bumped versions. Follow with npm install.

Use this monthly without much risk — minor versions are supposed to be backward compatible.

Major upgrade with interactive selection

When you want to do a bigger refresh, review each major bump:

bash
ncu -i

Output: opens an interactive multi-select prompt. Use space to toggle, a to select all, enter to confirm. Then it rewrites package.json for the chosen subset.

Combine with filters:

bash
ncu -i --filter "/^@types\//"            # only @types/* packages
ncu -i --filter "react,react-dom,next"   # one app, react ecosystem

Output: narrows the interactive prompt to matching packages.

Per-package filter / reject

bash
ncu --filter react,react-dom

Output: only consider react and react-dom.

bash
ncu --reject "@types/*,eslint*"

Output: skip type packages and ESLint plugins; consider everything else.

bash
ncu --reject "/^@radix-ui\//" --target minor

Output: keep Radix UI locked, bump everything else minor-only.

Doctor mode (try-then-rollback)

--doctor performs the upgrade per-package, runs npm install && npm test after each, and rolls back individual packages whose upgrade breaks tests.

bash
ncu --doctor -u

Output: for each candidate upgrade, prints "trying X→Y", runs install + test, then commits or reverts. Slow for many packages — typically 30–120 seconds per dep — but invaluable for unattended upgrades.

Override the test command:

bash
ncu --doctor -u --doctorTest "npm run test:unit"

Output: uses npm run test:unit instead of the default npm test.

Bound the time:

bash
ncu --doctor -u --doctorInstall "npm ci"

Output: uses npm ci for installs (faster than npm install if the lockfile is valid).

Workspaces support

For monorepos with workspaces: in the root package.json:

bash
ncu --workspaces -u

Output: upgrades all workspace package.json files in lock-step. Same version pinned everywhere.

bash
ncu --workspaces --root

Output: also upgrades the root package.json (the root itself is excluded by default).

For pnpm workspaces, the syntax is the same — ncu reads pnpm-workspace.yaml automatically.

Configuration file

For long-term repos, lock the policy in .ncurc.json (or .ncurc.yaml, .ncurc.js):

json
{
  "target": "minor",
  "reject": ["@types/*", "eslint*", "react", "react-dom"],
  "workspaces": true
}

Then bare ncu -u uses these defaults — no need to remember the flags.

Production deployment

ncu is a build-time / dev-time tool. It does not run in production. The "deployment" concern is whether to bump deps before committing for CI vs after as a separate PR.

  1. Branch first: git checkout -b deps/ncu-$(date +%Y-%m-%d).
  2. Run ncu: ncu -u --target minor (or whatever target you chose).
  3. Install: npm install (or the equivalent).
  4. Test: npm test && npm run build.
  5. Commit + PR: small, focused PR titled like chore(deps): minor + patch upgrades 2026-05-31.
  6. Merge: once CI passes.

For majors, do a separate PR per ecosystem (one for React, one for ESLint, etc.) so a regression isolates which dep caused it.

CI-driven version bumps

Renovate and Dependabot supersede ncu for fully-automated PRs. ncu --doctor in CI can be a middle ground — run it on a schedule, open one PR with the doctor-survived upgrades:

yaml
- run: ncu --doctor -u --doctorTest "npm test"
- run: |
    if [ -n "$(git diff --name-only)" ]; then
      git checkout -b deps/auto-$(date +%Y-%m-%d)
      git commit -am "chore(deps): doctor-mode upgrades"
      gh pr create --fill
    fi

Performance tuning

  • Reduce concurrency on slow networks. --concurrency 2 halves the parallel registry queries; useful on cellular / corporate proxies.
  • Skip the deprecation-check pass. Newer ncu queries npm deprecate info per package; --no-deprecated skips it and is 2–3× faster.
  • Cache the report. ncu --json > .ncu-report.json then parse the JSON with a script — avoids re-querying the registry.
  • Workspaces are slow. Each workspace package = separate registry queries. For huge monorepos, run ncu per package only when actively bumping that package.
  • Private registry latency. If .npmrc points to a slow proxy, ncu inherits that latency. Use --registry to override for a one-off run.

Version migration guide

ncu has been stable for over a decade — the major bumps mostly change Node floors and output formatting. Check the official changelog for breaking changes specific to your jump.

FromToLikely changes (verify against the changelog)
ncu@15ncu@16Node 18+ floor; ESM published as the primary entry.
ncu@16ncu@17Tightened peer-dep handling; new --peer flag semantics; programmatic API renamed (upgraderun).

Recommended upgrade flow:

  1. Bump in a branch: npm install -D npm-check-updates@latest (or npm install -g).
  2. Run ncu (without -u) to verify the new version produces a sane report.
  3. If you parse --json output, re-check the schema — minor versions sometimes add fields.
  4. Update any .ncurc to match the new flag names.

ESM/CJS interop & bundling

ncu is a CLI; the interop concern is only relevant if you import it programmatically.

ConcernPattern
Programmatic ESMimport { run } from "npm-check-updates"; const upgraded = await run({ target: "minor", upgrade: true });
Programmatic CJSconst { run } = require("npm-check-updates"); works on the CJS shim, but the team recommends ESM going forward.
No tree-shaking concernIt's a CLI — the whole tool runs in one process.

Plugin & ecosystem coverage

ncu has no plugin system. The "ecosystem" is the related tools that complement it:

ToolRole
syncpackCross-workspace dep alignment. Runs after ncu to enforce consistency.
npm-check (different package)Older interactive checker with prune support. Less maintained.
npm-auditSecurity advisory check. Pair with ncu — bump deps, then audit.
tazeCousin tool — similar concept, newer codebase.
renovateBot version of ncu — opens per-dep PRs on a schedule.
dependabotGitHub-native bot.

Testing & CI integration

Run as a periodic CI job

yaml
name: Weekly dep refresh
on:
  schedule:
    - cron: "0 7 * * 1"  # Monday 07:00 UTC
  workflow_dispatch:

jobs:
  bump:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with: { node-version: 22 }
      - run: npm ci
      - run: npx npm-check-updates --target minor -u
      - run: npm install
      - run: npm test
      - run: npm run build
      - uses: peter-evans/create-pull-request@v6
        with:
          branch: deps/auto-$(date +%Y-%m-%d)
          title: "chore(deps): weekly minor + patch upgrades"

Run in pretest hook

For solo projects, "pretest": "ncu --errorLevel 2" fails CI if any dep is outdated by more than the configured target. Heavy-handed but works for tiny libs.

Security considerations

  • ncu doesn't run code. It queries the registry and edits a JSON file. The risk is what happens afternpm install of the upgraded deps runs install scripts, which can execute arbitrary code from those new package versions.
  • Pair with npm audit post-upgrade. Always run npm audit after ncu -u && npm install — security fixes from the upgrade are the goal; verify the fix landed.
  • Pinned majors for a reason. Some deps are pinned to a specific major because of an internal patch / known regression. A blanket ncu -u (without --reject) defeats the pin. Document the reason in .ncurc or package.json comments.
  • Lockfile review. After npm install, review the lockfile diff. A small package.json change can cascade into thousands of lockfile lines — most benign, occasionally suspicious (typo-squatted transitive dep).
  • Private registry credentials. ncu reads .npmrc and uses your auth tokens. If you log ncu output, scrub auth tokens — though current versions don't print them by default.
  • Doctor-mode runs tests. --doctor executes npm test for each candidate upgrade. If your test suite has side effects (e.g. hits real APIs), --doctor runs them dozens of times. Use a sandboxed test target.

Troubleshooting common errors

No upgrades — your deps are already at target. Try --target latest for cross-major suggestions.

Error: Cannot find module 'npm-check-updates' — installed globally on a different Node version. Reinstall with the active Node.

No package file found — running from a directory without package.json. cd to the project root.

Error: Could not find a package.json file matching the workspace pattern — workspace glob in root package.json doesn't match any subfolder. Verify the workspaces field.

Doctor mode failed — your npm test failed for a candidate. Ncu rolls back that specific upgrade and continues. If everything fails, ensure npm test works on a clean install first.

Network timeoutsECONNRESET, ETIMEDOUT. Lower --concurrency; check .npmrc for a corporate proxy.

Peer-dep conflicts after npm install — npm 7+ enforces peer deps by default. Pass --legacy-peer-deps to npm install if you accept the warning (and pin your tests).

@types/* not bumping — they're often capped by the source library's types. --target latest and check the report for an explicit reason.

Private package skipped silently.npmrc registry / auth missing. npm whoami --registry=<url> to verify auth.

When NOT to use this

Skip ncu when:

  • You already use Renovate or Dependabot. They open per-dep PRs and supersede ncu for unattended updates. ncu is still useful for one-off audits, but redundant for routine bumps.
  • You're on Bun or pnpm exclusively. bun update --latest and pnpm update --latest do the same job without an extra dep.
  • You need cross-workspace consistency, not just upgrades. syncpack is the right tool — it ensures every workspace pins the same React version, regardless of "latest".
  • The deps are tightly version-pinned for a reason. Plugin ecosystems (Vue 2, older Angular, frozen LTS branches) actively rely on specific dep versions. Blanket upgrades break them.
  • You're in a "do not touch deps without security advisory" environment. Some regulated codebases only bump deps in response to CVEs. npm audit fix is the right tool there, not ncu.

See also