release
script/publish does the release. This skill runs the checks that script does not do,
then hands over.
Preflight — run all of these before touching script/publish
- Working tree clean.
git status --porcelain. The script warns and offers to
continue, but a dirty tree means uncommitted work gets swept into the release commits by
the git add . after the build. Stop and ask.
- On the default branch, and pushed up to date.
git status -sb.
- Tests and lint green.
script/test and script/lint if present, otherwise
npm test. Do not skip this — script/publish tags and pushes without running either.
## [Unreleased] has content. If CHANGELOG.md exists and that section is empty,
stop: the release will ship with empty notes. Offer the changelog-entry skill.
- The version argument makes sense. Semver, and not the version already in
package.json. Breaking changes in the changelog mean a major.
Report anything that fails and stop. Do not "fix" a failing test to unblock a release.
Then hand off
script/publish <version>
It is interactive — readline prompts for the version, and for whether to create the
GitHub release. Never run it in the background, never pipe it, never try to answer its
prompts for the user. Tell them to run it, or run it in the foreground and let them type.
If they want it non-interactive, pass the version as the argument — that skips the version
prompt, but the GitHub release prompt remains.
What it does, so you can tell them what to expect
- Writes the version into
package.json.
- Runs
script/changelog <version> if present — cuts ## [Unreleased] into a dated
release entry, starts a fresh one, writes the changelog post, and leaves the cut entry
in the temp dir as the release notes.
- Commits
Bump version to <version>.
- Runs
script/build if present, commits Build version <version>.
- Tags
v<version>, pushes commits and tags.
- Offers to
gh release create with the cut changelog entry as --notes-file.
npm publish happens in CI (publish.yml, trusted publishing) when the tag lands. It is
not part of this script. If the package did not appear on npm, that is a CI problem, not a
publish-script problem — check the workflow run.
Notes
Bump version to X and Build version X are the script's own commit messages. They are
generated, and are the one place the no-prefix one-liner rule does not apply — leave them.
- The release notes file is
$TMPDIR/<repo>-release-notes-v<version>.md. A failing gh
leaves it there on purpose, for a manual gh release create --notes-file retry.
script/changelog, script/publish and script/lint are identical across my repos —
they come from stamat/template. A fix to one belongs upstream in the template, not
copy-pasted around.
Boundaries
Preflight and hand-off. Does not write the changelog entry (see changelog-entry), does
not decide the version number — propose one from the changelog and let the user confirm.
1---2name: release3description: Preflight and run a release via script/publish — clean tree, tests green, changelog entry present, then hand off to the interactive script. Use when the user says "release", "publish", "cut a release", "ship it", "bump the version", or "/release".4---56# release78`script/publish` does the release. This skill runs the checks that script does *not* do,9then hands over.1011## Preflight — run all of these before touching script/publish12131. **Working tree clean.** `git status --porcelain`. The script warns and offers to14 continue, but a dirty tree means uncommitted work gets swept into the release commits by15 the `git add .` after the build. Stop and ask.162. **On the default branch, and pushed up to date.** `git status -sb`.173. **Tests and lint green.** `script/test` and `script/lint` if present, otherwise18 `npm test`. Do not skip this — `script/publish` tags and pushes without running either.194. **`## [Unreleased]` has content.** If `CHANGELOG.md` exists and that section is empty,20 stop: the release will ship with empty notes. Offer the `changelog-entry` skill.215. **The version argument makes sense.** Semver, and not the version already in22 `package.json`. Breaking changes in the changelog mean a major.2324Report anything that fails and stop. Do not "fix" a failing test to unblock a release.2526## Then hand off2728```bash29script/publish <version>30```3132**It is interactive** — readline prompts for the version, and for whether to create the33GitHub release. Never run it in the background, never pipe it, never try to answer its34prompts for the user. Tell them to run it, or run it in the foreground and let them type.3536If they want it non-interactive, pass the version as the argument — that skips the version37prompt, but the GitHub release prompt remains.3839## What it does, so you can tell them what to expect40411. Writes the version into `package.json`.422. Runs `script/changelog <version>` if present — cuts `## [Unreleased]` into a dated43 release entry, starts a fresh one, writes the changelog post, and leaves the cut entry44 in the temp dir as the release notes.453. Commits `Bump version to <version>`.464. Runs `script/build` if present, commits `Build version <version>`.475. Tags `v<version>`, pushes commits and tags.486. Offers to `gh release create` with the cut changelog entry as `--notes-file`.4950**npm publish happens in CI** (`publish.yml`, trusted publishing) when the tag lands. It is51not part of this script. If the package did not appear on npm, that is a CI problem, not a52publish-script problem — check the workflow run.5354## Notes5556- `Bump version to X` and `Build version X` are the script's own commit messages. They are57 generated, and are the one place the no-prefix one-liner rule does not apply — leave them.58- The release notes file is `$TMPDIR/<repo>-release-notes-v<version>.md`. A failing `gh`59 leaves it there on purpose, for a manual `gh release create --notes-file` retry.60- `script/changelog`, `script/publish` and `script/lint` are identical across my repos —61 they come from `stamat/template`. A fix to one belongs upstream in the template, not62 copy-pasted around.6364## Boundaries6566Preflight and hand-off. Does not write the changelog entry (see `changelog-entry`), does67not decide the version number — propose one from the changelog and let the user confirm.