pnpm/action-setup is being superseded by pnpm/setup, and the v2 breakage is the reason
Install pnpm package manager
At a glance
- What is it?
- A GitHub Action that installs the pnpm package manager, with caching keyed on the lockfile and an optional recursive install step. The README leads with a notice that pnpm/setup is also available for pnpm v11 and newer, and that the older v2 line of this action stopped working with newer Node.js versions.
- Who is it for?
- Adopt pnpm/action-setup if your workflow pins pnpm v10 or v11 and you want to keep the familiar two step setup with actions/setup-node. Do not adopt it for pnpm v12 or newer, because the README states that pnpm/setup installs the self-contained release binary and a JavaScript runtime in one step and is the recommended path.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 48 days ago.
- What is it written in?
- Mainly TypeScript, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.
Editorial analysis
The deprecation notice is the first thing in the README
The action supports pnpm v12 and earlier. For pnpm v11 and newer, pnpm/setup is also available, and it downloads pnpm's self-contained release binary with no Node.js or npm required, and can install a JavaScript runtime, Node.js, Bun or Deno, in the same step, replacing actions/setup-node when its feature set fits your workflow.
You can continue using pnpm/action-setup with actions/setup-node, including for pnpm v11 and v12, so this is not a hard end of life. The README points at a section titled Using pnpm/setup instead for anyone who wants a single action to install both the package manager and a runtime.
The reason the split exists is technical and the README states it precisely. pnpm/setup cannot install pnpm v11 on Intel macOS, `darwin-x64`, where no standalone pnpm v11 binary is published. On that platform you have to run actions/setup-node with Node.js 22.13 or newer before pnpm/action-setup, or upgrade to pnpm v12.
That constraint is the clearest argument for the direction of travel. pnpm v12 ships as a standalone native executable on its own, so the awkward platform does not apply and the two action problem disappears. The one action that installs pnpm and Node.js together is strictly simpler on most runners, and the one platform where it cannot be used is the one where you fall back to the older arrangement.
There is a second notice further down, and it is about the past rather than the future. The v2 version of this action has stopped working with newer Node.js versions, and the request is to upgrade to the latest version to fix any issues. The action is at v6.1.0 now, published on 2026-09-05, with v6.0.10 from 2026-08-03 and v6.0.9 from 2026-06-15 before it, and the last push to the repository was on 2026-09-05.
The input table is the migration guide
The README provides a side by side table of the inputs and outputs of the two actions, and it is the most useful part of the documentation for anyone moving between them.
The `version` input keeps its name but has a stricter rule, since it must resolve to pnpm v11 or newer for pnpm/setup. As before, it can be omitted when `packageManager` or `devEngines.packageManager` is set in package.json. `dest` and `cache` are unchanged.
`run_install` becomes `install`, and the behaviour differs. pnpm/setup runs `pnpm install` automatically when a package.json is present, with `install: true` by default, and you set `install: false` to skip it. The object and array form is not supported there, which means the recursive and cwd and args options that pnpm/action-setup offers have to move to separate steps.
Two inputs are renamed to kebab-case, `cache_dependency_path` becomes `cache-dependency-path` and `package_json_file` becomes `package-json-file`. That is a cosmetic difference, but it is a difference, and a workflow that is not updated will silently use the default rather than the path you meant.
`standalone` is removed, because pnpm/setup always installs the standalone native executable. Two inputs are new. `runtime` installs Node.js, Bun or Deno, for example `node@22`, `bun@latest` or `deno@2`, or reads `devEngines.runtime` from package.json. And `token` is a GitHub token for the release lookup, defaulting to `${{ github.token }}` and rarely needing to be set.
On the output side, `bin_dest` becomes `bin-dest`, and two new outputs, `runtime-name` and `runtime-version`, describe the installed runtime so later steps can refer to it.
The version input is where most of the configuration lives
The `version` input is optional when there is a `packageManager` or `devEngines.packageManager` field in package.json, and otherwise it is required.
It supports the npm versioning scheme, so it can be an exact version such as 10.9.8, or a version range such as 10, 10.x.x, 10.9.x, `^10.9.8` or `*`, or `latest`.
That flexibility is the point of the input. A range means the workflow installs whatever matches, which sounds like a bad idea for reproducibility and is, unless the lockfile and the store cache pin the actual package versions. The cache input handles the second half of that.
The other inputs are short and each does one thing. `dest` is where the pnpm files are stored. `run_install` has a default of `null`, and if it is `null` or `false` pnpm will not install any npm package, while `true` installs dependencies recursively. As a YAML string it can be the representation of an object or an array, in which case pnpm will execute every install command.
The object form has three properties. `recursive` is a boolean, defaulting to false, and controls whether pnpm recursive install is used. `cwd` is the working directory for the install. And `args` is a list of additional arguments after the install, for example `[--ignore-scripts, --strict-peer-dependencies]`.
`cache` is a boolean defaulting to false and controls whether the pnpm store directory is cached. `cache_dependency_path` is a string defaulting to `pnpm-lock.yaml`, the file path to the pnpm lockfile whose contents hash is used as the cache key, and it accepts multiple paths delimited by newlines. `package_json_file` is a string defaulting to `package.json`, the file to read `packageManager` or `devEngines.packageManager` configuration from.
The `standalone` input is the last one and it is version specific. For pnpm v11 and earlier, it installs `@pnpm/exe`, which enables pnpm to run without Node.js. For pnpm v12, the input has no effect, because the plain pnpm package already installs a standalone native executable.
Caching is keyed on the lockfile hash, and that is the whole mechanism
The cache is the feature that makes pnpm usable in CI, and the mechanism is simple enough to be worth stating plainly.
The `cache` input turns on caching of the pnpm store directory, and `cache_dependency_path` names the lockfile whose contents are hashed to form the cache key. The default is `pnpm-lock.yaml`, and multiple paths are accepted, delimited by newlines, which is what you need for a monorepo where each workspace has its own lockfile.
The logic is the one pnpm is built around. The store is a content addressed directory of packages, and the lockfile records the exact resolved versions and integrity hashes. If the lockfile does not change, the store contents that the install needs are already there. So a cache keyed on the lockfile hash hits for every commit that does not touch dependencies, and misses only when the dependency graph actually moves. That is a much better hit rate than caching the whole `node_modules` directory, which would be invalidated by any change at all.
The implementation detail in the repository explains the plumbing. The dependency list includes `@actions/cache` at 4.1.0 for the cache service, `@actions/core` for inputs and outputs, `@actions/exec` for running the commands, `@actions/glob` for locating files, and `yaml` for parsing. The `semver` package at 7.8.5 is what resolves the version range in the `version` input against the published pnpm versions, and `zod` at 3.22.4 validates the action's own inputs, which is a good practice for an action that takes a user supplied version range.
The `expand-tilde` dependency handles the `dest` input, so a path like `~/pnpm` resolves to the home directory rather than being taken literally.
The outputs are minimal, which suits a setup action. `dest` is the expanded path of the `dest` input, and `bin_dest` is the location of the `pnpm` and `pnpx` commands, which is what a later step needs on its PATH.
How the action is built and shipped
The repository is a TypeScript action bundled with esbuild, and the packaging choice is worth noting because it is a common source of confusion in GitHub Actions.
The build script bundles the source into a single file.
"build:bundle": "esbuild src/index.ts --bundle --platform=node --target=node24 --format=cjs --minify --outfile=dist/index.js --loader:.json=json"So the source is TypeScript in `src/`, and the published artefact is a bundled, minified CommonJS file at `dist/index.js`, targeting Node 24. The `dist/` directory is checked into the repository, which is required for a JavaScript action, since GitHub Actions runs what is in the repository rather than building it at run time. The `run.sh` script at the root is the entry point the action metadata points at.
The `start` script is `pnpm run build && sh ./run.sh`, and there is an `update-bootstrap` script that runs a Node script in `scripts/`, which is how the bundled runtime gets refreshed.
The action metadata itself is in `action.yml` at the root, where the inputs, outputs and runtime are declared, and the `docs/` directory is absent, which is consistent with the documentation living in the README.
The rest of the repository is the usual set of repository hygiene files. There is a `pnpm-lock.yaml` and a `pnpm-workspace.yaml`, so the action builds itself with the tool it installs, which is a nice touch. There is a `renovate.json` for dependency updates, an `.editorconfig`, a `tsconfig.json`, a `LICENSE.md` and a `CODE_OF_CONDUCT` is absent from the top level list, though the README badge in the upstream project references one.
The licence is MIT, the primary language is TypeScript, and the homepage points at the GitHub Marketplace listing, setup-pnpm, rather than at a separate documentation site, which is where the action's own README and its usage examples are.
Editorial conclusion
Adopt pnpm/action-setup if your workflow pins pnpm v10 or v11 and you want to keep the familiar two step setup with actions/setup-node. Do not adopt it for pnpm v12 or newer, because the README states that pnpm/setup installs the self-contained release binary and a JavaScript runtime in one step and is the recommended path. Verify first that the pnpm version you need has a standalone binary for the runner platform, since pnpm/setup cannot install pnpm v11 on Intel macOS, and that your cache key still matches the lockfile path you use after any rename.
Frequently asked questions
Should I use pnpm/action-setup or pnpm/setup?
The README says pnpm/action-setup supports pnpm v12 and earlier, and that pnpm/setup is available for pnpm v11 and newer, installing pnpm's standalone release binary and optionally a Node.js, Bun or Deno runtime in the same step. You can keep using pnpm/action-setup with actions/setup-node for v11 and v12.
What is the difference between the run_install and install inputs?
In pnpm/setup the input is renamed to install, it runs pnpm install automatically when a package.json is present with install true by default, and the object or array form with recursive, cwd and args is not supported, so those commands go in separate steps.
How does the pnpm cache work in pnpm/action-setup?
The cache input caches the pnpm store directory, and cache_dependency_path names the lockfile whose contents hash becomes the cache key, defaulting to pnpm-lock.yaml and accepting multiple paths delimited by newlines. The default is false for the cache input.
Can pnpm/action-setup install pnpm without Node.js?
Yes, for pnpm v11 and earlier the standalone input installs the @pnpm/exe package so pnpm runs without Node.js. For pnpm v12 the input has no effect, because the plain pnpm package already installs a standalone native executable.
What happens if I do not set the version input?
The version input is optional when there is a packageManager or devEngines.packageManager field in package.json, and otherwise it is required. It accepts exact versions, ranges such as 10 or 10.9.x or ^10.9.8, or latest.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/pnpm-action-setup)Was this useful?