README 未给出安装命令细节,安装方式需参考官网 Installation 页面;仓库含实验性 Rust 移植版 pacquet,非默认 CLI;pnpr/ 目录采用 PolyForm Shield 许可,与主体 MIT 不同

pnpm
pnpmMIT活跃维护快速、省磁盘空间的 JavaScript 包管理器,用硬链接共享依赖,装包更快、占用更小,适合替代 npm/yarn。
Fast, disk space efficient package manager
npm install -g pnpmREADME 未说明硬件要求,仅说明支持 Windows、Linux 和 macOS
pnpm 是快速省磁盘的 Node.js 包管理器,用硬链接共享依赖,适合 monorepo
快速、省磁盘空间的 JavaScript 包管理器,用硬链接共享依赖,装包更快、占用更小,适合替代 npm/yarn。
核心能力
- node_modules 文件从单一内容寻址存储硬链接而来
- 严格依赖隔离,包只能访问 package.json 声明的依赖
- 用 pnpm-lock.yaml 锁文件保证安装结果确定
- 支持 workspaces,适合 monorepo 多包管理
- 可兼作 Node.js 版本管理器,支持 Windows/Linux/macOS
容易踩的坑
查看更新说明
pnpr 0.1.0-alpha.18 keeps hosted package metadata in SQLite or a shared libSQL database, logs release records in transparency logs, and accepts packages with platform variants. The
documentsmetadata backend is gone, so packages hosted by an earlier pnpr have to be published again.Minor Changes
Metadata storage
-
pnpr now keeps hosted package metadata in SQL only. By default it uses a SQLite database at
<storage>/.metadata/metadata.sqlite. Themetadatablock names another database by URL, such asurl: sqlite:./metadata.sqlite. Thedocumentsmetadata backend is removed, and a config that setsmetadata.backendormetadata.pathis refused.pnpr does not import the metadata of an existing store. A store that kept its metadata as documents starts with empty metadata, so republish its packages after upgrading. An
s3:store that hosts packages needs a libSQLmetadata.url.migrate-storagemoves archives only and needs that libSQL database to hold the metadata already. -
pnpr can keep hosted package metadata in a libSQL database, such as Turso, shared by several pnpr instances. Set
metadata.urlto alibsql://URL. It works with ans3:block, so archives stay in object storage. Withmetadata.replicaPath, each instance reads package documents from a local replica that syncs everymetadata.syncInterval. Permission checks and the reads a write depends on always read the primary. -
pnpr refuses any change to a published npm version's manifest, and never accepts an unpublished version again. pnpr records who moved each dist-tag, and when. Hosted npm package responses carry a
pnpr-generationheader. -
A reader sees all of a publish or batch publish, or none of it. A retried publish gets its original response instead of a 409. Batch publishes accept an
Idempotency-Keyheader. pnpr records each publish as a publication and serves it at/-/publications/<org>/<id-or-name>. -
pnpr stores release notes for package versions and publications. A publish can include them in a
notesfield. Publishers can edit or delete a note later. npm clients read a version's note at/npm/<name>/<version>/notes. A package's notes are listed at/npm/<name>/-/notes. A publication's note is at/-/publications/<org>/<id-or-name>/notes.
Publishing
-
A hosted pnpr registry rejects a publish whose version metadata disagrees with the
package.jsoninside its archive. Its400response names the package, the version, and each differing field. pnpr checks the dependencies, the platform fields,bin, and the install scripts. pnpr also rejects a publish whose archive does not decode or holds more than onepackage.json.pnpr accepts the rewrites that npm and older clients make while publishing, such as a
binstring expanded into an object. pnpr publishes a version without semver build metadata. pnpr serves a version's checked fields as its archive states them, withhasInstallScriptand_hasShrinkwrapalways set. Other fields, such asdescription, are served as submitted. -
pnpr accepts release archives uploaded by integrity before the publish that references them, through
PUT /-/pnpr/v0/artifacts/blob?integrity=<sha512-…>without an owner #17608. An npm publish, alone or in a batch, can then reference a staged archive: the attachment carries the archive'sintegrityin place ofdata. A version and its platform variants therefore no longer have to fit in one request body. An archive the publishing account has not staged, or one that has expired, fails the whole publish. -
Trusted-publishing workload credentials can stage archives for the packages they are configured for, and send batch publish commits for those packages. A batch entry for any other package, or of another ecosystem, is refused.
-
A hosted registry that declares
tarballs: tarnow stores each published version as one tar compressed with zstd at level 19
-
- v11.28.11pnpm 11.28.112026-11-05 · 2026-11-05 01:00 UTC
查看更新说明
pnpm 11.28.11 fixes frozen installs with
excludeLinksFromLockfile,pnpm linkin workspaces,pnpm deploywith dangling symlinks, andverifyDepsBeforeRunstarting needless installs.Patch Changes
Installing packages
-
pnpm deploynow keeps a symlink in the project whose target is missing from the source, such as a link into anode_modulesdirectory that was removed after the build. Deploy used to fail withENOENTon such a link #17571. -
A package with
bundledDependenciesand a build script now keeps its bundled dependencies when it is restored from the side-effects cache #17523. -
pnpm installnow links the runtime that an earlierpnpm install --no-runtimeskipped #17542. -
Commands of a package whose
binpaths contain excess parent directory segments, such as../dist/cli.js, are no longer missing. Such paths now resolve inside the package #17586. -
Generated POSIX shell shims now quote their paths, so shell special characters in a path stay literal.
-
A repeat
pnpm installnow rewrites the bin shims afterextendNodePathchanges. Before, it reported "Already up to date" and the shims kept theNODE_PATHof the previous setting.
Lockfile and resolution
-
pnpm install --frozen-lockfilenow accepts the lockfile it wrote withexcludeLinksFromLockfileandlinkWorkspacePackageson, when a project depends on a workspace package through a plain version range or acatalog:entry. It used to fail withERR_PNPM_OUTDATED_LOCKFILE. -
pnpm install --frozen-lockfile,pnpm approve-builds, andpnpm rebuildnow accept a lockfile that resolves a*dependency to a prereleaselatestversion. pnpm wrote such a lockfile and then reported it as outdated #17594. -
Packages from the default registry keep plain lockfile keys, even when a prefix such as
npmjspoints at the registry set asregistry. A dependency written with such a prefix shares the plain entry of the same package. The next install rewrites keys that earlier versions qualified this way #17575. -
Relative local paths in root
overridesnow resolve from the workspace root when each project has its own lockfile #17691.Installing a local directory dependency no longer fails when another project's install is writing a lockfile in that directory.
-
Peer deduplication no longer gives a project different copies of a dependency across direct and transitive paths when an optional peer has no provider #17666.
-
A Node.js version range such as
>=26.13, for example indevEngines.runtime, now resolves to the newest stable release that satisfies it. pnpm picks a prerelease only when no stable release matches #17516.
verifyDepsBeforeRun
-
With
verifyDepsBeforeRun,pnpm runandpnpm execnow report dependencies as out of date after a dependency is added to thepackage.jsonof a local directory dependency, such as"lib": "file:../lib". Before, the command ran without the new dependency installed. -
verifyDepsBeforeRunno longer reports dependencies as out of sync when only theversionfield of a single-project repository changed #17560. The same holds for a workspace project that no dependency can resolve to. A script run after such a change no longer starts an install first.
pnpm link
- In a workspace,
pnpm link <dir>now adds thelink:dependency to thepackage.jsonof the project where the command runs, not to the workspace root'spackage.json. The link is created in that project'snode_modules
-
- v12.18.0pnpm 12.18最新正式版2026-11-05 · 2026-11-05 00:56 UTC
pnpm 12.18.0 packs, publishes, and installs packages with platform variants on pnpr registries. It also adds per-skill approval of agent skills and
pnpm store addfor offline installs from downloaded tarballs. Repeat installs andverifyDepsBeforeRunno longer read thepackage.jsonof unchanged workspace projects. The release fixes several peer dependency resolution bugs too.Minor Changes
Agent skills
-
pnpm now names the link to a dependency's agent skill after the skill alone. A skill that the
@acme/kitpackage ships inskills/auth/is linked as.claude/skills/auth, not.claude/skills/pnpm-@acme+kit-auth. The next install replaces links with the old names. pnpm lists the linked skills in a# pnpmblock of each agent skill directory's.gitignore#17455.When two approved packages ship a skill of the same name, or the name is already taken in an agent skill directory, pnpm links the skill as
pnpm-<package>-<skill>. Before, the install failed. -
pnpm approvenow asks which agent skills to link when a package ships more than one. pnpm records the chosen skills as a list, such aspermissions.<pkg>.skills: [guide, migrate], and does not offer the other skills for approval again. The first time a project approves a skill,pnpm approvealso asks which agent directories to link skills into, and records the answer underskills.dirs. -
pnpm links agent skills nested in category directories, such as
skills/engineering/implement/SKILL.md, up to three levels belowskills/. Before, it linked only the skills directly underskills/.
Platform variants
These features need a registry declared with
serverType: pnpr.-
pnpm packpacks one archive per entry ofpublishConfig.variants, each platform variant as<name>-<version>~<tag>.tgz.pnpm pack --variant <target>packs only the archive whose entry lists that target.pnpm pack --jsonprints theintegrityandsizeof every archive it writes. -
pnpm publishpublishes a package'spublishConfig.variants. pnpm uploads every archive before the publish request that references them. Publishing variants to any other registry is refused unless--no-variantsis given, which publishes only the archive that targetsany. -
pnpm publish --upload-variant <target>uploads the archive of onepublishConfig.variantsentry to the registry's staging area and prints<target>=<integrity>.pnpm publish --variant-integrity <target>=<integrity>then publishes the version from archives that other jobs uploaded. With--recursive, each value names its package as<name>~<target>=<integrity>. -
pnpm publish -r --batchnow uploads each package archive on its own request and skips archives the registry already holds, so the batch request no longer grows with the archives it publishes. A batch of more than 256 packages still carries every archive inline. Packages withpublishConfig.variantscan be published in a batch. A batch with variants that would reference more than 256 archives on one registry fails withERR_PNPM_BATCH_PUBLISH_TOO_MANY_ARCHIVESpnpm/tasks#244. -
pnpm publish --provenancesigns one statement that names every archive of a version withpublishConfig.variants. A platform variant's archive is named by the version's package URL with avariantqualifier. -
Rerunning
pnpm publishafter the version was already published now succeeds when the published version is the same release. pnpm compares the archives, the provenance statement when the rerun signs one, and the dist-tag. When the published version differs, the publish fails withERR_PNPM_PUBLISHED_RELEASE_DIFFERS, which names what differs. -
pnpm installs the platform variant of a package that fits the host, or the package's own archive when none does. The lockfile records every variant. A version published with variants only,
-
- v11.28.10pnpm 11.28.102026-10-30 · 2026-10-30 21:18 UTC
查看更新说明
pnpm 11.28.10 stops
pnpm store prunefrom deleting other stores whencacheDirpoints to their parent directory. It also fixes globally installed commands that load hoisted dependencies, and repeat installs that missed changes to local dependencies.Patch Changes
Installing packages
-
pnpm store prunepreserves other stores and global package data whencacheDirpoints to their parent directory. -
Commands installed with
pnpm add --globalnow find the dependencies that pnpm hoists for their package. A package that loads a dependency it does not declare, such as a native addon's platform-specific package, failed with "Cannot find module". Reinstall such a package withpnpm add --globalto update its existing command #17503. -
pnpm prune --prodno longer fails withERR_PNPM_EXDEVwhennode_moduleswas copied from an earlier Docker build stage #17424. -
pnpm installnow retries a Node.js runtime zip download when the connection drops partway through. A download that still fails names its URL. Before, a single dropped connection ended the install withterminated#17411. -
With the global virtual store, a change to a dependency of one package in a dependency cycle now gives every package in that cycle a new directory. Before, the other packages kept their directories and still linked the old copy of the changed package, so the project could load two copies of it #17466.
Packages in a dependency cycle, and packages that depend on one, move to new global virtual store directories once after this update. Those that run a build miss the side-effects cache once.
-
pnpm installandpnpm rebuildnow refresh privately hoisted.binshims innode_modules/.pnpm/node_modules/.binafter a dependency build replaces a script target with a native executable #17402. -
The Node.js
latestselector now chooses the newest stable release #17490. -
The standalone
@pnpm/exebuilds now embed Node.js 26.13.0.
Repeat installs and lockfiles
-
pnpm installnow resolves a local directory again after itspackage.jsonchanges when an override or a package extension adds it to the dependencies of a registry package.pnpm install --frozen-lockfilefails on a lockfile that still records the old dependencies of such a directory #17486. -
With
injectWorkspacePackagesand per-project lockfiles,pnpm installnow updates a project's lockfile when a local tarball that an injected workspace project depends on is replaced. The project's lockfile kept the old version and integrity before. -
pnpm installnow detects a change to a local tarball or directory that only a pnpmfilereadPackagehook depends on. A repeat install reported "Already up to date" and kept the old contents before pnpm/tasks#227. -
pnpm installnow relinks aworkspace:orlink:dependency whose link was deleted fromnode_modules. It used to report "Already up to date" and leave the link missing #17485. -
Merging git branch lockfiles now keeps a workspace project whose directory is named
__proto__. It was dropped from the merged lockfile before pnpm/tasks#59.
Adding and publishing packages
-
pnpm addno longer rewrites a catalog entry set to the dist-tag that the dependency resolves through. For example, an entrybetastaysbetaafterpnpm add foo@betaorpnpm add foo. Before, the entry was replaced with the version the tag pointed to pnpm/tasks#225. -
pnpm packand `pnpm publish
-
- v12.17.0pnpm 12.172026-10-30 · 2026-10-30 14:24 UTC
查看更新说明
pnpm 12.17.0 adds
pnpm peers check --global, dependency-group selectors and wildcards inoverrides, and runtime, package manager, Cargo, and Python updates inpnpm outdatedandpnpm update. It also fixes files that other users could not read in Docker images, and repeat installs that missed changes to local dependencies.Minor Changes
-
pnpm peers checknow accepts--global(-g) to check globally installed packages. After a global install or update, the peer dependency warning now suggestspnpm peers check -g#17504. -
pnpm outdatedandpnpm updatenow inspect and update package manager and runtime versions indevEngines.packageManager,packageManager,devEngines.runtime,engines.runtime, andruntime:dependencies. Withcargo.enabledorpython.enabled,pnpm outdatedandpnpm updatealso inspect and update Cargo dependencies inCargo.tomlandCargo.lockand Python dependencies inpyproject.tomlandpylock.toml. -
overridesselectors now support:prod,:optional, and:peerpseudo-selectors that target a single dependency group. They also support*wildcard patterns on parent and target package names. An override with a non-range value, such asnpm:orfile:, no longer adds a peer dependency todependencies. Removing an optional dependency with"-"now also removes the duplicate entry fromdependencies#5391.
Patch Changes
Installing packages
-
Files that pnpm creates in a project now get the permissions the umask gives any new file, such as
0644. Before, several of them were readable only by the user who ran pnpm, which broke Docker images that run as a different user #17435.The fix applies to:
node_modules/.pnpm-workspace-state-v1.json. A different user runningpnpm runreinstalled the dependencies because it could not read this file.pnpm-workspace.yaml- the files written by
pnpm deploy - patch files from
pnpm patch-commit - the lockfile restored by
pnpm dedupe --check - the Cargo and Python files that pnpm writes
When pnpm edits an existing file, the file keeps its permissions.
-
pnpm installno longer writes broken dependency links when the project'snode_modulesis a symlink to another directory, such as another project'snode_modules. The install reported success, but the links it wrote did not resolve #17448. -
Commands installed with
pnpm add --globalnow find the dependencies that pnpm hoists for their package. A package that loads a dependency it does not declare, such as a native addon's platform-specific package, failed with "Cannot find module". Reinstall such a package withpnpm add --globalto update its existing command #17503. -
When pnpm switches to the version a project pins, it now installs that version's native binary for the current host, even if the project's
supportedArchitecturesexcludes the host. Before, pnpm could not use the pinned version and kept running the installed one. pnpm also repairs a pinned version that an earlier install left without the host's binary. -
With the global virtual store, a change to a dependency of one package in a dependency cycle now gives every package in that cycle a new directory. Before, the other packages kept their directories and still linked the old copy of the changed package, so the project could load two copies of it #17466.
Packages in a dependency cycle, and packages that depend on one, move to new global virtual store directories once after this update. Those that run a build miss the side-effects cache once.
-
With
nodeLinker: hoisted, when two workspace projects need the same package version and it cannot be
-
用户点评
登录用户的真实使用记录,可按版本和硬件筛选还没有人点评。第一个说出真实体验的人最有价值。
简体中文 | 日本語 | 한국어 | Italiano | Português Brasileiro
Fast, disk space efficient package manager:
- Fast. Up to 2x faster than the alternatives (see benchmark).
- Efficient. Files inside
node_modulesare linked from a single content-addressable storage. - Great for monorepos.
- Strict. A package can access only dependencies that are specified in its
package.json. - Deterministic. Has a lockfile called
pnpm-lock.yaml. - Works as a Node.js version manager. See pnpm runtime.
- Works everywhere. Supports Windows, Linux, and macOS.
- Battle-tested. Used in production by teams of all sizes since 2016.
- Experimental Rust port. Includes pacquet, an experimental port of the CLI written in Rust.
- See the full feature comparison with npm and Yarn.
To quote the Rush team:
Microsoft uses pnpm in Rush repos with hundreds of projects and hundreds of PRs per day, and we've found it to be very fast and reliable.
Platinum Sponsors
Gold Sponsors
Silver Sponsors
Support this project by becoming a sponsor.
Background
pnpm uses a content-addressable filesystem to store all files from all module directories on a disk. When using npm, if you have 100 projects using lodash, you will have 100 copies of lodash on disk. With pnpm, lodash will be stored in a content-addressable storage, so:
- If you depend on different versions of lodash, only the files that differ are added to the store.
If lodash has 100 files, and a new version has a change only in one of those files,
pnpm updatewill only add 1 new file to the storage. - All the files are saved in a single place on the disk. When packages are installed, their files are linked from that single place consuming no additional disk space. Linking is performed using either hard-links or reflinks (copy-on-write).
As a result, you save gigabytes of space on your disk and you have a lot faster installations.
If you'd like more details about the unique node_modules structure that pnpm creates and
why it works fine with the Node.js ecosystem, read this small article: Flat node_modules is not the only way.
💖 Like this project? Let people know with a tweet
Getting Started
Benchmark
pnpm is up to 2x faster than npm and Yarn classic. See all benchmarks.
Benchmarks on an app with lots of dependencies:
License
MIT, except the pnpr/ directory, which is source-available under the PolyForm Shield License 1.0.0.