What's Changed
@nestjs/cli is now a native ES module, and the major version is aligned with the Nest 12 release line. Alongside the ESM move, the CLI no longer bundles webpack: every bundler-related package is an optional peer dependency now, so a default install is substantially smaller and you pull in only the builder you actually use. There are also two new commands — nest upgrade and nest deploy.
ESM migration
The package is published as pure ESM ("type": "module", compiled with NodeNext). All internal imports carry explicit .js extensions and the build output is ESM-only.
For the common case this is invisible — nest is a binary, and it keeps running your CJS and ESM projects alike. It matters if you import the CLI's internals programmatically (custom builders, plugin harnesses, scripts that drive @nestjs/cli/lib/...): those imports now resolve to ESM.
webpack is no longer a dependency
webpack, fork-ts-checker-webpack-plugin, tsconfig-paths-webpack-plugin, and webpack-node-externals moved from dependencies to optional peer dependencies, joining @swc/cli and @swc/core.
If you build with tsc (the default) or with SWC, nothing changes. If you use --builder webpack (or "webpack": true in nest-cli.json), install the bundler yourself:
npm i -D webpack webpack-node-externals fork-ts-checker-webpack-plugin tsconfig-paths-webpack-pluginWhen a builder's peer dependency is missing, the CLI now reports the actual missing package name instead of surfacing the raw resolution error.
Rspack support
@rspack/core is supported as an optional peer dependency (^1.7.7 || ^2.1.10) and is the builder that nest new scaffolds into nest-cli.json for new projects.
--builder rspackonnest buildandnest start--rspackPath [path]to point at a custom Rspack config, mirroring--webpackPath- Source maps are enabled in the Rspack defaults
New: nest upgrade
A new command (aliased nest update) that runs the upgrade schematic to migrate a Nest v11 project to v12 — dependency bumps, tsconfig and nest-cli.json migrations, and codemods for @nestjs/config, GraphQL, and NATS. See the @nestjs/schematics release notes for what the migration itself does.
nest upgradeOptions: -d, --dry-run, -s, --skip-install, -t, --tag [tag] (use a dist-tag such as next instead of the default version ranges), -c, --collection [name], and --observe / --no-observe to answer the @nestjs/observe prompt up front.
New: nest deploy
Deploy an application to the cloud, powered by Mau. Every option is forwarded verbatim to mau deploy, so the command claims no flags of its own.
nest deployPath confinement for build output
Build output and clean-up paths are now confined to the project directory by default. Symlinks are resolved before writing, so a dist that is itself a symlink pointing outside the project no longer lets a write escape.
Monorepo layouts that legitimately emit outside the project root can opt back out:
{
"compilerOptions": {
"allowOutsidePaths": true
}
}Monorepo and asset handling
- Parallel builds —
nest build --all --parallel [concurrency]builds monorepo projects concurrently, with an optional concurrency limit. - Library assets —
compilerOptions.includeLibraryAssetspulls assets from libraries into an application build. - Watch-mode restarts — asset changes restart the application in watch mode, debounced so a burst of writes triggers one restart. The build now awaits watcher close, so it no longer races shutdown.
- Asset path stripping is aligned with the effective TypeScript
rootDir.
Compiler internals
globis gone. It is replaced by an internalfs-based helper built onminimatch, which is now a direct dependency. Symlink traversal depth matches the previous behaviour.- A recursive
fswatcher replaces chokidar in the SWC watch path. - SWC respects
tsconfigexcludes — excluded files are skipped both on build and in watch mode, and newly added files no longer inherit watch mode when transpiled. --emit-declarationsemits.d.tsfiles under the SWC builder;--no-type-checkoverrides the config-level setting.--silentsuppresses informational compiler logs.
Other improvements
- Bun is supported as a package manager and runner, detected from
bun.lock/bun.lockb. nest new --skip-testsscaffolds a project without testing files, and--observe/--no-observeanswers the@nestjs/observeprompt.nest generate --formatformats generated files with Prettier; theresourceschematic accepts--type <rest|graphql|microservice>and--crud [value].- Clearer failures: a non-zero exit on an invalid
--builder, a readable error for malformednest-cli.json, a--parallelvalue that is validated instead of looping forever, and an explicit message fromnest infowhen no@nestjs/*dependencies are declared. nest infoand terminal-width detection preferprocess.stdout.columnsover shelling out totput.- Plugin metadata emits
.jsextensions on dynamic imports undernodenextresolution. .tsbuildinfois removed whendeleteOutDiris set.
Toolchain
TypeScript 6 (~6.0.2), @angular-devkit/* 22, commander 15, @inquirer/prompts 8, ora 9, node-emoji 2, and chokidar 5. Internally the CLI moved from Jest to Vitest and from ESLint to oxlint. engines.node stays at >= 20.11.
See the migration guide for the full picture.