Build Settings

ignoreScripts#

  • Default: false
  • Type: Boolean

Do not execute any scripts defined in the project package.json and its dependencies.

Note

This flag does not prevent the execution of .pnpmfile.mjs

childConcurrency#

  • Default: 5
  • Type: Number

The maximum number of child processes to allocate simultaneously to build node_modules.

sideEffectsCache#

  • Default: true
  • Type: Boolean or Object

Use and cache the results of (pre/post)install hooks.

When a pre/post install script modify the contents of a package (e.g. build output), pnpm saves the modified package in the global store. On future installs on the same machine, pnpm reuses this cached, prebuilt version—making installs significantly faster.

Note

You may want to disable this setting if:

  1. The install scripts modify files outside the package directory (pnpm cannot track or cache these changes).
  2. The scripts perform side effects that are unrelated to building the package.

An object says the same thing in more detail, and is the canonical way to declare the remote tier:

pnpm-workspace.yaml
sideEffectsCache:
  read: true
  write: true
  remote:
    org: acme
    packages:
      - native-addon
  • read — restore a build from the cache when one is present. Default true.
  • write — save a package's build output to the cache. Default true.
  • remote — reuse builds across machines; see below.

sideEffectsCache: true is the shorthand for reading and writing, and is what the setting meant before it grew a remote tier. Writing without reading (read: false, write: true) populates a cache the run never consumes, which is what a job that warms one for others wants.

Since v12.2.0, the --side-effects-cache and --no-side-effects-cache flags, and PNPM_CONFIG_SIDE_EFFECTS_CACHE, toggle the local cache only. A remote tier declared under sideEffectsCache.remote is left in place, so a run can turn the local cache off without losing the shared one.

sideEffectsCacheReadonly#

  • Default: false
  • Type: Boolean

Only use the side effects cache if present, do not create it for new packages. The older spelling of sideEffectsCache: { read: true, write: false }.

sideEffectsCache.remote#

Added in: v12.0.0

  • Default: undefined
  • Type: Object

Opt in to reusing a dependency's build output across machines, by restoring signed, organization-scoped artifacts instead of running the package's lifecycle scripts locally. The artifacts live on the server remoteCache names: a pnpr server started with artifacts.enabled: true, or, since v12.12.0, a server that speaks the Turborepo Remote Cache API. This is a proof of concept: it is off unless configured, and it restores artifacts on Linux/glibc, macOS, and Windows, on x64 and arm64. Other operating systems and libc families build locally.

A repository declares eligibility and nothing else:

pnpm-workspace.yaml
pnprServer: http://127.0.0.1:7677
allowBuilds:
  native-addon: true
remoteCache:
  org: acme
sideEffectsCache:
  remote:
    packages:
      - native-addon

Declaring only remote leaves read and write at their defaults, so the local cache keeps working as it did.

packages is an eligibility list, not a permission: a package is only a candidate when it also passes allowBuilds, has requiresBuild: true, and has a verified source integrity. Listing a package here does not review its build scripts for you — under the default strictDepBuilds an install still fails with ERR_PNPM_IGNORED_BUILDS when it reaches a build nobody has ruled on, and a package denied with allowBuilds: false is never built, from the cache or otherwise.

The organization and the trust material are set under remoteCache. They can also be set under sideEffectsCache.remote, where they lived before v12.12.0, and remoteCache wins where both set a field. Everything describing the act of signing — publish, keyId, builderId, imageDigest, architectureBaseline, buildEnv, trustedKeys and privateKey — is refused in pnpm-workspace.yaml with ERR_PNPM_WORKSPACE_REMOTE_SIDE_EFFECTS_TRUST, and is read from the global configuration file or the environment instead. A cloned repository is not a trust root, and must not be able to turn the machine's signing key into a signing oracle.

Any cache failure — an unreachable server, an unverifiable signature, an incompatible platform, a bad blob — falls back to the ordinary local build. See Shared side-effects cache for the full setup, including the server flag, the trust material, and how an artifact is published.

Since v12.1.0, a restored artifact is saved in the shared store together with its signed origin. Before a later install reuses it, pnpm checks the signature again against the machine's current keys and revalidates its owner, package and source identity, platform, policy, and stored files. A bad remote variant is quarantined for that server and is not selected again.

Note

remoteSideEffectsCache is the older spelling of this setting, and organization of its org field; both still work.

The two spellings are merged, not chosen between: a field set under both takes its value from sideEffectsCache.remote, and a field set under only one is kept either way. That is what lets a repository declare the org in pnpm-workspace.yaml while the machine supplies the signing key from the global config under whichever spelling it already used.

remoteCache#

Added in: v12.12.0

  • Default: undefined
  • Type: Object

The server that shares build output between machines, and the keys every shared artifact is signed and verified with. Both sideEffectsCache.remote and the task cache of pnpm pipeline use it.

