A procedure, step by step
Cutting a plugin release
Cut a release in 11 steps: bump the version, pass the checks, merge, tag, publish, then update your own copy.
- Work in a worktree, on a branch named release/X.Y.Z.
- node tools/check-repo.mjs must exit 0 before the pull request opens.
- A release is a merged pull request, a tag and a GitHub release.
The 11 steps, in order
Cutting 1.9.0Take: tick a row as you finish its step. The first open step is marked Next, and each row links to its step.
- What you need firstFour tools, with a one-line check for each.
- Prepare the release branchA worktree, the version, the changelog and the upgrade hash.
- Check it and open the pull requestUpgrade the shipped pages, run both checks, open the pull request.
- Publish it and update your copyMerge, tag, create the GitHub release, then update.
- When it goes wrongHow far each stage can be taken back.
Chapter 1 of 5, about 1 minute
What do I need before I start?
Before this: a release is a merged pull request, a tag and a GitHub release.
The steps use 1.9.0, the next release, and 1.8.1, the last one. Change both numbers for yours. Release work gets its own worktree, in a folder the repository already ignores.
- Node 18 or newer
node --versionprints v18 or higher. - Git, on a clean main
git status --shortprints nothing. - GitHub CLI, signed in
gh auth statusnames your account. - Claude Code
claude --versionprints a version.
Take from this: four tools, one command each. If one prints nothing, fix it before step 1.
Remember: check the four tools first, and swap in your own version numbers.
Chapter 2 of 5, about 2 minutes
How do I prepare the release branch?
Before this: the four tools work and main is clean.
- Start a release branch in its own worktree.
git worktree add .claude/worktrees/release-1.9.0 -b release/1.9.0 main cd .claude/worktrees/release-1.9.0Check:
git worktree listshows the new folder on[release/1.9.0].If it fails: if the branch exists, drop
-b release/1.9.0 mainand name the branch last. - Set the version in the manifest and the template.
sed -i 's/1\.8\.1/1.9.0/' .claude-plugin/plugin.json skills/html-explainer/assets/template.htmlCheck:
git diff --statshows2 +-for both files.If it fails: any other count means a stray match. Undo it and edit both numbers by hand.
- List what shipped, then write the changelog section.
git log --oneline v1.8.1..mainCheck:
grep -n '^## ' CHANGELOG.mdlists## 1.9.0above## 1.8.1.If it fails: move the new section above the newest release.
- Find the template's hash for the upgrader.
node skills/html-explainer/scripts/upgrade.mjs --hash skills/html-explainer/assets/template.htmlCheck: 16 hex digits print. If KNOWN lists them, add nothing. If not, add
'digits': '1.9.0',.If it fails: run it from the worktree's top folder.
Take from this: after step 4 the branch holds the new version, the changelog and the hash.
Remember: a release branch starts in a worktree and ends with the version, the changelog and the hash.
Chapter 3 of 5, about 2 minutes
How do I check the release and open the pull request?
Before this: the branch holds the new version, the changelog and the hash.
- Bring the shipped pages to the new mark.
node skills/html-explainer/scripts/upgrade.mjs skills/html-explainer/assets/gallery.html skills/html-explainer/examples skills/explainer-gather/examples docs/index.html docs/roadmap.htmlCheck: every line says
version mark set,upgradedoralready current.If it fails:
skipped: custom stylesmeans hand edits. Paste the template's style and script in. - Run both checks.
node tools/check-repo.mjs claude plugin validate --strict .Check: they end with
all checks passedandValidation passed, and both exit 0.If it fails: fix each FAIL line. A mark mismatch means step 2 missed a number.
- Commit, push and open the pull request.
git add -A && git commit -m "chore(release): 1.9.0" git push -u origin release/1.9.0 gh pr create --title "Release 1.9.0: public examples" --fillCheck:
gh pr checks --watchends withcheckpassing. Thesitejob is skipped on a pull request.If it fails:
gh pr checks --webopens the log. Fix the FAIL line here and push again.
Take from this: the checks run on your machine first, and CI runs the repository check again.
Remember: upgrade the shipped pages, run both checks, then open the pull request.
Chapter 4 of 5, about 2 minutes
How do I publish the release and update my copy?
Before this: the pull request is open and its check job passes.
- Merge the pull request and delete its branch.
gh pr merge --merge git push origin --delete release/1.9.0Check: after
git fetch,git log origin/main -1 --onelinenames your pull request.If it fails: wait for the check job. If main moved, merge origin/main and push.
- Tag the merge and push the tag.
git tag -a v1.9.0 -m "1.9.0: public examples" origin/main git push origin v1.9.0Check:
git ls-remote --tags origin v1.9.0lists the tag.If it fails:
already existsmeans someone tagged it. Readgit show v1.9.0first. - Create the GitHub release from the changelog.
sed -n '/^## 1.9.0/,/^## 1.8.1/{//!p}' CHANGELOG.md > ../notes.md gh release create v1.9.0 --title "1.9.0: public examples" --notes-file ../notes.mdCheck:
gh release view v1.9.0prints the title and the 1.9.0 changelog text.If it fails:
../notes.mdmust hold only the 1.9.0 section. - Update your own copy.
claude plugin marketplace update html-explainer-skill claude plugin update html-explainer@html-explainer-skillCheck: after a restart,
claude plugin listshowsVersion: 1.9.0.If it fails: still old? Run both commands in this order, then restart.
Take from this: merge, tag and release are separate acts with separate checks.
Show how to confirm the site redeployed
gh run list --workflow ci --branch main --limit 1
The public site builds from main after the merge. The newest run should end in completed and success.
Remember: merge, tag, release, then update your own copy and restart.
Chapter 5 of 5, about 1 minute
What do I do when it goes wrong?
Before this: a release is a merge, a tag and a GitHub release, and each can be taken back.
- Before the mergeClose the pull request and remove the worktree. Nothing reached main.
- After the merge, before the tagRevert the merge in a new pull request, then run the checks again.
- After the tag and the releaseDelete the release and its tag. Releases here are not locked.
- After people have updatedYou cannot recall it. Fix forward with a patch release.
Take from this: the earlier you stop, the cheaper the way back. This repository has shipped fast fixes before: 1.8.1 followed 1.8.0 about three hours later.
Show the commands for each stage
# before the merge (run the second line from the main checkout)
gh pr close --comment "Not shipping"
git worktree remove .claude/worktrees/release-1.9.0
# after the merge, before the tag
git revert -m 1 <merge commit>
# after the tag and the release
gh release delete v1.9.0 --cleanup-tag --yes
git tag -d v1.9.0
A reader can stay on one release by adding its tag when they add the marketplace: ariasr47/html-explainer-skill#v1.8.1.
Remember: take it back as far as it got, and fix forward once people have updated.
Recap
- Check the four tools first, and swap in your own version numbers.
- A release branch starts in a worktree and ends with the version, the changelog and the hash.
- Upgrade the shipped pages, run both checks, then open the pull request.
- Merge, tag, release, then update your own copy and restart.
- Take it back as far as it got, and fix forward once people have updated.