packageManager Field

Pinning with the packageManager Field

corepack 3,816 use picks a version, writes it with its hash into package.json's packageManager field, and runs an install. From then on Corepack's shims enforce it.

Pinning pnpm 12.6.0 and trying the wrong toolsShell
mkdir ~/v5-ch1/corepack-demo && cd ~/v5-ch1/corepack-demo && cp ../booknest/package.json .
corepack use pnpm@12.6.0 > /dev/null && tail -2 package.json
yarn install; echo "exit=$?"
npm install 2>&1 | grep -m1 "npm error"; echo "exit=${PIPESTATUS[0]}"
Output
  "packageManager": "pnpm@12.6.0+sha512.3ef68f951cb111ac204b4a5a16f0b2ddf0da56a96e0413e...
}
This project is configured to use pnpm because /home/dev/v5-ch1/corepack-demo/package.json ...
exit=1
npm error Cannot read properties of null (reading 'matches')
exit=1

The Yarn 11,798 shim refused to run, which is the point. npm 2,036 was not stopped: Corepack does not shim npm unless you run corepack enable npm, so npm install went ahead over pnpm 69,400 's symlinked node_modules, printed a screen of peer-dependency warnings and crashed. npm has its own guard, the devEngines field, which npm 10.9 and later check before installing.

devEngines: npm refuses to install when the project wants pnpmShell
"devEngines": {
  "runtime": { "name": "node", "version": ">=24" },
  "packageManager": { "name": "pnpm", "version": "12.x", "onFail": "error" }
}

With that block, npm install stops at once with EBADDEVENGINES Invalid name "pnpm" does not match "npm". Pin with packageManager for Corepack and with devEngines for npm, commit both, and set COREPACK_ENABLE_STRICT=0 only when a script genuinely must run another tool.