⚠️ Breaking changes & migration
1. Node.js 22+ required (#1844)
The minimum supported Node.js is now 22. Supported versions: ^22.22.2 || ^24.15.0 || >=26.0.0 (and npm >=10).
- Migration: Upgrade Node before installing. On older Node, stay on v22.x.
2. Pure ESM package — CJS build dropped, default export is now callable (#1916, #1894)
The package is now pure ESM (no more CommonJS build), and the default export is now callable directly. ncu.run() and ncu.defineConfig() still work as namespaced properties.
- Migration (ESM):
// before import * as ncu from 'npm-check-updates' const upgraded = await ncu.run({ /* ... */ }) // after import ncu from 'npm-check-updates' const upgraded = await ncu({ /* ... */ }) // ncu.run({...}) also still works
- Migration (CommonJS): Still usable via Node's native
require()of ESM (Node 22+), but the import shape changed:// before const ncu = require('npm-check-updates') // after const { default: ncu } = require('npm-check-updates') ncu({ /* ... */ }).then(upgraded => console.log(upgraded))
3. filterVersion / rejectVersion no longer accept a predicate function. Use filter / reject instead. (#1933)
These options now accept only a string, wildcard, glob, comma/space-delimited list, or /regex/. (CLI usage is unchanged — the CLI never supported functions.)
- Migration: If you passed a function to
filterVersion/rejectVersionin.ncurc.jsor via the module API, move it tofilter/rejectinstead. Those receive the package name and the parsed current version, so they can match on both:// before filterVersion: (name, semver) => !(name.startsWith('@myorg/') && +semver[0].major > 5) // after filter: (name, semver) => !(name.startsWith('@myorg/') && +semver[0].major > 5)
4. Output is now grouped by default (#1937)
--format now defaults to ["group"], so upgrades are grouped by major / minor / patch out of the box. This is a better default for most users.
- Migration: To get the old flat output, use:
The new
ncu --format no-group
no-prefix removes a value from the default list instead of replacing the whole list, so--format no-group,timedisables grouping while adding publish times.
5. --target semver now respects explicit upper bounds (#1920)
An explicit upper bound in a range is now preserved and never exceeded, e.g. ^9.5.0 <10 → ^9.7.0 <10 (previously the bound could be overrun). This can change which versions are selected for ranges with explicit upper bounds.
✨ Other improvements
- Native TypeScript loading (#1888), lazy-loaded
npm-registry-fetchfor faster startup (#1898), and reduced dependencies for a lighter install. - Numerous bug fixes: scoped-package 404s with encoded
@(#1923),--doctor+--errorLevel 2crash (#1900), registry settings ignored by--enginesNode/--ownerChanged(#1925), and YAML catalog preservation (#1922).
Full changelog: v22.2.9...v23.0.0