This codemod migrates a pnpm v10 project to pnpm v11.
sh
Running locally
sh
What it does
The codemod runs against the workspace root (and every package when a pnpm-workspace.yaml is present) and applies the following automatable migrations from the pnpm v11 changelog:
Moves settings out of package.json#pnpm into pnpm-workspace.yaml
In v11, pnpm no longer reads settings from the pnpm field of package.json. Every known setting under pnpm.* is moved to the top level of pnpm-workspace.yaml. If pnpm-workspace.yaml does not exist, it is created.
Splits .npmrc into auth/registry vs. everything else
In v11, only auth and registry settings are read from .npmrc. For the root .npmrc and every workspace subproject .npmrc, the codemod:
- Keeps auth, token, and registry lines (
registry,@scope:registry,//host/:_authToken,email,cafile, etc.) in.npmrc. - Moves every other setting out, converting the key to camelCase (
hoist-pattern[]→hoistPattern,save-exact→saveExact, and so on) and typing the value (true/false/number/string). - Root-level migrated settings land at the top of
pnpm-workspace.yaml. - Subproject migrated settings land under
packageConfigs["<project-name>"]in the rootpnpm-workspace.yaml, keyed by the subproject'spackage.json#name. - Deletes the
.npmrcfile if nothing was left to keep.
Consolidates build-dependency settings into allowBuilds
The following settings are removed in v11 and merged into a single allowBuilds map:
| Old setting | Translated to |
|---|---|
onlyBuiltDependencies | allowBuilds: { <name>: true } |
neverBuiltDependencies | allowBuilds: { <name>: false } |
ignoredBuiltDependencies | allowBuilds: { <name>: false } |
onlyBuiltDependenciesFile | each entry merged in as true |
The ignoreDepScripts setting has no equivalent — the codemod removes it and prints a warning.
Replaces the package-manager strictness settings with pmOnFail
| Removed setting | Replacement |
|---|---|
managePackageManagerVersions: true | pmOnFail: download |
managePackageManagerVersions: false | pmOnFail: ignore |
packageManagerStrict: false | pmOnFail: warn |
packageManagerStrictVersion: true | pmOnFail: error |
Renames
allowNonAppliedPatches→allowUnusedPatchesauditConfig.ignoreCves→auditConfig.ignoreGhsas(the key is renamed; the codemod prints a warning that each CVE id needs to be replaced with the corresponding GHSA id manually)useNodeVersion→devEngines.runtimein the rootpackage.json(populated as{ name: "node", version: "<value>" }; ifdevEngines.runtimeis already set, the conflict is reported as a warning and left untouched)
Removes
ignorePatchFailures(v11 always throws on a failed patch)
Bumps the packageManager field in package.json
If the root package.json pins pnpm below v11 via packageManager, it is bumped to the latest pnpm v11 release. The exact version is resolved at runtime from the latest-11 dist-tag on the npm registry. If the registry is unreachable, the codemod falls back to a pinned version (currently pnpm@11.0.1).
Things the codemod will NOT do automatically
The following v11 changes require human judgement and are only reported as warnings:
executionEnv.nodeVersionin workspace subpackages. DeclaredevEngines.runtimein that subpackage'spackage.jsoninstead.npm_config_*environment variables are no longer read. Rename them topnpm_config_*.pnpm link <pkg-name>no longer resolves from the global store — use a relative or absolute path.pnpm install -g(with no args) is no longer supported — usepnpm add -g <pkg>.