With url, artifacts live on a server that speaks the Turborepo Remote Cache API, such as Vercel Remote Cache or a self-hosted implementation. Without it, they live on pnprServer.

pnpm-workspace.yaml
remoteCache:
  org: acme
~/.config/pnpm/config.yaml
remoteCache:
  url: https://vercel.com/api
  team: team_abc123
  trustedKeys:
    ci-2026: <base64 P-256 SubjectPublicKeyInfo DER public key>
FieldWhere it may be setMeaning
urlGlobal config or environmentThe API base URL of a Turborepo Remote Cache server, such as https://vercel.com/api.
teamGlobal config or environmentA Vercel team ID (team_...) or team slug.
orgAnywhereThe organization that owns the artifacts. On a pnpr server, one of the organizations it declares under artifacts.orgs. It also names the organization pnpm pipeline --report records a run under.
trustedKeysGlobal config or environmentThe public keys an artifact must be signed by, keyed by key id.
publishGlobal config or environmenttrue publishes what this machine builds: dependency builds and pnpm pipeline task results. A task result includes the task's output files and its captured terminal output. Defaults to false. Set under sideEffectsCache.remote, it publishes dependency builds only.
privateKey, keyId, builderIdGlobal config or environmentThe key that signs published artifacts, the id consumers trust it under, and a label for the builder. Required with publish.
imageDigest, architectureBaseline, buildEnvGlobal config or environmentOptional provenance recorded in the signed artifact.

Every field is also read from the environment as PNPM_REMOTE_CACHE_ followed by the field name in upper snake case, such as PNPM_REMOTE_CACHE_URL. trustedKeys and buildEnv take a JSON object there. The environment takes precedence over both files. A pnpm-workspace.yaml that sets a field marked "Global config or environment" fails with ERR_PNPM_WORKSPACE_REMOTE_CACHE_TRUST. A repository that could name the server could have the machine's token sent to a server of its choosing.

Authenticating with Vercel Remote Cache#

pnpm sends the server the credential its authentication settings hold for url, as it does for a registry. Create an access token in your Vercel account settings, under Tokens, scoped to the team that owns the cache. On your own machine, store it:

pnpm config set //vercel.com/api/:_authToken "$VERCEL_TOKEN"

In CI, pass it in the environment for the one command instead:

env "pnpm_config_//vercel.com/api/:_authToken=$VERCEL_TOKEN" pnpm pipeline

Use this form rather than _auth. An _auth entry also routes package requests to its URL.

pnpm does not read the token turbo login stores. That token expires within hours, and only turbo renews it.

A Turborepo Remote Cache server holds one build per package for each combination of operating system, CPU architecture, and Node.js major, and a later publication replaces it. A machine restores a build when it meets the build's minimum OS or glibc version, and publishes only when it found none it could restore. Publish from the machine with the oldest system you support.

A server that pnpm would send credentials to must use HTTPS or a loopback address. Otherwise the remote cache is not used.

unsafePerm#

  • Default: false IF running as root, ELSE true
  • Type: Boolean

Set to true to enable UID/GID switching when running package scripts. If set explicitly to false, then installing as a non-root user will fail.

nodeOptions#

  • Default: NULL
  • Type: String

Options to pass through to Node.js via the NODE_OPTIONS environment variable. This does not impact how pnpm itself is executed but it does impact how lifecycle scripts are called.

An empty value, such as --config.node-options= or PNPM_CONFIG_NODE_OPTIONS=, overrides a value from a lower-priority configuration source. With an empty nodeOptions, scripts retain NODE_OPTIONS from the parent environment or extraEnv.

To preserve existing NODE_OPTIONS you can reference the existing environment variable using ${NODE_OPTIONS} in your configuration:

pnpm-workspace.yaml
nodeOptions: "${NODE_OPTIONS:- } --experimental-vm-modules"

verifyDepsBeforeRun#

  • Default: install
  • Type: install, warn, error, prompt, false

This setting allows the checking of the state of dependencies before running scripts. The check runs on pnpm run and pnpm exec commands. The following values are supported:

  • install - Automatically runs install if node_modules is not up to date. If that install fails, for example because the store is read-only or there is no network, pnpm prints a warning and runs the command anyway.
  • warn - Prints a warning if node_modules is not up to date.
  • prompt - Prompts the user for permission to run install if node_modules is not up to date.
  • error - Throws an error if node_modules is not up to date.
  • false - Disables dependency checks.

strictDepBuilds#

Added in: v10.3.0

  • Default: true
  • Type: Boolean

When strictDepBuilds is enabled, the installation will exit with a non-zero exit code if any dependencies have unreviewed build scripts (aka postinstall scripts).

allowBuilds#

Added in: v10.26.0

A map of package matchers to explicitly allow (true) or disallow (false) script execution.

