Major Changes
Store
- Runtime dependencies are always linked from the global virtual store #10233.
- Optimized index file format to store the hash algorithm once per file instead of repeating it for every file entry. Each file entry now stores only the hex digest instead of the full integrity string (
<algo>-<digest>). Using hex format improves performance since file paths in the content-addressable store use hex representation, eliminating base64-to-hex conversion during path lookups. - Store version bumped to v11.
- Store the bundled manifest (name, version, bin, engines, scripts, etc.) directly in the package index file, eliminating the need to read
package.jsonfrom the content-addressable store during resolution and installation. This reduces I/O and speeds up repeat installs #10473. - Use SQLite for storing package index in the content-addressable store. Instead of individual JSON files under
$STORE/index/, package metadata is now stored in a single SQLite database at$STORE/index.dbwith MessagePack-encoded values. This reduces filesystem syscall overhead, improves space efficiency for small metadata entries, and enables concurrent access via SQLite's WAL mode. Packages missing from the new index are re-fetched on demand #10500 #10826.
Global Packages
-
Global installs (
pnpm add -g pkg) andpnpm dlxnow use the global virtual store by default. Packages are stored at{storeDir}/linksinstead of per-project.pnpmdirectories. This can be disabled by settingenableGlobalVirtualStore: false#10694. -
Isolated global packages. Each globally installed package (or group of packages installed together) now gets its own isolated installation directory with its own
package.json,node_modules/, and lockfile. This prevents global packages from interfering with each other through peer dependency conflicts, hoisting changes, or version resolution shifts.Key changes:
pnpm add -g <pkg>creates an isolated installation in{pnpmHomeDir}/global/v11/{hash}/pnpm remove -g <pkg>removes the entire installation group containing the packagepnpm update -g [pkg]re-installs packages in new isolated directoriespnpm list -gscans isolated directories to show all installed global packagespnpm install -g(no args) is no longer supported; usepnpm add -g <pkg>instead
Configuration
-
Changed default values:
optimisticRepeatInstallis nowtrueandverifyDepsBeforeRunis nowinstall. -
pnpm config get(without--json) no longer print INI formatted text.
Instead, it would print JSON for both objects and arrays and raw string for
strings, numbers, booleans, and nulls.
pnpm config get --jsonwould still print all types of values as JSON like before. -
pnpm config get <array>now prints a JSON array. -
pnpm config listnow prints a JSON object instead of INI formatted text. -
pnpm config listandpnpm config get(without argument) now hide auth-related settings. -
pnpm config listandpnpm config get(without argument) now show top-level keys as camelCase.
Exception: Keys that start with@or//would be preserved (their cases don't change). -
pnpm config getandpnpm config listno longer load non camelCase options from the workspace manifest (pnpm-workspace.yaml). -
pnpm no longer loads non-auth and non-registry settings from rc files. Other settings must be defined in
pnpm-workspace.yaml. -
Replace workspace project specific
.npmrcwithpackageConfigsinpnpm-workspace.yaml.A workspace manifest with
packageConfigswould look something like this:# File: pnpm-workspace.yaml packages: - "packages/project-1" - "packages/project-2" packageConfigs: "project-1": saveExact: true "project-2": savePrefix: "~"
Or this:
# File: pnpm-workspace.yaml packages: - "packages/project-1" - "packages/project-2" packageConfigs: - match: ["project-1", "project-2"] modulesDir: "node_modules" saveExact: true
Lockfile
- Simplified
patchedDependencieslockfile format fromRecord<string, { path: string, hash: string }>toRecord<string, string>(selector to hash). Existing lockfiles with the old format are automatically migrated #10911.
Other
-
This package is now pure ESM.
-
Node.js v18, 19, 20, and 21 support discontinued.
-
The standalone exe version of pnpm requires at least glibc 2.27.
-
strictDepBuildsistrueby default. -
blockExoticSubdepsistrueby default. -
Remove deprecated build dependency settings:
onlyBuiltDependencies,onlyBuiltDependenciesFile,neverBuiltDependencies, andignoredBuiltDependencies.Use the
allowBuildssetting instead. It is a map where keys are package name patterns and values are booleans:truemeans the package is allowed to run build scriptsfalsemeans the package is explicitly denied from running build scripts
Same as before, by default, none of the packages in the dependencies are allowed to run scripts. If a package has postinstall scripts and it isn't declared in
allowBuilds, an error is printed.Before:
onlyBuiltDependencies: - electron onlyBuiltDependenciesFile: "allowed-builds.json" neverBuiltDependencies: - core-js ignoredBuiltDependencies: - esbuild
After:
allowBuilds: electron: true core-js: false esbuild: false
-
Removed the deprecated
allowNonAppliedPatchescompletely in favor ofallowUnusedPatches.
RemoveignorePatchFailuresso all patch application failures should throw an error. -
Removed the
pnpm servercommand #10463. -
Removed support for the
useNodeVersionandexecutionEnv.nodeVersionfields.devEngines.runtimeandengines.runtimeshould be used instead #10373. -
Removed support for
hooks.fetchers. We now have a new API for custom fetchers and resolvers via thefetchersfield ofpnpmfile. -
The default value of the
typefield in thepackage.jsonfile of the project initialized bypnpm initcommand has been changed tomodule. -
Support lowercase options in
pnpm add:-d,-p,-o,-e#9197.When using
pnpm addcommand only:-pis now an alias for--save-prodinstead of--parseable-dis now an alias for--save-devinstead of--loglevel=info
-
pnpm publishnow works without thenpmCLI.The One-time Password feature now reads from
PNPM_CONFIG_OTPinstead ofNPM_CONFIG_OTP:export PNPM_CONFIG_OTP='<your OTP here>' pnpm publish --no-git-checks
If the registry requests OTP and the user has not provided it via the
PNPM_CONFIG_OTPenvironment variable or the--otpflag, pnpm will prompt the user directly for an OTP code.If the registry requests web-based authentication, pnpm will print a scannable QR code along with the URL.
Since the new
pnpm publishno longer callsnpm publish, some undocumented features may have been unknowingly dropped. If you rely on a feature that is now gone, please open an issue at https://github.com/pnpm/pnpm/issues. In the meantime, you can usepnpm pack && npm publish *.tgzas a workaround. -
pnpm no longer reads settings from the
pnpmfield ofpackage.json. Settings should be defined inpnpm-workspace.yaml#10086. -
Breaking changes to
pnpm link:pnpm link <pkg-name>no longer resolves packages from the global store. Only relative or absolute paths are accepted. For example, usepnpm link ./fooinstead ofpnpm link foo.pnpm link --globalis removed. Usepnpm add -g .to register a local package's bins globally.pnpm link(no arguments) is removed. Usepnpm link <dir>with an explicit path instead.
-
Do not exclude the root workspace project, when it is explicitly selected via a filter #10465.
Minor Changes
New Commands
- Added
pnpm sbomcommand for generating Software Bill of Materials in CycloneDX 1.7 and SPDX 2.3 JSON formats #9088. - Added
pnpm cleancommand that safely removesnode_modulesdirectories from all workspace projects #10707. Use--lockfileto also removepnpm-lock.yamlfiles. - Added a new command
pnpm runtime set <runtime name> <runtime version spec> [-g]for installing runtimes. Deprecatedpnpm env usein favor of the new command. - Add the ability to fix vulnerabilities by updating packages in the lockfile instead of adding overrides. Use
pnpm audit --fix=update#10341.
Configuration
-
Add support for a global YAML config file named
config.yaml.Now configurations are divided into 2 categories:
- Registry and auth settings which can be stored in INI files such as global
rcand local.npmrc. - pnpm-specific settings which can only be loaded from YAML files such as global
config.yamland localpnpm-workspace.yaml.
- Registry and auth settings which can be stored in INI files such as global
-
Load environment variables whose names start with
pnpm_config_into config. These environment variables override settings frompnpm-workspace.yamlbut not the CLI arguments. -
Support reading
allowBuildsfrompnpm-workspace.yamlin the global package directory for global installs. -
Added support for
pnpm config get globalconfigto retrieve the global config file path #9977. -
Added a new setting
virtualStoreOnlythat populates the virtual store without creating importer symlinks, hoisting, bin links, or running lifecycle scripts. This is useful for pre-populating a store (e.g., in Nix builds) without creating unnecessary project-level artifacts.pnpm fetchnow uses this mode internally #10840. -
Support specifying the pnpm version via
devEngines.packageManagerinpackage.json. Unlike thepackageManagerfield, this supports version ranges. The resolved version is stored inpnpm-lock.yamland reused if it still satisfies the range #10932. -
Config dependencies are now installed into the global virtual store (
{storeDir}/links/) and symlinked intonode_modules/.pnpm-config/. This allows config dependencies to be shared across projects that use the same store, avoiding redundant fetches and imports #10910. -
Store config dependency and package manager integrity info in
pnpm-lock.yamlinstead of inlining it inpnpm-workspace.yaml. The workspace manifest now contains only clean version specifiers forconfigDependencies, while the resolved versions, integrity hashes, and tarball URLs are recorded in the lockfile as a separate YAML document. The env lockfile section also storespackageManagerDependenciesresolved during version switching and self-update. Projects using the old inline-hash format are automatically migrated on install #10912 #10964.
Store
- When the global virtual store is enabled, packages that are not allowed to build (and don't transitively depend on packages that are) now get hashes that don't include the engine name (platform, architecture, Node.js major version). This means ~95% of packages in the GVS survive Node.js upgrades and architecture changes without re-import #10837.
Hooks & Pnpmfiles
- Added support for pnpmfiles written in ESM. They should have the
.mjsextension:.pnpmfile.mjs#9730. - Support
.pnpmfile.mjsas the default pnpmfile. When.pnpmfile.mjsexists, it takes priority over.pnpmfile.cjsand only one is loaded.
CLI & Other
- Added
-Fas a short alias for the--filteroption.
Patch Changes
-
Check if a package is installable for non npm-hosted packages (e.g., git or tarball dependencies) after the manifest has been fetched.
-
Explicitly tell
npmthe path to the globalrcconfig file. -
Fix YAML formatting preservation in
pnpm-workspace.yamlwhen running commands likepnpm update. Previously, quotes and other formatting were lost even when catalog values didn't change.Closes #10425
-
The parameter set by the
--allow-buildflag is written toallowBuilds. -
Fix a bug in which specifying
filteronpnpm-workspace.yamlwould cause pnpm to not detect any projects. -
Defer patch errors until all patches in a group are applied, so that one failed patch does not prevent other patches from being attempted.
-
Fail on incompatible lockfiles in CI when frozen lockfile mode is enabled #10978.
Platinum Sponsors
|
|
Gold Sponsors
|
|
|
|
|
|
|
|
|
|
|