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.
npm install -g npm-check-updates
Output: added 1 package; ncu on PATH
pnpm add -g npm-check-updates
Output: added npm-check-updates globally
yarn global add npm-check-updates
Output: added npm-check-updates globally
bun add -g npm-check-updates
Output: installed npm-check-updates as a global tool
One-off run without installing:
npx npm-check-updates
Output: prints the upgrade table (does NOT modify package.json without -u).
Per-project install (preferred for CI parity):
npm install -D npm-check-updates
Output: added npm-check-updates to devDependencies
Verify:
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.xline. 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-updateson 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 areasyncpack— for monorepos; enforces consistent dep versions across packagespnpm update --latest— built into pnpm; same behaviour asncu -ufor pnpm-managed reposbun update --latest— built into Bun; rewritespackage.json(Bun 1.1+)renovate/dependabot— bot-driven version bumps via PRs; superset ofncufor CI workflowsupdates— minimalist alternative, fewer features and faster
Alternatives
| Tool | When to choose it |
|---|---|
npm outdated | Just look at what's outdated — no rewriting. Read-only. |
npm update | Patch updates within existing semver range. No major bumps. |
taze | Newer, faster startup, Bun-aware. Active development. |
syncpack | Monorepo dep-consistency enforcement, not pure upgrades. |
pnpm update --latest | If you're already on pnpm — built-in, no extra tool. |
bun update --latest | If you're on Bun — built-in. |
renovate | CI-driven PRs per dep, with config for grouping / scheduling. |
dependabot | GitHub-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
ncuwithout-udoesn't change anything. It just prints the upgrade table. New users sometimes runncu, see the report, runnpm install, and are confused nothing changed. You needncu -u(orncu --upgrade) to rewritepackage.json.ncu -udoes NOT runnpm install. Afterncu -uyourpackage.jsonis updated butnode_modulesand the lockfile aren't. Always follow withnpm install(or the equivalent for your package manager).- 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"afterncu -u. If you want to skip exact pins entirely, use--target minoror--reject. --workspacesflag is required for monorepos. Without it, only the rootpackage.jsonis scanned. With-ws, all workspacepackage.jsonfiles are upgraded uniformly.- 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--peerto make ncu consider peer constraints. ncu --filterand--rejectaccept 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.ncuqueries the npm registry per-package. Hundreds of deps mean hundreds of HTTP requests. The--concurrencyflag controls fan-out (default 8). Slower networks should use--registryto point at a closer mirror.- Custom registries / private packages.
ncureads.npmrcfor 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.
ncu --target minor
Output: prints the upgrade table — only minor/patch bumps suggested.
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:
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:
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
ncu --filter react,react-dom
Output: only consider react and react-dom.
ncu --reject "@types/*,eslint*"
Output: skip type packages and ESLint plugins; consider everything else.
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.
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:
ncu --doctor -u --doctorTest "npm run test:unit"
Output: uses npm run test:unit instead of the default npm test.
Bound the time:
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:
ncu --workspaces -u
Output: upgrades all workspace package.json files in lock-step. Same version pinned everywhere.
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):
{
"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.
Recommended workflow
- Branch first:
git checkout -b deps/ncu-$(date +%Y-%m-%d). - Run ncu:
ncu -u --target minor(or whatever target you chose). - Install:
npm install(or the equivalent). - Test:
npm test && npm run build. - Commit + PR: small, focused PR titled like
chore(deps): minor + patch upgrades 2026-05-31. - 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:
- 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 2halves the parallel registry queries; useful on cellular / corporate proxies. - Skip the deprecation-check pass. Newer ncu queries
npm deprecateinfo per package;--no-deprecatedskips it and is 2–3× faster. - Cache the report.
ncu --json > .ncu-report.jsonthen 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
.npmrcpoints to a slow proxy, ncu inherits that latency. Use--registryto 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.
| From | To | Likely changes (verify against the changelog) |
|---|---|---|
ncu@15 | ncu@16 | Node 18+ floor; ESM published as the primary entry. |
ncu@16 | ncu@17 | Tightened peer-dep handling; new --peer flag semantics; programmatic API renamed (upgrade → run). |
Recommended upgrade flow:
- Bump in a branch:
npm install -D npm-check-updates@latest(ornpm install -g). - Run
ncu(without-u) to verify the new version produces a sane report. - If you parse
--jsonoutput, re-check the schema — minor versions sometimes add fields. - Update any
.ncurcto match the new flag names.
ESM/CJS interop & bundling
ncu is a CLI; the interop concern is only relevant if you import it programmatically.
| Concern | Pattern |
|---|---|
| Programmatic ESM | import { run } from "npm-check-updates"; const upgraded = await run({ target: "minor", upgrade: true }); |
| Programmatic CJS | const { run } = require("npm-check-updates"); works on the CJS shim, but the team recommends ESM going forward. |
| No tree-shaking concern | It'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:
| Tool | Role |
|---|---|
syncpack | Cross-workspace dep alignment. Runs after ncu to enforce consistency. |
npm-check (different package) | Older interactive checker with prune support. Less maintained. |
npm-audit | Security advisory check. Pair with ncu — bump deps, then audit. |
taze | Cousin tool — similar concept, newer codebase. |
renovate | Bot version of ncu — opens per-dep PRs on a schedule. |
dependabot | GitHub-native bot. |
Testing & CI integration
Run as a periodic CI job
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
ncudoesn't run code. It queries the registry and edits a JSON file. The risk is what happens after —npm installof the upgraded deps runs install scripts, which can execute arbitrary code from those new package versions.- Pair with
npm auditpost-upgrade. Always runnpm auditafterncu -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.ncurcorpackage.jsoncomments. - Lockfile review. After
npm install, review the lockfile diff. A smallpackage.jsonchange can cascade into thousands of lockfile lines — most benign, occasionally suspicious (typo-squatted transitive dep). - Private registry credentials.
ncureads.npmrcand uses your auth tokens. If you logncuoutput, scrub auth tokens — though current versions don't print them by default. - Doctor-mode runs tests.
--doctorexecutesnpm testfor each candidate upgrade. If your test suite has side effects (e.g. hits real APIs),--doctorruns 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 timeouts — ECONNRESET, 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
ncufor unattended updates.ncuis still useful for one-off audits, but redundant for routine bumps. - You're on Bun or pnpm exclusively.
bun update --latestandpnpm update --latestdo the same job without an extra dep. - You need cross-workspace consistency, not just upgrades.
syncpackis 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 fixis the right tool there, notncu.
See also
- JavaScript: ncu — full CLI reference, flags, recipes
- JavaScript: npm —
npm outdated,npm update, the underlying registry - JavaScript: package-json — semver ranges, dependencies vs devDependencies
- Concept: api — npm registry HTTP API that ncu queries