name: pnpm description: pnpm package manager for fast, disk-efficient dependency management and workspaces. Use when user mentions "pnpm", "pnpm install", "pnpm workspace", "pnpm-workspace.yaml", "pnpm add", "pnpm store", "pnpm dlx", "content-addressable store", or managing Node.js packages with pnpm.
pnpm
Fast, disk-efficient package manager for Node.js.
Installation
# Via corepack (recommended, ships with Node.js 16.13+)
corepack enable
corepack prepare pnpm@latest --activate
# Standalone script
curl -fsSL https://get.pnpm.io/install.sh | sh -
# Via npm
npm install -g pnpm
# Via Homebrew
brew install pnpm
Why pnpm
Content-addressable store -- pnpm stores every package version exactly once in a global store. Projects hard-link to the store, so the same dependency across ten projects uses disk space only once.
Strict node_modules -- pnpm creates a non-flat node_modules. Packages can only access dependencies they explicitly declare. This prevents phantom dependencies that work by accident through hoisting.
Speed -- hard linking avoids redundant downloads and copies. Parallel resolution makes installs consistently faster than npm.
Basic Commands
pnpm install # Install all dependencies from lockfile
pnpm add lodash # Add a production dependency
pnpm add -D typescript # Add a dev dependency
pnpm add -g vercel # Add globally
pnpm add lodash@4.17.21 # Specific version
pnpm remove lodash # Remove a dependency
pnpm update # Update within semver ranges
pnpm update --latest # Update to latest, ignoring ranges
pnpm dlx create-next-app@latest # Run a package without installing
pnpm vs npm vs yarn
| Action | pnpm | npm | yarn |
|---|---|---|---|
| Install all | pnpm install |
npm install |
yarn |
| Add dependency | pnpm add pkg |
npm install pkg |
yarn add pkg |
| Add dev dep | pnpm add -D pkg |
npm install -D pkg |
yarn add -D pkg |
| Remove | pnpm remove pkg |
npm uninstall pkg |
yarn remove pkg |
| Run script | pnpm run dev |
npm run dev |
yarn dev |
| Execute binary | pnpm dlx pkg |
npx pkg |
yarn dlx pkg |
| Update | pnpm update |
npm update |
yarn up |
| Audit | pnpm audit |
npm audit |
yarn audit |
| Why installed | pnpm why pkg |
npm why pkg |
yarn why pkg |
Workspaces
pnpm-workspace.yaml
packages:
- 'packages/*'
- 'apps/*'
Filtering
pnpm --filter web run build # By package name
pnpm --filter "./apps/*" run build # By path glob
pnpm --filter web... run build # Package and its dependencies
pnpm --filter ...web run build # Package and its dependents
pnpm -r run build # All workspace packages
pnpm -r --parallel run build # All in parallel
Workspace protocol
Reference sibling packages with workspace: in package.json:
{
"dependencies": {
"@myorg/shared": "workspace:*",
"@myorg/utils": "workspace:^1.0.0"
}
}
On publish, pnpm replaces workspace:* with the actual version. workspace:^ and workspace:~ produce the corresponding semver range.
Monorepo Patterns
Shared dependencies
Place shared dev dependencies in the workspace root. Use -w to add them:
pnpm add -Dw typescript eslint prettier
Peer dependencies
# .npmrc
auto-install-peers=true
strict-peer-dependencies=false
.npmrc Configuration
shamefully-hoist=true # Flat node_modules (compatibility)
auto-install-peers=true # Auto-install peer deps
strict-peer-dependencies=false # Warn instead of error on peer mismatches
enable-pre-post-scripts=true # Run pre/post lifecycle scripts
use-node-version=20.11.0 # Pin Node.js version
registry=https://registry.npmjs.org/
@myorg:registry=https://npm.pkg.github.com
public-hoist-pattern[]=*eslint* # Hoist specific packages only
public-hoist-pattern[]=*prettier*
store-dir=/path/to/custom/store # Custom store location
Lock File
pnpm uses pnpm-lock.yaml. In monorepos it contains an importers section with per-package snapshots:
importers:
apps/web:
dependencies:
react:
specifier: ^18.2.0
version: 18.2.0
devDependencies:
typescript:
specifier: ^5.3.0
version: 5.3.3
Always commit pnpm-lock.yaml. Use --frozen-lockfile in CI.
Patching Dependencies
pnpm patch express@4.18.2 # Opens temp dir with package source
# Edit files, then:
pnpm patch-commit /tmp/patch-dir-xxxxx # Generates patch file
This adds a patchedDependencies entry to package.json:
{
"pnpm": {
"patchedDependencies": {
"express@4.18.2": "patches/express@4.18.2.patch"
}
}
}
Commit the patches/ directory.
Overrides
Force dependency versions across the entire tree:
{
"pnpm": {
"overrides": {
"lodash": "^4.17.21",
"got@<11.8.5": ">=11.8.5",
"express>debug": "~4.3.0"
}
}
}
Use overrides to fix transitive vulnerabilities or force version alignment.
Scripts
pnpm run dev # Run script from package.json
pnpm dev # Shorthand (no conflict with pnpm commands)
pnpm --filter web run build # Run in specific package
pnpm -r run test # Run in all workspace packages
pnpm -r --parallel run lint # Parallel across packages
pnpm does not run pre/post scripts by default. Enable with enable-pre-post-scripts=true in .npmrc.
Store Management
pnpm store path # Print global store location
pnpm store prune # Remove unreferenced packages
pnpm store status # Check for modified packages
pnpm install --offline # Install from store only (no network)
Publishing from a Workspace
pnpm -r publish --access public # Publish all public packages
pnpm -r publish --dry-run # Dry run first
pnpm --filter "./packages/*" publish # Publish subset
pnpm replaces workspace: references with real version numbers during publish.
CI/CD
# GitHub Actions
- uses: pnpm/action-setup@v4
with:
version: 9
- uses: actions/setup-node@v4
with:
node-version: 20
cache: 'pnpm'
- run: pnpm install --frozen-lockfile
- run: pnpm -r run build
- run: pnpm -r run test
--frozen-lockfile fails if pnpm-lock.yaml is out of date, preventing accidental lockfile changes.
For generic CI, cache the directory from pnpm store path between builds.
Migration from npm/yarn
# From npm
rm -rf node_modules package-lock.json
pnpm import # Reads package-lock.json if present
pnpm install
# From yarn
rm -rf node_modules yarn.lock
pnpm import # Reads yarn.lock if present
pnpm install
After migrating: replace npm ci / yarn --frozen-lockfile with pnpm install --frozen-lockfile in CI. Add pnpm-workspace.yaml if the project uses workspaces.