.agents/skills/pnpm/references/core-store.md
pnpm uses a content-addressable store to save disk space and speed up installations. All packages are stored once globally and hard-linked to project node_modules.
~/.pnpm-store/ # Global store (default location)
└── v3/
└── files/
└── <hash>/ # Files stored by content hash
project/
└── node_modules/
├── .pnpm/ # Virtual store (hard links to global store)
│ ├── [email protected]/
│ │ └── node_modules/
│ │ └── lodash/
│ └── [email protected]/
│ └── node_modules/
│ ├── express/
│ └── <deps>/ # Flat structure for dependencies
├── lodash -> .pnpm/[email protected]/node_modules/lodash
└── express -> .pnpm/[email protected]/node_modules/express
# Show store location
pnpm store path
# Remove unreferenced packages
pnpm store prune
# Check store integrity
pnpm store status
# Add package to store without installing
pnpm store add <pkg>
# .npmrc
store-dir=~/.pnpm-store
# Or use environment variable
PNPM_HOME=~/.local/share/pnpm
The virtual store (.pnpm in node_modules) contains symlinks to the global store:
# Customize virtual store location
virtual-store-dir=node_modules/.pnpm
# Alternative flat layout
node-linker=hoisted
pnpm saves significant disk space:
# Compare actual vs apparent size
du -sh node_modules # Apparent size
du -sh --apparent-size node_modules # With hard links counted
Configure how node_modules is structured:
# Default: Symlinked structure (recommended)
node-linker=isolated
# Flat node_modules (npm-like, for compatibility)
node-linker=hoisted
# PnP mode (experimental, like Yarn PnP)
node-linker=pnp
node_modules like npmCache build outputs for native modules:
# Enable side effects caching
side-effects-cache=true
# Store side effects in project (instead of global store)
side-effects-cache-readonly=true
For CI/CD, you can share the store:
# GitHub Actions example
- uses: pnpm/action-setup@v4
with:
run_install: false
- name: Get pnpm store directory
shell: bash
run: echo "STORE_PATH=$(pnpm store path --silent)" >> $GITHUB_ENV
- uses: actions/cache@v4
with:
path: ${{ env.STORE_PATH }}
key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }}
# Verify and fix store
pnpm store status
pnpm store prune
# Use copying instead of hard links
package-import-method=copy
# Fix store permissions
chmod -R u+w ~/.pnpm-store