Commit Graph
25 Commits
Author SHA1 Message Date
Zoltan Kochan b3eee14a96 docs(cli): correct the command reference from access to init (#17247)
Part of pnpm/tasks#191.

Wrong claims, fixed on the v12 page and on the v11 twin where it had
the same text:
- audit: `--interactive` implies `--fix=override`; `info` is a valid
  audit level.
- change check validates the pending intents.
- deploy copies the publish packlist unless `deployAllFiles` is set.
- deprecate: an empty message fails, use `pnpm undeprecate`.
- deprecate, dist-tag: only `--otp` supplies the one-time password.
- dist-tag add defaults to `latest`, not the `tag` setting.
- docs takes exactly one package.
- env: there is no `add` subcommand, and `list` queries the Node.js
  mirror only.
- v12 only: clean no longer says it uses Node.js, add no longer
  presents `-w` as an alias, the deploy package-manager-pin history
  is no longer contradictory, doctor sample shows store v11.

Missing facts:
- add: `--save-prefix`, `--save-build`, `--no-save-peer`,
  `--no-save-types`, `--lockfile-only`, `--force`; where Yarn vs npm
  and Bun pins go; catalog and configDependencies links.
- access status shorthands; approve-builds error codes, the
  placeholder value and the immediate rebuild; audit exit code,
  `--optional`, `--production`, and how to make `--ignore` write
  `audit.ignore`; `--ignore` exits with code 0 and
  `--ignore-unfixable` fails on an advisory without a GHSA ID.
- bugs and docs `--registry`; ci accepts install options;
  clean script override and modulesDir; config `--location` type and
  `get` output; create name mapping, `--shell-mode`, `--cpu`, `--os`,
  `--libc`; dedupe flags; deploy error codes and Dockerfile WORKDIR;
  dist-tag aliases and web OTP; env `--global` requirement; exec
  recursive options and PNPM_PACKAGE_NAME; fetch `--ignore-pnpmfile`,
  lockfile requirement, optional pnpmfile in the Dockerfiles.
- usage, examples, and output for bin, cache, cache list, cache
  delete (with the no-argument warning), cache view, cat-file,
  cat-index, find-hash, ignored-builds, import, and init
  (`initPackageManager`, `initType`, ERR_PNPM_PACKAGE_JSON_EXISTS).

Stale history on v12 pages: removed "Added in" markers for v10 and
v11 and rewrote "Since v11..." passages as current behavior in
access, add, approve-builds, audit, bugs, cache-list-registries,
cache-path, cache-prune, change, ci, config, create, deploy,
deprecate, dist-tag, docs, doctor, help, ignored-builds, and init.

Review follow-up: cat-file now says it rejects the hex digest that
cat-index prints; the settings index links initPackageManager and
initType; `change check` says it plans the release without reporting
it (both versions); `pnpm bin` follows a custom modulesDir.
2026-10-23 00:49:08 +02:00
Zoltan Kochan cb3f29bc0a docs(cli): correct the command reference from install to with (#17251)
Part of pnpm/tasks#191.

Wrong claims, fixed in the v12 docs and, where the same text is wrong
for v11, in the v11 docs:
- logout: drop the nonexistent --scope option.
- patch: the edit dir is node_modules/.pnpm_patches/<name>@<version>;
  drop the "*" special case.
- patch-commit: fix the ---patches-dir heading.
- prefix: describe the real marker walk instead of "closest package.json".
- setup: setup installs pnpm as a global package and writes pn/pnpx/pnx.
- start, test: "run start" and "run test" are not aliases.
- unlink: drop the system-wide and link --global wording.
- unpublish: a package name is required; --otp has no env var; --registry
  wording.
- update: --depth is dependency depth, not directory depth.
- version: --tag-version-prefix defaults to the tagVersionPrefix setting.
- view: the first argument is always the package.
- why: drop --global and --only-projects; --exclude-peers has no effect;
  --prod includes optionalDependencies.
- install: recursiveInstall spelling; replace the stale ci-info snippet.
- v12 only: pack-app runtime default and builder download, pnx
  provisioning list and cmd.exe typo, tasks sample priority.

Missing flags, settings, and error codes on the v12 pages: install (about
twenty flags), lane, licenses, link, list, outdated, owner, pack-app path
rules, pack, patch, patch-remove, peers, permissions, ping, pipeline, pm,
pnx, prune, publish, rebuild, recursive, remove, repo, root, run,
runtime, sbom, search, self-update, set-script, setup, shim, stage, star,
start, store, tasks, team, test, token, unlink, unpublish, update,
version, view, why, with.

Stale history on the v12 pages: removed "Added in" markers older than
v12 and rewrote "Since v11.x" and "In v11" sentences as current behavior
(login, logout, licenses, link, outdated, patch, pnx, publish, runtime,
sbom, self-update, setup, update, and others).

Review follow-up: patch's default edit directory is named after the
argument as typed (both versions); self-update installs the unscoped
package only for pnpm 12 and newer; only --no-bail is restricted;
npm_package_* covers name, version, config, engines and bin; prefix -g
prints the parent of root -g; --optional no longer claims to override
--no-optional.
2026-10-23 00:47:42 +02:00
Zoltan KochanandClaude Opus 5.5 6f95957063 docs: lint prose with Vale (#17238)
* docs: lint prose with Vale

Add Vale with an in-repo style, .vale/styles/pnpm, that turns the
writing rules in AGENTS.md and the Google developer documentation style
guide into lint rules. The stock Vale packages (Google, Microsoft,
RedHat, write-good) were too noisy to block on, for example 1,300
passive-voice hits in the v12 docs alone, so the rules are written for
this repo, following the GitLab model. Each one links the guideline it
enforces.

Levels:
- error, fails CI: dashes, plain-word substitutions, condescending
  words, "please", "note that", hedges, puffery, optional plurals,
  exclamation marks, ellipses, curly quotes, generic link text, product
  spellings, sentence-case headings, repeated words, double spaces,
  implementation history in comments; in changesets, bold or italic
  emphasis, internal names and release-line names.
- warning: future tense, sentences over 30 words, "instead of" and
  "so that" tails in changesets.
- suggestion: passive voice.

.vale.ini scopes the rules. Docs get every rule. Contributor Markdown
and code comments keep dashes and headings as warnings until their
roughly 8,100 em dashes are rewritten. Released changesets stay in
.changeset/ and are not rewritten, so lint-prose.mjs lints only the
changesets added since PROSE_BASE (the PR base in CI).

The prose workflow installs a pinned, checksum-verified Vale release and
runs `pnpm lint:prose`. The rest of this change rewrites the existing
docs, READMEs, contributor Markdown, and code comments to pass the
error-level rules. Only prose and comment text changed. Renamed
headings keep their anchors.

Spelling stays with cspell, which checks identifiers that Vale does not
see.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* docs: keep prose lint from flattening meaning

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-22 21:48:09 +02:00
Zoltan Kochan 674c3088b9 fix(setup): allow installation without registry access (#17170)
Handle registry read and environment-write failures in setup's existing
post-install outcome handler. Keep installation separate from environment
persistence, as the missing-shell-config fallback already does.

Print session-local PowerShell assignments and profile instructions when
registry persistence is unavailable. Preserve the original diagnostic and
leave environment conflicts and other failures fatal. Do not attempt to
replace an unreadable persisted PATH or elevate to another Windows user.

Apply the behavior in both CLI versions, with regression tests for read and
write failures and literal quoting of ASCII and typographic apostrophes.

Closes pnpm/pnpm#17167.
2026-10-20 22:26:48 +02:00
Zoltan Kochan e4d91d6d4c fix(licenses): align lockfile and empty result handling (#17165)
Keep license reporting scoped to importers recorded in the selected lockfile. An unrecorded workspace package contributes no dependencies; it must not crash or inherit the root importer's dependency list.

Require the lockfile in the Rust CLI, matching the existing TypeScript error. Render empty license reports according to the selected output format in both CLIs.

Closes pnpm/tasks#174.
2026-10-20 19:18:42 +02:00
Zoltan Kochan b6b53dbf28 fix: generate v11 SBOMs from dedicated workspace lockfiles (#17163)
Load dedicated lockfiles for selected and reachable workspace projects when
sharedWorkspaceLockfile is false. Re-key their importers to the workspace root
before SBOM collection, and merge package entries without losing required
package status. Reject conflicting package data to avoid emitting an inaccurate
SBOM. Fail when a selected or reachable project lacks a lockfile importer.
Read directory package metadata relative to the project that owns its lockfile.

Fixes pnpm/tasks#170.
2026-10-20 19:05:37 +02:00
Zoltan Kochan 473cccecef fix(prune): remove extraneous direct deps and honor workspace selection (#17154)
Fix three `pnpm prune` issues across pnpm v11 and pnpm v12:

1. Extraneous direct dependencies in `node_modules`:
   - In pnpm v11, `prune.handler` did not disable `optimisticRepeatInstall`, and `installDeps` could short-circuit via `canReportAlreadyUpToDate` before `headlessInstall` ran `prune()`. In addition, `pruneRemovedDependencies` skipped `prune()` when `currentLockfile` was absent (for example, when a project had zero dependencies). Disable `optimisticRepeatInstall` in `prune.handler`, prevent `canReportAlreadyUpToDate` when `pruneDirectDependencies` or `pruneStore` is set, and pass an empty `currentLockfile` to `prune()` when `pruneDirectDependencies` is enabled and no current lockfile exists.
   - In pnpm v12 (`pacquet`), `prune_stale_modules` only unlinked direct dependencies that were present in `current_lockfile` and removed from `wanted_lockfile`, never scanning `node_modules` on disk for extraneous entries when `prune` ran. Add `PruneTreeOptions::direct_dependencies` and `PruneExtraneousDirectDeps` to scan each selected importer's `node_modules` directory during `pnpm prune`, remove entries (and their bin shims and emptied scope directories) that are not wanted direct dependencies, excluded manifest links, or root public hoists, and force `commit_modules_state`'s virtual-store sweep during `prune`.

2. `pnpm --filter <pkg> prune` and `pnpm -r prune` in pnpm v11:
   - Separate `cliOptionsTypes` from `rcOptionsTypes` in `@pnpm/installing.commands` `prune` and add `'recursive': Boolean` so the CLI parser accepts `-r` / `--recursive` and `--filter`.
   - Do not pass `include` to `validateModules` when `pruneDirectDependencies` is set so `prune --prod` does not purge every workspace project's `node_modules` directory.
   - Do not auto-include the workspace root in `shouldInstallWorkspaceRoot` during filtered `prune`.
   - Scope `pruneDirectDependencies` to the selected `ctx.projects` and keep all dependency groups in `findOrphanDepPaths` / `getPkgsDepPathsOwnedOnlyByImporters` during a partial workspace `prune` so unselected workspace importers do not lose their devDependencies from the shared virtual store.

3. Workspace selection and `sharedWorkspaceLockfile: false` in pnpm v12:
   - Add `CliCommand::Prune(_)` to `CliCommand::recursive_by_default`.
   - Route `PrunePipeline` through `select_install_family_plan` (`PerProject`, `Shared`, `Single`) and pass `WorkspaceInstallSelection` (with `install_dirs` restricted to `selected_dirs`) into `Install::run_prune`.

Closes https://github.com/pnpm/tasks/issues/171
2026-10-20 17:07:56 +02:00
Zoltan Kochan 7b0d6873a6 feat: pin tar hashes with lockfile.integrityTarget and address revisions by tar digest (#17092)
lockfile.integrityTarget: tar makes the integrity of every package tarball
entry the hash of its uncompressed tar, recorded as settings.integrityTarget.
The lockfile then survives a registry recompressing its tarballs, switching
to tar resources, or being replaced by a mirror that does either. A lockfile
recorded under another target is stale: a frozen install fails with
ERR_PNPM_LOCKFILE_CONFIG_MISMATCH, and any other install re-resolves with
update-checksums semantics so no hash of the old kind carries forward. The
setting is opt-in and the lockfile version is unchanged.

The tarball crate now reports both hashes of every extraction: the resource
after content decoding, and the tar a .tgz decodes to. A pin names one of
them (IntegrityKind::Resource / Tar), or either at resolution, where a locked
or published integrity may be of either kind (ResourceOrTar, sha512 only).
Under a tar pin every gzip member is decoded and nothing may follow the tar.
The resource pin keeps today's behaviour, extracting the first member and
tolerating trailing data, but then records no tar.

Store rows extracted from a .tgz record tarIntegrity and get an alias under
the tar key, in a table pnpm v11 never reads. Store lookups follow aliases,
so a tar-pinned frozen install is served offline by a store that .tgz
installs populated, and resolution takes a version's tar hash from its row
before downloading anything.

Registry revisions now always pin their tar, revision 0 included, and are
fetched with a tar pin, so the digest route can use any content coding.
Revision metadata must list revision 0 and the selected revision, and a
digest-route URL without a revision is rejected. pnpr keys its digest
references by tar hash on every registry format, serves the route as a
negotiated tar resource, and projects revision 0 explicitly. pnpm v11 cannot
extract tar resources, so it now rejects revisions with
ERR_PNPM_REGISTRY_REVISIONS_UNSUPPORTED.

Implements pnpm/rfcs text/0000-tar-integrity-for-every-source.md and
pnpm/rfcs#42.
2026-10-18 17:36:30 +02:00
Zoltan Kochan cb5cc84ac8 fix(setup): succeed when no shell config file can be found (#17079)
`pnpm setup` treated ERR_PNPM_UNKNOWN_SHELL and ERR_PNPM_NO_SHELL_CONFIG
as fatal. In containers SHELL is usually unset, so setup exited non-zero
and the get.pnpm.io installer failed, although the pnpm binary and bins
were already in place.

Both errors now mean only "no shell config file can be updated". Setup
continues with the GitHub Actions env files and legacy shim cleanup,
then prints the reason and the PNPM_HOME/PATH lines to add manually, and
exits 0. Errors that indicate a real conflict or an unsupported shell
still fail the command.

Implemented in the Rust v12 CLI and the TypeScript v11 CLI with the same
message.

Related to pnpm/pnpm#4495, pnpm/pnpm#6217, pnpm/pnpm#16973.
2026-10-18 11:48:47 +02:00
Zoltan Kochan 4255419bad fix(self-update): read the project pin where the pre-command pass reads it (#17026)
`pnpm self-update` located the pnpm pin on its own: it read only
`package.json` in `--dir`. Run inside a workspace package, it missed the
pin in the workspace root's manifest, left the pin alone, and switched the
global pnpm instead. Under Corepack or Homebrew it refused outright. A pin
in `package.yaml` or `package.json5` was missed the same way.

`PinRoots`, the pre-command pass's pin locator, moves to `package_manager`
and becomes the one place both read from. The manifest at the workspace
root (or `--dir` outside a workspace) holds the pin, in whichever basename
it uses, and the env lockfile directory follows `lockfileDir`.
self-update now writes the manifest it read back in its own format and
records `packageManagerDependencies` where the pre-command pass reads them.

The Corepack/Homebrew refusal for a project without a pin now runs after
config loads, so it reads the pin through the same locator. The wasm
refusal still runs before.

pnpm v11 already reads the pin from the workspace root, so this is a
v12-only fix.

Part of https://github.com/pnpm/tasks/issues/144
2026-10-17 13:21:47 +02:00
Zoltan Kochan 74ad723eca fix(self-update): update the project pin under Homebrew or Corepack (#17003)
`pnpm self-update` refused to run when Homebrew installed pnpm or
Corepack ran it, even in a project that pins pnpm. The refusal guards the
global switch, which would install a second pnpm shadowed by the one on
PATH. Writing the pin touches nothing Homebrew or Corepack manages.

Both CLIs now skip only the global switch under an external manager and
report it after the pin update. Without a pnpm pin the command still fails
with ERR_PNPM_CANT_SELF_UPDATE_IN_HOMEBREW / _IN_COREPACK.

In pnpm v12 the check stays in the dispatcher before config is loaded. It
now reads package.json from the same directory as the handler to decide
whether a pin exists.

Closes pnpm/pnpm#17001
2026-10-16 23:35:56 +02:00
Max Schwenk e22d34bd3b fix(pkg): normalize the repository field in pkg fix (#16981)
`pnpm pkg fix` left `repository` as written. It now follows the
fixRepositoryField step of `npm pkg fix`: a non-empty string becomes
{ "type": "git", "url": <string> }, and a url that hosted-git-info
recognizes becomes https() for a shortcut and the form of its own
protocol otherwise. Unrecognized urls, other keys, and a shortcut with
no owner stay as written. The legacy `repositories` array step is not
ported.

The TypeScript CLI uses the hosted-git-info fork the git resolver
already depends on. The Rust CLI adds HostedGit::normalized_repository_url,
because HostedGit's Display renders the git and http forms differently
from hosted-git-info's toString(). Rust does not recognize gist urls, so
a `gist:` repository keeps its url there, while the TypeScript CLI
normalizes it like npm.

Closes pnpm/pnpm#16980
2026-10-16 21:02:50 +02:00
a156c4e11f fix(deploy): bind a linked workspace package's peer to what its parent provides (#16809)
Without injectWorkspacePackages, pnpm deploy failed with
ERR_PNPM_DEPLOY_AMBIGUOUS_PEER when a linked workspace package's peer had
more than one resolution in the deployed graph, even when the deployed
project depended on the peer itself. In the issue, the project depends
on the workspace is-number directly, while is-odd brings a registry
is-number@6.

A linked workspace package has no package snapshot in the shared
lockfile, so deploy binds its peers itself. It used the graph-wide set
of resolutions for the peer's name. An injected install instead
resolves a dependency's peer from its parents.

Deploy now does the same. For each unbound peer, it walks up the pruned
deployed graph and takes, on every path, the nearest ancestor that
depends on the peer, the deployed project included. One distinct
provider is bound. Several still refuse, because deploy keeps one copy
of each linked package where injection would create one per parent.
With none, the existing graph-wide singleton rule applies. A peer the
deployed project depends on directly now binds to that version, which
turns a former refusal into the binding an injected install produces.

The pnpm 11 deploy also reads an injected workspace's recorded dev
dependencies as own properties, so a peer named after an
Object.prototype member no longer crashes it.

Closes pnpm/pnpm#16807

---------

Co-authored-by: Amp <amp@ampcode.com>
Co-authored-by: Zoltan Kochan <z@kochan.io>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
2026-10-10 21:05:46 +02:00
Zoltan Kochan 83f860fb97 docs: tag every code block with its language (#16715)
Give the untagged code blocks a language: text for command output and
directory trees, ini for .npmrc lines. Retag .npmrc snippets that were
marked sh as ini, the faq error output marked console as text, and
normalize Dockerfile to dockerfile.

Also fix snippets that did not parse as their language: trailing commas
in the catalogs.md package.json examples and the peer-dependencies.md
peerDependencyRules YAML, and the missing closing brace in the run.md
pnpm-exec-summary.json example.
2026-10-08 08:39:28 +02:00
Zoltan KochanandClaude Opus 5.5 c13953b3bc docs: label shell commands and title file snippets (#16699)
Code blocks that hold only shell commands now use the `sh` language,
and blocks showing a file's contents carry a `title` naming the file,
across the pnpm v12, pnpm v11, and pnpr docs. Bold file-name labels
above code blocks are folded into the titles.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 16:14:37 +02:00
Zoltan Kochan daf834397a fix: prune stale download and tarball spill directories (#16620)
Clean up spill directories left after an interrupted download or archive extraction during store prune. Reuse the existing store-directory scan and removal helpers without adding install-time work.

Only remove matching directories when their own mtime and the mtimes of their immediate files are more than 24 hours old. Checking files preserves an old directory whose download is still writing. Stream file entries and check one directory and file at a time to bound pending filesystem work. Stop scanning a directory after its first recent file. Skip symlinks and tolerate ENOENT when another process finishes cleanup first.

Age is a conservative heuristic, not a process-liveness check: an install suspended for over 24 hours without filesystem activity can lose its spill directory.

Add regression coverage for stale, recent, empty, and unrelated entries, symlinks, missing stores, recent writes in old directories, and expected versus unexpected filesystem errors. Close SQLite fixture handles before removing test directories for Windows compatibility.

Closes pnpm/tasks#109.
2026-10-06 01:23:25 +02:00
Zoltan Kochan 68445b254a fix: harden dependency verification and package handling (#16613)
Verify configuration dependency registry resolutions before installing
plugins, with independently checked pinned tarballs. Require config dependencies to resolve from a registry and skip
registry verification when the installed config dependencies already match
the lockfile.

Constrain archive and deployment paths and preserve content-addressed files
when streaming package entries. Bound metadata allocation before the archive
parser buffers it, using an opt-in patch to the upstream tar crate. Bound
publishing manifest and README buffers without imposing a total extraction
disk quota.

Bind audit signatures to lockfile integrity, hash ambiguous URL dependency
directory names, and sanitize license terminal output. Preserve dependency
error context and structured fatal logs. Update affected documentation,
release notes, and regression coverage.
2026-10-05 22:09:01 +02:00
Zoltan Kochan ff295f3904 fix(config): make --global and --location=global read only the global config (#16601)
`pnpm config get --global` and `pnpm config list --global` printed the
settings from the project's pnpm-workspace.yaml when run inside a
project, and `--global` and `--location=global` disagreed on what the
global config is, although the docs call them the same.

pnpm v12: `ConfigFlags::is_global` resolves both flags in one place,
with `--location` winning. A `get`/`list` scoped that way loads config
the way other global commands do, anchored at the pnpm home, so neither
the project's pnpm-workspace.yaml nor its .npmrc applies. The
pre-command pin checks and the `-w` conflict check use the same helper.
A global config read also implies --ignore-workspace, so
PNPM_CONFIG_WORKSPACE_DIR does not bring a workspace back in.

pnpm v11: config commands turn `--global` into `--location=global`
before loading config, so `--global` no longer loads the config of a
global install. That mode required the global bin directory in PATH and
read the global packages' pnpm-workspace.yaml. The CLI parser lets
`--location` win over `--global` when looking for the workspace.

Both now skip the project .npmrc for these reads, as npm does in global
mode. A new `ignoreProjectNpmrc` getConfig option does it in v11; other
v11 global commands are unchanged.

Closes pnpm/pnpm#16598
2026-10-05 16:20:00 +02:00
Zoltan KochanandClaude Opus 5.5 53428ea2dd fix(self-update): refuse to update a pnpm installed by Homebrew (#16564)
`pnpm self-update` installs the target pnpm into the global packages
directory and links it into PNPM_HOME. It never touches the Homebrew
keg, so a Homebrew user ended up with a second pnpm that the Homebrew
binary on PATH kept shadowing. The update reported success while
`pnpm -v` stayed the same, and later runs declined because the target
was "already installed globally".

Both CLIs now detect a running pnpm that lives inside a Homebrew keg
(`<cellar>/pnpm/<version>/` or `<cellar>/pnpm@<major>/<version>/`) from
its canonical path and fail with ERR_PNPM_CANT_SELF_UPDATE_IN_HOMEBREW,
pointing at `brew upgrade <formula>`. The check sits next to the
existing Corepack refusal, before project config is loaded.

Closes https://github.com/pnpm/pnpm/issues/16547

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-03 21:49:08 +02:00
Zoltan Kochan c82802b114 fix(pkg): keep projects that share a name in pkg get -r output (#16494)
`pnpm -r pkg get` keyed its JSON report by package name, so when two
selected workspace projects had the same name the later one silently
replaced the earlier one. Workspaces allow duplicate names, so failing
is not an option.

Keep name keys when a name is unique. Key every project that shares a
name by its workspace-relative directory, the same fallback already
used for nameless projects. Re-keying all of them rather than only the
later one keeps the result independent of selection order. A project
whose name equals a directory key that another project falls back to
also moves to its directory, and this repeats until no key collides.
Directories are distinct, so every key is. Workspaces with unique names
keep the same output.

Implemented in both the TypeScript and Rust CLIs, with the docs updated
for both.
2026-10-01 20:18:07 +02:00
Zoltan Kochan 6fd18fa16b fix: remove legacy global hard links during migration (#16425)
Expose installed executable paths from the global package scanner and
use file identity to recognize hard links during legacy global migration.
Keep the existing symlink and shim cleanup, and include Windows exe paths.
Do not treat equal file contents as proof of ownership.

Apply the fix in both CLI implementations and test hard-link cleanup,
large native executables, and preservation of unrelated files.

Closes pnpm/pnpm#16420.
2026-09-30 10:56:32 +02:00
2211354fd7 fix(deploy): don't copy the workspace root's package manager pin into the deployed manifest (#16405)
Deploy no longer writes the workspace root's `packageManager` or
`devEngines.packageManager` into the deployed manifest. This reverts the
inheritance added in pnpm/pnpm#15434 for pnpm/pnpm#9079, in both the
Rust and TypeScript CLIs.

A deploy directory is run by whatever package manager or runtime its
consumer uses, often npm in a plain Node.js image. With the default
onFail, npm refuses to run the scripts of a manifest whose
devEngines.packageManager names pnpm, so every script in the deploy
output failed with EBADDEVENGINES. A packageManager pin can likewise
make corepack or pnpm's version switching fetch another pnpm inside the
image. The deploy output is meant for running the app, so it carries no
development-time pin from the workspace. A deployed project's own pin is
kept, since deploy leaves the project's manifest fields as they are.

The inheritance helper, its call sites, and the now-unused
`@pnpm/workspace.project-manifest-reader` dependency of
`@pnpm/releasing.commands` are removed. A regression test in each CLI
checks that neither field reaches the deployed manifest, for native and
legacy deploy.

Closes pnpm/pnpm#16403

---------

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Zoltan Kochan <z@kochan.io>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Copilot-Session: 7ee9c5ce-96b9-4d2b-a163-a6e5a4a4eb38
2026-09-30 02:09:22 +02:00
5a5de95b6e fix(publish): recognize npm README file names (#16352)
Include bare README and npm-compatible Markdown README filenames in
publish metadata for both pnpm CLIs, from directories and tarballs.

Select README.md before other Markdown names and bare README, with the
lower file name breaking ties so the pick does not depend on readdir or
archive order. Preserve root-only and regular-file checks. Tarballs are
scanned once, reading only README entries that outrank the current pick.
The Rust CLI decodes README bytes lossily, matching the TypeScript CLI.

Related to pnpm/pnpm#12704

---------

Co-authored-by: Zoltan Kochan <z@kochan.io>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 02:01:15 +02:00
Zoltan Kochan 417ab35c21 docs: consolidate migrated documentation contributions (#16393)
Port applicable documentation contributions from the website PR backlog to
pnpm/docs and pnpm11/docs now that documentation lives alongside the CLI.
Reconcile overlapping fixes and outdated paths against the current code.
Keep documentation for unmerged features with the implementation PRs.
The PR description credits each original author and records all 99 dispositions.
2026-09-29 17:18:52 +02:00
Zoltan Kochan 07839df5c3 docs: move product documentation beside its implementation (#16385)
* docs: move website documentation into the pnpm repository

* docs: keep v11 and v12 documentation beside their implementations

* docs(pnpr): keep registry documentation beside its implementation

* ci: classify product documentation as documentation changes

* test: cover product documentation in Rust CI exclusions

* ci: isolate documentation publishing and support manual sync

* test: make dependency status fixture timestamps deterministic
2026-09-29 15:56:43 +02:00