Files
pnpm/pnpm11/docs/cli/publish.md
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

5.6 KiB

id, title
id title
publish pnpm publish

Publishes a package to the registry.

pnpm [-r] publish [<tarball|folder>] [--tag <tag>]
     [--access <public|restricted>] [options]

:::note

Since v11, pnpm publish is implemented natively and no longer delegates to the npm CLI. If you rely on a feature that is now gone, open an issue at pnpm/pnpm. As a workaround, you can still run pnpm pack && npm publish *.tgz.

:::

When publishing a folder or a tarball, pnpm includes a package-root README in the registry metadata if the manifest has no readme value. It recognizes README.md, other README files with npm-compatible Markdown extensions (such as README.markdown and README.mdown), and README. It prefers README.md, then another Markdown README, then README.

When publishing a pre-built tarball, pnpm rejects manifests and README files larger than 64 MiB.

When publishing a package inside a workspace, the LICENSE file from the root of the workspace is packed with the package (unless the package has a license of its own).

You may override some fields before publish, using the publishConfig field in package.json. You also can use the publishConfig.directory to customize the published subdirectory (usually using third party build tools).

When running this command recursively (pnpm -r publish), pnpm will publish all the packages that have versions not yet published to the registry.

Options

--recursive, -r

Publish all packages from the workspace.

--json

Show information in JSON format.

--tag <tag>

Publishes the package with the given tag. By default, pnpm publish updates the latest tag.

For example:

# inside the foo package directory
pnpm publish --tag next
# in a project where you want to use the next version of foo
pnpm add foo@next

--access <public|restricted>

Tells the registry whether the published package should be public or restricted.

--no-git-checks

Don't check if current branch is your publish branch, clean, and up-to-date with remote.

--publish-branch <branch>

  • Default: master and main
  • Types: String

The primary branch of the repository which is used for publishing the latest changes.

--force

Try to publish packages even if their current version is already found in the registry.

--batch

Added in: v11.7.0

When publishing recursively (pnpm -r publish), send all selected packages to the registry in a single PUT /-/pnpm/v1/publish request instead of one request per package.

The target registry has to implement the batch publish endpoint (pnpr does); registries that don't are reported with an ERR_PNPM_BATCH_PUBLISH_UNSUPPORTED error. The batch is processed all-or-nothing: if any package in the batch fails validation, none of the packages are published.

Since v11.24.0, the selected packages are grouped by the registry each one publishes to, and one request is sent per group. Every package in a group must authenticate with the same credential. A scope-specific token shared across the group is fine, and mismatched credentials for one registry are rejected before anything is published, rather than after part of the release went out. The publish and postpublish scripts run after each completed group.

--skip-manifest-obfuscation

Added in: v11.3.0

Keep the original packageManager field and publish lifecycle scripts in the published manifest instead of stripping them. The pnpm-specific pnpm field is still omitted.

--report-summary

Save the list of published packages to pnpm-publish-summary.json. Useful when some other tooling is used to report the list of published packages.

An example of a pnpm-publish-summary.json file:

{
  "publishedPackages": [
    {
      "name": "foo",
      "version": "1.0.0"
    },
    {
      "name": "bar",
      "version": "2.0.0"
    }
  ]
}

--dry-run

Does everything a publish would do except actually publishing to the registry.

--otp

When publishing packages that require two-factor authentication, this option can specify a one-time password.

You can also provide the OTP via the PNPM_CONFIG_OTP environment variable:

export PNPM_CONFIG_OTP='<your OTP here>'
pnpm publish --no-git-checks

If the registry requests OTP and you have not provided it via the environment variable or the --otp flag, pnpm will prompt you directly for an OTP code.

If the registry requests web-based authentication, pnpm will print a scannable QR code along with the URL.

--provenance

When publishing from a supported cloud CI/CD system, the package will be publicly linked to where it was built and published from.

--filter <package_selector>

Read more about filtering.

Configuration

You can also set gitChecks, publishBranch options in the pnpm-workspace.yaml file.

For example:

gitChecks: false
publishBranch: production

Registry

Since v11.28.0, a scoped package is published to the registry set by publishConfig["@<scope>:registry"] in its package.json. This takes precedence over the registry set for the same scope in .npmrc and over publishConfig.registry:

{
  "name": "@acme/utils",
  "publishConfig": {
    "@acme:registry": "https://npm.acme.example/"
  }
}

Life cycle scripts

  • prepublishOnly
  • prepublish
  • prepack
  • prepare
  • postpack
  • publish
  • postpublish