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/best-practices-ci.md
name: pnpm-ci-cd-setup description: Optimizing pnpm for continuous integration and deployment workflows
pnpm CI/CD Setup
Best practices for using pnpm in CI/CD environments for fast, reliable builds.
CI auto-behaviors: When pnpm detects a CI environment it switches to frozen-lockfile mode automatically (opt out with
--no-frozen-lockfile; force or disable detection with thecisetting) and fails on an incompatible lockfile written by a newer pnpm major instead of rewriting it — keep the CI pnpm version in sync with the one that generated the lockfile. The global virtual store is auto-disabled in CI (no warm cache).
Installing pnpm in CI
On CI systems that run jobs in a container image (GitLab CI, Bitbucket Pipelines), use the official image ghcr.io/pnpm/pnpm:<major> as the job image: pnpm is already on PATH, and pnpm runtime set node lts -g installs Node.js. For your own Dockerfile, copy pnpm in: COPY --from=ghcr.io/pnpm/pnpm:12 /opt/pnpm /opt/pnpm (use the -alpine tag for musl bases), then symlink pnpm pn pnpx pnx from /opt/pnpm into /usr/local/bin.
Elsewhere outside GitHub Actions (which has its own action), use the standalone install script, never Corepack. Save it to a file first, with a fallback download so a failed download never runs a partial script:
{ curl -fsSL https://get.pnpm.io/ -o /tmp/pnpm-install.sh \
|| curl -fsSL https://github.com/pnpm/get.pnpm.io/releases/latest/download/install.sh -o /tmp/pnpm-install.sh; } \
&& sh /tmp/pnpm-install.shNo Node.js needed — pnpm is self-contained and can install a runtime afterwards (
pnpm runtime set node lts -g).Follows the project's version — after bootstrap, pnpm switches to the
packageManager/devEngines.packageManagerpin on first use, so you don't pin twice.The script sets
PNPM_HOMEand edits a shell profile CI never reloads — exportPNPM_HOMEand put$PNPM_HOME/binonPATHyourself.
Corepack installs a JS shim, so every
pnpmcall starts Node.js to run the shim first — a cost paid on each of CI's many invocations. Installing pnpm itself avoids it.
Cache the metadata cache too
pnpm cache path prints pnpm's metadata cache directory. Caching it (alongside the store) also caches the lockfile verification log, letting a job skip re-checking an unchanged lockfile against supply-chain policies — the dominant install cost once the store is warm.
GitHub Actions
Basic Setup
name: CI
on: [push, pull_request]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
with:
version: 10
- uses: actions/setup-node@v4
with:
node-version: 22
cache: 'pnpm'
- run: pnpm install --frozen-lockfile # or: pnpm ci
- run: pnpm test
- run: pnpm build
pnpm ci(aliasesclean-install,install-clean) =pnpm clean+pnpm install --frozen-lockfile, ideal for fully reproducible CI builds.
With Store Caching
For larger projects, cache the pnpm store:
- uses: pnpm/action-setup@v4
with:
version: 10
- name: Get pnpm store directory
shell: bash
run: |
echo "STORE_PATH=$(pnpm store path --silent)" >> $GITHUB_ENV
- uses: actions/cache@v4
name: Setup pnpm cache
with:
path: ${{ env.STORE_PATH }}
key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }}
restore-keys: |
${{ runner.os }}-pnpm-store-
- run: pnpm install --frozen-lockfileTrust: only cache/restore the pnpm store and cache dir between trusted jobs. A store an untrusted job can write to must not be reused by trusted jobs — it is part of pnpm's trust domain.
Matrix Testing
jobs:
test:
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest, windows-latest, macos-latest]
node: [18, 20, 22]
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
- uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node }}
cache: 'pnpm'
- run: pnpm install --frozen-lockfile
- run: pnpm testGitLab CI
image: node:20
stages:
- install
- test
- build
variables:
PNPM_HOME: /root/.local/share/pnpm
PATH: $PNPM_HOME:$PATH
before_script:
- corepack enable
- corepack prepare pnpm@latest --activate
cache:
key: ${CI_COMMIT_REF_SLUG}
paths:
- .pnpm-store
install:
stage: install
script:
- pnpm config set store-dir .pnpm-store
- pnpm install --frozen-lockfile
test:
stage: test
script:
- pnpm test
build:
stage: build
script:
- pnpm buildDocker
PATH: global pnpm binaries live in
$PNPM_HOME/bin. In Docker setENV PATH="$PNPM_HOME/bin:$PATH"(not$PNPM_HOME). The official imageghcr.io/pnpm/pnpm:<version|major|latest>(Debian slim, or-alpinevariants; pnpm + bundlednode-gyp, no Node.js) already setsPNPM_HOME=/pnpmand PATH; choose Node viapnpm runtime set node <ver> -gordevEngines.runtime(pnpm installdownloads it).Always copy
pnpm-workspace.yaml(when present) beforepnpm install/pnpm fetch: it holds project settings and workspace patterns, and omitting it can change installs or fail frozen installs. Also copy patches and files named byinclude.BuildKit cache mounts: if the image has a runtime from
pnpm runtime set node -g, don't mount over/pnpm/store; mount/var/cache/pnpmand pass--store-dir /var/cache/pnpm.
pnpm fetchrecipe:COPY pnpm-lock.yaml pnpm-workspace.yaml /app/,RUN pnpm fetch, then afterCOPY . /apprunpnpm install --offline --frozen-lockfile(fetch only fills the virtual store); use a separate stage withpnpm fetch --prod+install --offline --frozen-lockfile --prodfor production deps.
Multi-Stage Build
# Build stage
FROM node:24-slim AS builder
# Enable corepack for pnpm
RUN corepack enable
WORKDIR /app
# Copy package files first for layer caching
COPY package.json pnpm-lock.yaml pnpm-workspace.yaml ./
COPY packages/*/package.json ./packages/
# Install dependencies
RUN pnpm install --frozen-lockfile
# Copy source and build
COPY . .
RUN pnpm build
# Production stage
FROM node:20-slim AS runner
RUN corepack enable
WORKDIR /app
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/package.json ./
COPY --from=builder /app/pnpm-lock.yaml /app/pnpm-workspace.yaml ./
# Production install
RUN pnpm install --frozen-lockfile --prod
CMD ["node", "dist/index.js"]Optimized for Monorepos
FROM node:20-slim AS builder
RUN corepack enable
WORKDIR /app
# Copy workspace config
COPY pnpm-lock.yaml pnpm-workspace.yaml ./
# Copy all package.json files maintaining structure
COPY packages/core/package.json ./packages/core/
COPY packages/api/package.json ./packages/api/
# Install all dependencies
RUN pnpm install --frozen-lockfile
# Copy source
COPY . .
# Build specific package
RUN pnpm --filter @myorg/api buildKey CI Flags
--frozen-lockfile
Always use in CI. Fails if pnpm-lock.yaml needs updates:
pnpm install --frozen-lockfile--prefer-offline
Use cached packages when available:
pnpm install --frozen-lockfile --prefer-offline--ignore-scripts
Skip lifecycle scripts for faster installs (use cautiously):
pnpm install --frozen-lockfile --ignore-scriptsPinning the pnpm version
Pin with packageManager (exact) or devEngines.packageManager (range, resolved version stored in the lockfile):
// package.json
{ "packageManager": "[email protected]" }The standalone install script and pnpm/action-setup both honor this pin. To skip the pin check when version management is external (asdf/mise/Volta), set pmOnFail: ignore in pnpm-workspace.yaml, or run a one-off with pnpm with current <cmd>.
Corepack still works but is no longer the recommended CI path (it adds a Node.js shim to every
pnpmcall). Prefer the standalone script above.
Monorepo CI Strategies
Build Changed Packages Only
- name: Build changed packages
run: |
pnpm --filter "...[origin/main]" buildParallel Jobs per Package
jobs:
detect-changes:
runs-on: ubuntu-latest
outputs:
packages: ${{ steps.changes.outputs.packages }}
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- id: changes
run: |
echo "packages=$(pnpm --filter '...[origin/main]' list --json | jq -c '[.[].name]')" >> $GITHUB_OUTPUT
test:
needs: detect-changes
if: needs.detect-changes.outputs.packages != '[]'
runs-on: ubuntu-latest
strategy:
matrix:
package: ${{ fromJson(needs.detect-changes.outputs.packages) }}
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
- run: pnpm install --frozen-lockfile
- run: pnpm --filter ${{ matrix.package }} testBest Practices Summary
Use
pnpm cior--frozen-lockfilein CIInstall via the standalone script (
get.pnpm.io/install.sh) rather than CorepackCache the pnpm store and metadata cache (
pnpm cache path), only across trusted jobsMatch the CI pnpm major to the one that wrote the lockfile (CI fails on incompatible lockfiles)
Pin
packageManager(ordevEngines.packageManager) in package.jsonUse
--filterin monorepos to build only what changedMulti-stage Docker builds; set
PATH=$PNPM_HOME/bin:$PATH
<!-- Source references: - https://pnpm.io/continuous-integration - https://pnpm.io/docker - https://pnpm.io/cli/ci - https://pnpm.io/settings/other#ci - https://pnpm.io/cli/cache-path - https://github.com/pnpm/action-setup -->
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