pnpm-workspace.yaml
allowBuilds:
  esbuild: true
  core-js: false
  # nx versions with build scripts not listed below will
  # fail by default with ERR_PNPM_IGNORED_BUILDS
  nx@21.6.4 || 21.6.5: true
  nx@21.6.0: false

Git-hosted packages: a package name on its own never approves builds for a git or tarball dependency — the name alone does not identify the artifact. Approve one either by its exact resolved path (including the commit) or, since v11.11.0, by its repository URL:

pnpm-workspace.yaml
allowBuilds:
  # Approves any commit from this repository
  'foo@git+ssh://git@example.com/org/foo.git': true
  # Approves only this exact commit
  'bar@git+https://github.com/org/bar.git#abc123': true

The repository form lets a trusted git dependency keep running its build scripts across branch updates without re-approving each new commit. The key is the package name, followed by @ and the git URL, with no #<ref> suffix. Matching is exact, so git+ssh:// and git+https:// URLs for the same repository are separate keys.

Since v11.19.0, the repository form also approves git-hosted packages that pnpm downloads as a tarball rather than clones — such as github: dependencies, which are fetched from codeload.github.com. A foo@git+https://github.com/org/foo.git entry approves foo whether pnpm clones the repository or downloads a tarball. GitLab and Bitbucket tarball downloads are matched the same way. Approving or denying a specific resolved commit by its full tarball dep path continues to work.

Denials by package name are not restricted this way: foo: false blocks foo whether it comes from the registry or from git.

Default behavior: Packages not listed in allowBuilds are disallowed by default and are treated as unreviewed. By default, an error is printed (strictDepBuilds defaults to true). If strictDepBuilds is set to false, a warning is printed instead.

During install, dependencies with ignored builds that are not yet listed in allowBuilds are automatically added to pnpm-workspace.yaml with a placeholder value, so you can manually set them to true or false. The --allow-build flag on pnpm add and pnpm approve-builds writes its entries here as well.

Patched packages: since v12.4.0, a patch that adds an install script or a binding.gyp makes the package buildable, and the build goes through the same approval. Until the package is allowed, it is listed under "Ignored build scripts".

Migrating from older settings

To migrate these settings automatically, run pnpx codemod run pnpm-v10-to-v11 from the Migrating from v10 to v11 guide.

The following settings have been removed in v11 and replaced by allowBuilds: onlyBuiltDependencies, onlyBuiltDependenciesFile, neverBuiltDependencies, ignoredBuiltDependencies, and ignoreDepScripts.

Before:

pnpm-workspace.yaml
onlyBuiltDependencies:
  - electron
neverBuiltDependencies:
  - core-js
ignoredBuiltDependencies:
  - esbuild

After:

pnpm-workspace.yaml
allowBuilds:
  electron: true
  core-js: false
  esbuild: false

permissions#

Added in: v12.11.0

  • Type: Object

What each dependency may do, keyed by package. The keys have the same forms as the keys of allowBuilds. Each entry decides one or more capabilities:

  • build: the package may run its build scripts. Outranks the package's allowBuilds entry.
  • skills: pnpm may link the agent skills the package ships into the project's agent skill directories. See Agent skills.
pnpm-workspace.yaml
permissions:
  drizzle-kit:
    build: true
    skills: true
  esbuild:
    build: true
  some-pkg:
    skills: false

false records a denial, so the package is not offered for approval again. pnpm approve writes these entries.

A build decision is written to permissions only when the file already has a permissions setting. Otherwise it is written to allowBuilds, which older pnpm versions read too.

skills.dirs#

Added in: v12.11.0

  • Default: the agent skill directories that exist in the workspace root, plus the one of the agent running pnpm
  • Type: String[]

The directories, relative to the workspace root, that pnpm links approved agent skills into. When set, it replaces the detected directories, and pnpm creates the ones that are missing.

pnpm-workspace.yaml
skills:
  dirs:
    - .claude/skills

An empty list turns agent skills off. pnpm stops offering them for approval and removes the ones it linked.

dangerouslyAllowAllBuilds#

Added in: v10.9.0

  • Default: false
  • Type: Boolean

If set to true, all build scripts (e.g. preinstall, install, postinstall) from dependencies will run automatically, without requiring approval. A package whose build is denied, by false in allowBuilds or build: false in permissions, is still blocked, so this setting allows every build except the denied ones. As everywhere else, a package's permissions entry outranks its allowBuilds entry.

Warning

This setting allows all dependencies—including transitive ones—to run install scripts, both now and in the future. Even if your current dependency graph appears safe:

  • Future updates may introduce new, untrusted dependencies.
  • Existing packages may add scripts in later versions.
  • Packages can be hijacked or compromised and begin executing malicious code.

For maximum safety, only enable this if you’re fully aware of the risks and trust the entire ecosystem you’re pulling from. It’s recommended to review and allow builds explicitly.