This skill does two things: onboard a project to (or correct it to) a unified release standard; and execute a release for the project according to the standard. It applies to any npm ecosystem project—single package or monorepo, with or without a version management tool. Differences between projects are recorded only in the project's own configuration and scripts; this skill does not record any specific project.
Core principles
A released version cannot be taken back. An npm version number cannot be reused even after being unpublished, and a GitHub tag with immutable releases enabled likewise cannot be reused; if something goes wrong, the only fix is to bump the version. Therefore:
- All checks that can be done before publishing are done before publishing; publishing, tagging, and creating the Release are placed last.
- Publishing can be safely rerun: versions already present on the registry are automatically skipped, and after a failure you fix the cause and rerun directly, without rolling back.
- Whether publishing succeeded is determined by a registry query (
npm view), not by command output. - The release script is non-interactive: all input comes from parameters, and humans and Agents use the same command.
Unified tool definitions
交互式提问: a type of tool built into most Agents, a tool by which the Agent asks the user questions and provides options and custom input; its name differs across Agents, and it may be calledAskUserQuestionorAskQuestion, etc.
Reference files (read as needed, do not read them all at once)
| File | When to read |
|---|---|
| references/public-release.md | Public release projects: onboarding or correcting scripts and CI, executing releases, first release of a new package, trusted publishing configuration, troubleshooting CI publishing failures |
| references/local-release.md | Local release projects: onboarding or correcting release scripts, executing releases, troubleshooting publishing failures |
| references/release-content.md | Determining version magnitude, writing changeset / CHANGELOG / GitHub Release body / release commit message |
| references/tools/changesets.md | The project uses changesets (exists .changeset/config.json) |
Two sets of standards
Public release public |
Local release local |
|
|---|---|---|
| Publishing target | npmjs + GitHub Release | Private registry (any source compatible with the npm protocol) |
| Who publishes | CI(GitHub Actions + npm trusted publishing) | Local machine release script |
Local release script |
Check → bump version → build and test → commit → push | Check → bump version → build → package verification → commit and push → publish → tag |
| Credentials | None (OIDC) | User-level ~/.npmrc |
Contracts shared by both sets of standards (see the respective reference files for details):
- Entry point: the root
package.jsonof thereleasescript;--dry-rundry run, and the workspace is restored to its original state afterward. Parameter parsing ignores a standalone--。 - Starting point: the workspace is clean (including untracked files), on the release branch, and not behind the remote.
- Version: when a version tool is available, it is calculated by the tool; when not, pass the target version
release <x.y.z>, all publishable packages share the same version. - Order: commit and push the release commit first, then publish; the tag is created only after a successful publish.
- Naming: commit
chore(release): 发布 …; tag for a single package or the whole repo with the same versionv<版本>, changesets for multiple packages<包名>@<版本>; the dist-tag of a prerelease takes the prerelease identifier and never falls tolatest. See release-content.md.
Command style:<pm> refers to the project package manager; passing arguments to scripts is always written as <pm> run release -- <参数>(npm must have --)。
Project configuration
The release standard is recorded at the repo root .pe.jsonc(committed to the repo, no sensitive information; if the file already exists, only add fields):
{
"release_mode": "public" // public | local
}
Credentials never go into the repo: public releases rely on trusted publishing and need no token; login information for local releases is written by the user into the user-level ~/.npmrc。
Process
When the user only asks to write a changeset or CHANGELOG, finish it per release-content.md and stop; do not proceed to release.
1. Identify the project (always the first step)
Confirm each item; do not re-judge afterwards:
- Standard: read
.pe.jsoncofrelease_mode. If missing, use交互式提问to ask (public release / local release), and write it in after confirmation. - Package manager:
packageManagerfield takes priority, then the lockfile (bun.lock、pnpm-lock.yaml、yarn.lock、package-lock.json)。 - Publishable packages: the root package or packages in workspaces without
"private": true; for local releases also read each package'spublishConfig.registry。 - Version tool: if
.changeset/config.jsonexists → read tools/changesets.md. Other tools (release-please, semantic-release, Nx Release, etc.) have no reference file yet; check their latest official docs first before acting, while the script contract and content standard still follow this skill. If none → no-tool process. - Infrastructure:
releasescript, and for public releases whether.github/workflows/release.ymlexists and conforms to the contract of the corresponding reference file.
2. Integrate or fix (when infrastructure is missing or non-standard)
- Read the corresponding reference file, list the files to add / modify and the reasons, and use
交互式提问to confirm before changing. - Implement per the contract: scripts use only the project's existing runtime and dependencies; to add a dependency (e.g. integrating changesets), get consent first, and use the latest version verified on npm.
- Run
<pm> run release -- [<版本>] --dry-run, and fix until it passes. - List the one-time operations that must be done by a human (npm trusted publisher configuration, first release of a new package, private registry login), and wait for the user to confirm completion.
- Commit integration changes separately; do not mix them with the release commit.
3. Perform the release
- Determine content: collect changes since the last release per release-content.md. For changesets projects, complete and correct the pending changesets; for no-tool projects, determine the bump, compute the target version, and write that version's section at the top of the CHANGELOG.
- Give the plan: list for the user package → new version → dist-tag, plus a summary of the release content. Use
交互式提问to confirm once in the following cases: the bump is uncertain (especially major, breaking changes in 0.x), the first release of a new package, or a prerelease becoming a stable release. In other cases, when the user says "release", it is taken as consent to push and publish. - Dry run:
<pm> run release -- [<版本>] --dry-run, and check the output version, files, and release plan. - Execute: remove
--dry-runand rerun. When OTP or login is required, ask the user to provide it or complete it in their terminal; the Agent must not fill it in or guess. - Verify:
- Public release: track CI until it finishes (public-release.md "Tracking and Verification"), then check
npm view <包>@<版本> versionand the GitHub Release. - Local release: rely on the script's registry query result; spot-check
npm view <包>@<版本> version --registry <源>。 - Do not verify by installing in a downstream project: pnpm ≥ 11 (
minimumReleaseAgedefaults to 1440 minutes) and newer Yarn (npmMinimalAgeGatedefaults to1d) do not install versions published less than a day ago by default. When downstream needs to use it immediately, configure pnpmminimumReleaseAgeExcludeor YarnnpmPreapprovedPackagesdownstream, adding the package name or@scope/*。
- Public release: track CI until it finishes (public-release.md "Tracking and Verification"), then check
- Report: the published packages and versions, dist-tag, tag, release commit hash. On failure, explain which step it stopped at, what has been completed, and what to do next.
On failure, handle it according to the troubleshooting table in the reference file: fix the cause and rerun; repeated guess-based retries are prohibited; deleting or moving an already-pushed tag is prohibited; force pushing the release branch is prohibited; reverting a release commit requires the user's consent first.
Checklist
-
.pe.jsonchasrelease_mode; credentials are not in the repository - Package manager, publishable packages, and version tooling have been identified; for changesets projects, commands have been selected according to the actual version (3.x / 2.x)
- The infrastructure conforms to the contract of the corresponding reference file; integration changes are committed separately
- Release content is written according to release-content.md, and the magnitude determination is justified
- First
--dry-runthen execute for real - Confirm via registry query that every package has been published; CI for the public release has been tracked to completion
- Tag and Release (for public release) have been created, and the report has been provided
Anti-patterns
- Writing specific projects in this skill; writing private registry addresses anywhere other than
publishConfig.registry; writing tokens into the repository - Running interactive commands (
changeset/changeset addwithout arguments, runningnpm login) - Skipping
--dry-runand publishing directly; or treatingnpm publish --dry-runas a connectivity and login check - Running
workspace:/catalog:directly on a directory containingnpm publish - After a failed publish, rolling back or rewriting an already-published version, or moving a tag, instead of fixing the cause and rerunning
- Using a command output of "success" instead of a
npm viewquery - Publishing a prerelease version to
latest - Mixing unrelated changes into the release commit, or having commit messages with
[skip ci] - Publishing a public release locally with an npm token; or enabling trusted publishing while also configuring
NODE_AUTH_TOKEN