| name | release-flow |
| description | Walk a personal project through release end-to-end โ scan changes, recommend a SemVer bump, preview every file write, wait for user confirm, execute, then ask separately before pushing. Use whenever the user says "release", "ๅ็", "ๅบ็ๆฌ", "tag a version", "cut v1.2.0", "let's ship", "make a release", "/release" โ or implicitly when the user is finalizing CHANGELOG `[Unreleased]` and treating it as a version. Strongly prefer using this skill over ad-hoc tagging because all writes are previewed and reversible until the user types yes. Skip release-please workflow setup unless explicitly asked; this is the manual / interactive flow. |
release-flow
A 5-step interactive flow that turns accumulated changes into a tagged release. Every write happens only after the user confirms a preview. Pushing is a separate confirmation because it's the only irreversible step.
The skill exists because:
- Ad-hoc tagging skips CHANGELOG hygiene; the project ends up with tags whose contents nobody can reconstruct.
- Auto-committing version bumps without showing the diff means users sometimes find themselves with a wrong tag in remote history โ recoverable but annoying.
- Personal projects don't need release-please ceremony, but they do still benefit from "stop, show me, ask, then act."
When to invoke
Trigger on any of these patterns:
- Direct: "ๅ็", "release", "tag", "cut v1.2.0", "ship it", "make a release", "/release"
- Implicit: user says "I think we're ready for v0.3" / "let's finalize the unreleased section" / "time for a new version"
- Setup-adjacent: user adds a final commit and says "and now bump the version" โ run the full flow, don't just
git tag
If the user only wants one piece (e.g., "what version should this be?"), do just Step 2 and stop โ don't drag them through unnecessary steps.
Workflow
The flow has 5 steps. Steps 3 and 5 are hard gates: do not write or push until the user types yes / ็กฎ่ฎค / OK.
Step 1 โ Scan current state
Read what's actually in the repo:
git tag --sort=-version:refname | head -3
git log $(git tag --sort=-version:refname | head -1)..HEAD --oneline
sed -n '/^## \[Unreleased\]/,/^## \[/p' CHANGELOG.md | head -50
grep -E '^version\s*=' pyproject.toml package.json Cargo.toml 2>/dev/null
If there's no CHANGELOG.md, ask the user whether to create one as part of this release. Don't silently create โ explain it's optional.
If [Unreleased] is empty and there are no commits since the last tag, stop and tell the user there's nothing to release.
Step 2 โ Recommend a version (SemVer)
Infer the bump from commit types since the last tag:
Example:
Last tag: v1.1.3
Commits since:
feat(auth): add JWT refresh
fix(loader): handle empty wav
refactor(api): split routers
โ Recommend MINOR bump: v1.2.0
Reason: contains feat: (no breaking changes)
Bump rules:
| Commit signal | Bump |
|---|
BREAKING CHANGE: footer, or feat!: / fix!: etc. | MAJOR |
Any feat: | MINOR |
Only fix: / perf: / revert: | PATCH |
Only docs: / chore: / test: / build: / ci: / style: | Ask user โ usually no release needed |
| Project still at 0.x | Treat feat: as MINOR (0.Y.0); breaking is fine without MAJOR bump |
State the recommended version and the reasoning. The user might override (e.g., "actually bump to 2.0 because I want to mark a milestone") โ that's fine.
Step 3 โ Preview, then ASK CONFIRM โ ๏ธ
Show the exact changes that will happen โ but don't write yet. The point is that the user can spot a wrong version, a missing changelog entry, or an unintended file change before anything hits disk.
Example preview:
=== Release preview: v1.2.0 ===
๐ CHANGELOG.md
Rename: [Unreleased] โ [1.2.0] - 2026-05-19
Insert new empty [Unreleased] at top
Append link: [1.2.0]: https://github.com/owner/repo/compare/v1.1.3...v1.2.0
๐ฆ pyproject.toml
version = "1.1.3" โ "1.2.0"
๐ New commit
chore(release): v1.2.0
๐ท New tag
v1.2.0 โ HEAD
Proceed? (yes / no / "let me adjust X")
Wait for an unambiguous yes (yes / y / OK / ็กฎ่ฎค / ็ปง็ปญ / go). If the user says "no" / "cancel" / "wait", stop and ask what to adjust. If they say "actually let me edit CHANGELOG first" โ let them, don't try to do it for them unless they ask.
Step 4 โ Execute (after user said yes)
Apply the changes in order. On any error, stop and report โ don't try to recover silently.
git add CHANGELOG.md pyproject.toml
git commit -m "chore(release): vX.Y.Z"
git tag vX.Y.Z
Tell the user what happened: "โ Committed v1.2.0 (commit abc1234), tag created locally."
Step 5 โ Push? ASK CONFIRM โ ๏ธ (separate from Step 3)
Pushing is the one part that's not locally reversible โ once it's on origin, other clones can pull it, and CI may run, and the world sees the tag.
Tag created locally. Push to origin?
git push origin main
git push origin vX.Y.Z
(yes / no โ answering no leaves everything local, you can push manually later)
Only push if the user explicitly says yes. "Yeah probably" / "I guess" โ ask again for an unambiguous answer.
If the user said yes in Step 3 but then said no here, that's normal โ Step 3 was about local writes; pushing is its own decision.
Examples
Example 1: Standard release
User: "Let's release v0.4 now"
Skill response (Step 1):
Reading state...
Last tag: v0.3.0 (2026-04-10)
Commits since v0.3.0:
feat(parser): support TOML config
fix(cli): exit code on missing input
[Unreleased] contains:
### Added
- TOML config support (#42)
### Fixed
- Wrong exit code when input file is missing (#48)
Step 2:
Recommendation: v0.4.0 (MINOR)
Reason: contains feat:, no breaking changes, currently at 0.x
(You said "v0.4", so v0.4.0 matches โ proceeding with that.)
Step 3 (preview + ask), then Step 4 only if yes, then Step 5 (separate push confirm).
Example 2: Nothing to release
User: "ๅ็"
Skill response:
Last tag: v1.0.0 (2026-05-15, 2 days ago)
Commits since: none.
[Unreleased] is empty.
There's nothing to release. Add changes first, or did you mean to tag an existing commit explicitly?
Stop. Don't pretend there's something to release.
Example 3: Partial use
User: "What version should we bump to?"
Run only Step 1 + Step 2, return the recommendation, stop. Don't drag them into a full release.
Anti-patterns
- โ Auto-pushing after commit. Push is a separate confirmation, always.
- โ Tag without
v prefix. Use v1.2.3, not 1.2.3 โ most tooling assumes the prefix.
- โ Same version twice. Once
v1.2.0 is tagged, only v1.2.1 or higher is legal.
- โ Silent CHANGELOG creation. If
CHANGELOG.md doesn't exist, ask before creating one.
- โ Restarting after partial failure. If commit succeeds but tag fails, don't undo the commit โ report the state and ask the user what to do.
- โ Using
git add -A / git add .. Stage only the files this skill changed; otherwise you risk pulling in unrelated work-in-progress.
Cancellation is always safe
At any step, if the user says "cancel" / "stop" / "็ฎไบ / ไธๅไบ":
- Steps 1โ3: nothing was written; just acknowledge and stop.
- Step 4: if any file was edited but not committed, suggest
git restore <file> โ but ask first, don't auto-revert.
- After Step 4 (committed but not pushed): the commit and tag exist locally. Tell the user how to undo if they want:
git reset --hard HEAD~1 && git tag -d vX.Y.Z. Don't run it yourself โ reset --hard is destructive.
- After Step 5 (pushed): can't be silently undone. Discuss with the user; usually the answer is "next version".
Hotfixes (release from an old tag)
When the user needs to patch an already-released version:
git checkout -b hotfix/v1.0.1 v1.0.0
Then run this skill โ but in Step 3's CHANGELOG preview, the new section goes under [1.0.1], not [Unreleased] (which belongs to the main line). After Step 5, ask whether to cherry-pick the fix to main.
When this skill is the wrong tool
- The project uses release-please. Then this skill duplicates what the automation does. Let
release-please-action propose the release PR; the user merges it; that's it.
- Publishing to PyPI / npm and need an action. Use a
release.yml workflow with OIDC trusted publishing (see trash/claude-md-template-ci/ for a template). This skill stops at tag creation; the workflow takes it from there.
- Just want to know the next version, not release yet. Run only Step 2.
See also