From the skill’s files
Taken from the skill’s own files (its description, section headings and stated usage). Not an AutoGineer summary, and not written by the author as one.
Node.js package manager with strict dependency resolution. Use when running pnpm specific commands, configuring workspaces via pnpm-workspace.yaml, or managing dependencies with catalogs, patches, overrides, config dependencies, or the global virtual store. pnpm is a fast, disk space efficient package manager. It uses a content-addressable store to deduplicate packages across all projects on a machine, and enforces strict dependency resolution by default, preventing phantom dependencies.
What it does
- Core
- Features
- Best Practices
When to use it
- Use when running pnpm specific commands, configuring workspaces via pnpm-workspace.yaml, or managing dependencies with catalogs, patches, overrides, config dependencies, or the global virtual store.
Advantages
The skill’s files do not state this.
Usage examples
The skill’s files do not state this.
Install
Download the skill as a ZIP:
https://autogineer.com/agent-skills/antfu/pnpm/downloadUnzip it into the cross-client skills folder of your project:
mkdir -p .agents/skills && unzip pnpm.zip -d .agents/skills
Documentation by Anthony Fu
pnpm is a fast, disk space efficient package manager. It uses a content-addressable store to deduplicate packages across all projects on a machine, and enforces strict dependency resolution by default, preventing phantom dependencies.
pnpm v12 is a Rust rewrite of v11: stable, and keeps v11's commands, flags, settings, and lockfile format — so most guidance here applies to both. A handful of v12 behaviors differ (git deps resolve via HTTPS, project-aware global bins, other package managers, packageImportMethod: auto hardlinks first on Linux) — see best-practices-migration.
Configuration model (important): pnpm settings live in pnpm-workspace.yaml (and the global config.yaml) using camelCase keys. .npmrc is used only for authentication/registry credentials, and the pnpm field of package.json is no longer read. When working in a pnpm project, check pnpm-workspace.yaml for settings/workspace structure and .npmrc only for auth. Always use --frozen-lockfile (or pnpm ci) in CI.
The skill is based on pnpm 12.18, generated at 2026-11-05. It covers v11+v12 behavior (config split, config includes, isolated global packages,
allowBuilds,pmOnFail, global virtual store, native release management, workspace task orchestration, and experimental Python/Cargo support) where current docs describe them.
Core
| Topic | Description | Reference |
|---|---|---|
| CLI Commands | install/add/remove/update, run, dlx/pnx, workspace, runtime, publishing (version, view, sbom, stage) | core-cli |
| Configuration | pnpm-workspace.yaml settings (camelCase), global config.yaml, config includes, packageConfigs, auth (.npmrc, auth.ini) | core-config |
| Workspaces | Monorepo support: filtering, workspace protocol, shared lockfile, packageConfigs | core-workspaces |
| Store | Content-addressable store, virtual store, node linker modes (incl. loaded/store loader), frozen/read-only store | core-store |
Features
| Topic | Description | Reference |
|---|---|---|
| Catalogs | Centralized dependency versions; catalogMode, catalog: in overrides | features-catalogs |
| Overrides | Force versions (incl. transitive & peer deps); packageExtensions | features-overrides |
| Patches | Modify third-party packages; patchedDependencies in pnpm-workspace.yaml | features-patches |
| Aliases | Install under custom names (npm:) and registry aliases (namedRegistries) | features-aliases |
| Hooks | .pnpmfile.mjs hooks (readPackage, updateConfig, beforePacking), finders, resolvers/fetchers | features-hooks |
| Peer Dependencies | Auto-install, strict mode, rules, dedupePeers, peers check | features-peer-deps |
| Config Dependencies | Share hooks/settings/catalogs/patches across repos via configDependencies | features-config-dependencies |
| Global Virtual Store & Shims | Shared node_modules, git-worktree multi-agent setups, isolated global packages, project-aware bins, other package managers | features-global-virtual-store |
| Supply-Chain Security | Build approval (allowBuilds), permissions and agent skills, minimumReleaseAge, trustPolicy, lockfile integrity | features-supply-chain-security |
| Task Orchestration | Cross-project task graphs (tasks/dependsOn), concurrency groups, priority, pnpm pipeline | features-task-orchestration |
| Release Management | Native versioning: pnpm change/version -r/lane, lanes, epics, fixed groups | features-versioning |
| Multi-Ecosystem | Python (pypi:) and Cargo (crate:) dependencies alongside npm (experimental) | features-multi-ecosystem |
Best Practices
| Topic | Description | Reference |
|---|---|---|
| CI/CD Setup | GitHub Actions, GitLab, Docker, pnpm ci, store caching, frozen lockfiles | best-practices-ci |
| Migration | npm/Yarn → pnpm, phantom deps, and pnpm v10 → v11 → v12 upgrade notes | best-practices-migration |
| Performance | Install optimizations, allowBuilds, global virtual store, workspace parallelization | best-practices-performance |
Files
- ATTRIBUTION.mdAdded by AutoGineer889 B
- GENERATION.md134 B
- LICENSELicence file added by AutoGineer1.1 KiB
- SKILL.md5.1 KiB
- references/best-practices-ci.md9.7 KiB
- references/best-practices-migration.md9.9 KiB
- references/best-practices-performance.md6.0 KiB
- references/core-cli.md11.3 KiB
- references/core-config.md12.8 KiB
- references/core-store.md10.7 KiB
- references/core-workspaces.md6.6 KiB
- references/features-aliases.md4.4 KiB
- references/features-catalogs.md5.0 KiB
- references/features-config-dependencies.md4.2 KiB
- references/features-global-virtual-store.md10.0 KiB
- references/features-hooks.md8.9 KiB
- references/features-multi-ecosystem.md6.2 KiB
- references/features-overrides.md5.5 KiB
- references/features-patches.md5.0 KiB
- references/features-peer-deps.md5.9 KiB
- references/features-supply-chain-security.md7.7 KiB
- references/features-task-orchestration.md6.8 KiB
- references/features-versioning.md5.5 KiB
references/core-store.md
name: pnpm-store description: Content-addressable storage system that makes pnpm fast and disk-efficient
pnpm Store
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.
How It Works
Global Store: Packages are downloaded once to a central store
Hard Links: Projects link to store instead of copying files
Content-Addressable: Files are stored by content hash, deduplicating identical files
Storage Layout
<store-dir>/ # Global content-addressable store (pnpm store path)
└── 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/expressStore Commands
# Show store location
pnpm store path
# Remove unreferenced packages
pnpm store prune
# Check lockfile packages for modifications (ERR_PNPM_MODIFIED_DEPENDENCY)
pnpm store status
# Add package (or tarballs) to store without installing
pnpm store add <pkg>
pnpm store add ./tarballs/*.tgz && pnpm install --offline --frozen-lockfile # offline/sandboxed buildsstore addof tarballs: install uses one when the lockfile entry names the same package/version and pins that tarball (integritymay be sha512/sha1 of the tgz or the uncompressed tar hash fromlockfile.integrityTarget: tar). For named-registry packages, run it in the declaring project.store prunealso deletes expiredpnxcache entries first, removes the package metadata cache (metadata*dirs; next install re-downloads), keeps undecodable index entries (reported in summary), and (v12.7+) removes private pnpm/runtime copies left by killed processes. With a global virtual store it mark-and-sweepslinks/using registered projects (symlinks in$(pnpm store path)/projects; written by everypnpm installexcept--frozen-store/enableModulesDir: falsewithout GVS,--lockfile-only,--dry-run); if no registered project links intolinks/, it is left unchanged.
Configuration
Store/linker settings live in pnpm-workspace.yaml (camelCase), not .npmrc.
Store Location
storeDir: ~/.local/share/pnpm/storeIf no directory above the project accepts hard links (agent sandbox, writable bind mount), the store falls back to node_modules/.pnpm-store (workspace root in a workspace). Cross-process locks live in a per-user dir ($XDG_RUNTIME_DIR if usable, else /tmp; ~/AppData/Local on Windows); a sandbox blocking /tmp can set XDG_RUNTIME_DIR (processes sharing a store should see the same value).
The default store path is OS-specific (e.g. ~/.local/share/pnpm/store on Linux, ~/Library/pnpm/store on macOS). Find it with pnpm store path.
Virtual Store
The virtual store (.pnpm in node_modules) contains hard links to the global store:
virtualStoreDir: node_modules/.pnpm
virtualStoreDirMaxLength: 60 # lower this for long-path issues on Windows
nodeLinker: hoisted # alternative flat layoutStore index format (v12.13+)
storeIndexFormat: sqlite # default: one index.db, local disk only
# storeIndexFormat: files # one file per package in <store>/index; lock-free, for network stores shared by CI jobsThe format belongs to the store: once an index dir exists, every pnpm uses it; existing index.db entries are not carried over (re-download). Switch back by deleting index. pnpm v11 cannot read files stores.
Disk Space Benefits
pnpm saves significant disk space:
Deduplication: Same package version stored once across all projects
Content deduplication: Identical files across different packages stored once
Hard links: No copying, just linking
Check disk usage
# Compare actual vs apparent size
du -sh node_modules # Apparent size
du -sh --apparent-size node_modules # With hard links countedGlobal Virtual Store
With virtualStoreType: global, projects skip the per-project node_modules/.pnpm directory entirely; their node_modules contains only symlinks into one shared virtual store at <store-path>/links/, keyed by dependency-graph hash. It is the default for global installs (pnpm add -g) only; pnpm dlx/pnx does NOT use it (each dlx cache entry keeps its own virtual store); for project installs it is still opt-in/experimental. Each project's node_modules/.pnpm still holds its current lockfile and hidden hoisted deps. Location: <store-path>/links, or set globalVirtualStoreDir (wins) or virtualStoreDir. Only applies with nodeLinker: isolated. Spawned processes get NODE_PATH plus a NODE_OPTIONS --import hook so hoisted lookups work in ESM too. It is no longer auto-disabled in CI. See features-global-virtual-store for details and the git-worktrees multi-agent workflow.
virtualStoreType: global # canonical spelling
# enableGlobalVirtualStore: true # equivalent, still works (virtualStoreType wins if both set)Node Linker Modes
Configure how node_modules is structured (nodeLinker in pnpm-workspace.yaml):
nodeLinker: isolated # default: symlinked virtual store (strict, no phantom deps)
# nodeLinker: hoisted # flat node_modules (npm-like) for tools that dislike symlinks
# nodeLinker: pnp # Plug'n'Play, no node_modules (set `symlink: false` too)
# nodeLinker: { type: loaded, excluded: [vitest] } # experimental store loader, see belowIsolated Mode (Default)
Strict dependency resolution
No phantom dependencies
Packages can only access declared dependencies
Hoisted Mode
Flat
node_moduleslike npmFor compatibility with tools that don't support symlinks
Loses strictness benefits
Loaded linker (experimental store loader)
nodeLinker: { type: loaded } lets Node load JS/JSON directly from the content-addressable store with no packages in node_modules (also enables the global virtual store). Setting nodeLinker replaces the whole value across config sources; env/CLI accept JSON (PNPM_CONFIG_NODE_LINKER, --config.node-linker).
nodeLinker:
type: loaded
excluded: # exact names; all versions + their full dep trees are materialized as normal GVS packages
- vitestRun
pnpm install, thenpnpm run/test/execas usual: pnpm writesnode_modules/.pnpm/.store-manifest.jsonand.store-loader.mjsand preloads the loader (child Node processes inherit viaNODE_OPTIONS). Outside pnpm:node --import ./node_modules/.pnpm/.store-loader.mjs app.mjs.Requires Node 24.18+ (24.x) or 26.2+, else
ERR_PNPM_LOADER_UNSUPPORTED_NODE.Patched packages, runtimes (
node@runtime:), and anything with build scripts must be materialized (scripts packages need explicitexcludedselection unless scripts are disabled; build approval still applies).Not combinable with
symlink: falseornodePackageMap.modeother thanoff. Remove oldnode_moduleswhen switching modes. Files are machine-local: reinstall after moving the project.Limits: no real filesystem (
__dirname,import.meta.urlare virtual;fsreads of adjacent assets fail), no native addons, WASM, TypeScript, or package-internal symlinks. Packages needing these must be put inexcluded.
Package map (v12.13+)
nodePackageMap:
mode: off # off (default) | write-only (write node_modules/.package-map.json) | load (also add --experimental-package-map to NODE_OPTIONS)
# type: looseReplaces deprecated nodeExperimentalPackageMap (true = mode: load) and nodePackageMapType.
Side Effects Cache
Cache build outputs for native modules (enabled by default):
sideEffectsCache: true
sideEffectsCacheReadonly: false # only read the cache, don't create itRead-only / Frozen Store
frozenStore: true lets pnpm install run against a read-only store (Nix store, read-only bind mount, OCI layer). Pair with --offline --frozen-lockfile; the store must already contain everything, including approved build outputs.
pnpm install --frozen-store --offline --frozen-lockfileNo other process may modify the store during a frozen-store install (immutable reads bypass SQLite locks and can report a malformed database). Missing builds fail with ERR_PNPM_FROZEN_STORE_NEEDS_BUILD, a missing content dir with ERR_PNPM_FROZEN_STORE_INCOMPLETE. Leave it off for ordinary parallel installs sharing a local store.
Shared Store Across Machines
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') }}Troubleshooting
Store corruption
# Verify and fix store
pnpm store status
pnpm store pruneHard link issues (network drives, Docker)
# auto (default): on Linux (v12) tries hardlink -> clone -> copy; macOS is clone-first (APFS)
packageImportMethod: copy # copy | clone | clone-or-copy | hardlinkCloning shares data with the store until written (safe to edit). A package a lifecycle script or patch will write is imported with clone-or-copy under auto/hardlink/clone. On macOS pnpm writes with 4 threads; on machines with Endpoint Security software try PNPM_MACOS_LINK_THREADS=0.
v12 change: on Linux
packageImportMethod: autohardlinks before reflinking (roughly halves materialize time on btrfs). Useclone(orclone-or-copy) if you edit files insidenode_modules, since a hardlinked file is the store's file.
Permission issues
# Fix store permissions (find the path with `pnpm store path`)
chmod -R u+w "$(pnpm store path)"<!-- Source references: - https://pnpm.io/symlinked-node-modules-structure - https://pnpm.io/cli/store - https://pnpm.io/settings/store - https://pnpm.io/settings/node-modules - https://pnpm.io/global-virtual-store - https://pnpm.io/store-loader - https://pnpm.io/settings/store#storeindexformat -->
Requirements and compatibility
Works with: Claude Code, Claude apps, OpenAI Codex, GitHub Copilot, Cursor, Gemini CLI, Kiro, OpenCode, Goose, Amp, Roo Code, JetBrains Junie, Factory Droid, Devin (ex-Windsurf), Mistral Vibe, OpenHands, Letta
“Works with” means the tool reads the open Agent Skills format; a skill written for one tool may use features others lack.
Needs: Needs Node.js
Security
What our scanner noticed· Low risk
- Instructions that use the network
A static scan is not a guarantee. Skills are third-party content: review a skill before you let an agent use it.
Attribution and licence
- Created by
- Anthony Fu
- Publisher
- Anthony Fu (Community)
- Source
- antfu/skills · skills/pnpm · commit f63e9ec
- Licence
- MIT License (redistribution allowed)
- LICENSE (added by AutoGineer from LICENSE.md)
- ATTRIBUTION.md (written by AutoGineer)
- Synced
AutoGineer is not affiliated with or endorsed by Anthony Fu or Anthony Fu.
Download ZIP
The ZIP holds the skill’s files, its licence files and an ATTRIBUTION.md. Download pnpm.zip