Release Finalize
Gathers the release artifacts of any product and prepares the repository for a push to a public repository or a deploy. Runs autonomously: a single checkpoint before applying edits, then a straight run to the tag with no intermediate confirmations.
Invocation is manual only, via /release-finalize — the skill never self-activates.
Scope of responsibility
- ✅ Changelog — prepend a new section (Keep a Changelog / SemVer).
- ✅ Root
README.md— sync to the release context. - ✅ Pre-publish scan — secrets, version consistency, clean tree.
- ✅ Annotated git tag on HEAD.
- ❌ merge — forbidden.
- ❌
git push, deploy — only suggest the command, never run it.
Artifacts are auto-detected; overrides come from a .release-finalize.yml file at the root of the
target repo (format — this skill's templates/release-config.yml, e.g.
${CLAUDE_SKILL_DIR}/templates/release-config.yml in Claude Code).
Process indication
At the start of each phase, print a status line:
[release-finalize] <emoji> <action in present tense>: <progress> [<context>]
Reserved emoji: 🛑 stop/block · ❓ clarification · ⏸️ awaiting approval · ✅ finish.
Working actions use a per-phase topical emoji (🧭 🔎 ✍️ 📝 🏷️ and the like).
Checklist (run plan)
Before Phase 0, print the plan and create one TodoWrite task per phase; track status via TodoWrite. The list is fixed and executed in order:
- Detect — version, branch, artifacts, commits
- Scan — secrets, version consistency, cleanliness
- Draft — changelog draft + README edits
- Apply — apply changelog and README (after approval)
- Commit — delegate to
committing-changes - Tag — annotated tag
- Hand-off — summary and commands
Workflow
Phases 0–2 run autonomously. Between Phase 2 and Phase 3 there is a single ⏸️ checkpoint.
Phases 3–6 run autonomously, with no further confirmations.
Phase 0 — Detect
Status: [release-finalize] 🧭 Gathering release context: <version|?>
- Release version
X.Y.Z— source of truth: the command argument ($1) or the user's message. If not given — try to extract it from version files; still missing →❓"Specify the release version (e.g. 0.2.0)". Version files serve only for the consistency check (Phase 1); they do not determine the release version. - Read
.release-finalize.ymlat the repo root, if present, and take its overrides (changelog, readme, version_files, branch_pattern, public_prep). No file — work off auto-detection. - Determine the artifacts (honoring overrides):
- changelog:
CHANGELOG.md, otherwiseHISTORY.md; if neither exists → mark a newCHANGELOG.md(heading# Changelog) for creation in Phase 3; - readme: the root
README.md; - version files:
pyproject.toml,package.json,VERSION,Cargo.toml(whichever are present).
- changelog:
- Branch:
git rev-parse --abbrev-ref HEAD. Ifbranch_patternis set and the branch does not match — warn, but do not stop. - Latest tag:
git describe --tags --abbrev=0. If a tag exists →git log <tag>..HEAD --oneline; no tags →git log --oneline. Keep the list as reference for Phase 2.
Phase 1 — Scan
Status: [release-finalize] 🔎 Checking readiness to publish
- Clean tree:
git status --porcelain. Non-empty →🛑, list the files, offer stash /committing-changes/ cancel. - Secrets:
git grep -nIEon assignment patterns, not bare words —(AKIA[0-9A-Z]{16}|BEGIN [A-Z ]*PRIVATE KEY|(api[_-]?key|secret|token|password)[[:space:]]*[=:][[:space:]]*['"])and on the paths frompublic_prep.exclude(e.g..env). On a hit →🛑, show file:line (do not print the full value), stop. - Version consistency: read the version in each version file, compare with
X.Y.Z. On a mismatch →🛑, show a file→version table. .gitignore/ stray files: fromgit statusand any un-ignored private paths —⚠️, list them for review (not a stop).
Phase 2 — Draft
Status: [release-finalize] ✍️ Preparing changelog and README edits
- Group the commits from Phase 0 by conventional-commit type (
feat→ Added,fix→ Fixed,docs/refactor/chore→ Changed,BREAKING→ its own block). Read the templatetemplates/changelog-entry.md(e.g.${CLAUDE_SKILL_DIR}/templates/changelog-entry.md). - Assemble the section:
{VERSION}→X.Y.Z,{DATE}→today (the systemToday's date),{NARRATIVE}→2–3 points on the essence of the release,{CHANGES_LIST}→a minimal list of- module: what changed. - README: prepare a generic sync to the release context (version / component status, if such sections exist; no hardcoding of specific sections). If there are no obvious edits — leave the README unchanged.
Checkpoint ⏸️
Status: [release-finalize] ⏸️ Awaiting approval: vX.Y.Z
Show in one block: the version, branch, detected artifacts, the Phase 1 scan report, the prepared
changelog section, and the proposed README edits (before/after). Ask (via AskUserQuestion):
"Apply? (ok / edits)". Do not touch files until ok.
Phase 3 — Apply
Status: [release-finalize] 📝 Applying edits
Changelog exists → prepend the section (insert before the first ##). Does not exist → create
CHANGELOG.md with heading # Changelog and the first release section. Apply the README edits, if
any.
Phase 4 — Commit
Status: [release-finalize] 📦 Committing the finalization
Delegate to the committing-changes skill with the context "release vX.Y.Z: changelog + README".
Do not proceed to Phase 5 until it completes.
Phase 5 — Tag
Status: [release-finalize] 🏷️ Creating the tag
git tag -a vX.Y.Z -m "Release vX.Y.Z"
git rev-parse vX.Y.Z
Phase 6 — Hand-off
Status: [release-finalize] ✅ Release vX.Y.Z finalized
Print the summary and next steps (do not run the commands):
Release vX.Y.Z finalized:
✅ changelog — section vX.Y.Z added
✅ README — synced
✅ git tag vX.Y.Z on <SHA>
Next:
• merging-branches — merge the release branch → main
• git push origin vX.Y.Z — publish the tag
• deploy — per the product's procedure
Boundaries (what the skill does not do)
- Does not run
git merge,git push,git branch -D, or a deploy — only suggests the commands. - Does not touch files outside the declared artifact set (changelog, root README).
- On a secret hit or a version mismatch —
🛑, does not silently continue. - Does not apply edits before approval at the
⏸️checkpoint. - Version bump in version files (
pyproject.toml/package.json/ …) is out of scope and must be done before the skill runs; Phase 1 only checks consistency. - Bash: do not use
git -C <path>; the working directory is already set; avoid compound&&commands for read-only calls.