name: releasing
description: Full release lifecycle — version bump, CHANGELOG, rich release notes, tag, publish. Use when user says "release", "tag and release", "publish version", "cut a release", "new version".
user-invocable: true
allowed-tools:
- Bash(git *)
- Bash(gh *)
- Bash(git cliff *)
- Bash(make check)
- Read
argument-hint: "[patch|minor|major|] (e.g., patch, minor, 2.4.0)"
Release
Tag and publish a new version with rich, narrative release notes.
Step 1: Pre-flight
Run in parallel:
git branch --show-current # Must be main
git status --porcelain # Must be clean
git log origin/main..HEAD --oneline # Must be empty (all pushed)
If any fail: report and stop.
Run make check — all must pass.
Step 2: Determine Version
Get the last tag:
git describe --tags --abbrev=0
Parse $ARGUMENTS:
- If a semver like
2.4.0→ use it directly - If
patch/minor/major→ bump the last tag accordingly - If empty → analyze commits since last tag to suggest:
featcommits → minor- Only
fix/docs/refactor→ patch - Breaking changes → major
- Present suggestion, ask user to confirm
The version is X.Y.Z (no v prefix in display). The git tag is vX.Y.Z.
Step 3: Generate CHANGELOG
git cliff --tag vX.Y.Z --output CHANGELOG.md
Step 4: Craft Release Notes
Read the FULL diff since the last tag to understand every change:
git diff <last-tag>..HEAD -- '*.py' '*.yml' '*.toml'
git log <last-tag>..HEAD --format="%H %s"
Also read any PR descriptions referenced in commits:
gh pr list --state merged --search "is:merged" --limit 20 --json number,title,body
Now write release notes following this structure and style (study existing releases for tone):
Style Rules
Lead with a theme headline — one sentence summarizing what this release is about
- Feature release:
## Shell Provider — Chat-First Shell Interface via Telegram - Bug fix release:
## Bug Fixes & Reliability - Mixed:
## Wrap Prompt Mode — Preserve Your Shell Prompt
- Feature release:
Explain WHY, not just WHAT — don't just list commit messages. Explain user-facing impact:
- Bad:
- Fix idempotent prompt markers - Good:
- **Idempotent prompt markers** — guards prevent duplicate marker injection on repeated setup (e.g., after exec bash or profile reload)
- Bad:
Group by theme, not commit type — if 3 fixes all relate to "shell prompt reliability", group them under that heading instead of a flat "### Fixed" list
Include context — before/after examples, tables, config snippets where they help
End with Install / Upgrade block — always include
uv tool upgrade ccgramandbrew upgrade ccgramKeep it concise — a patch release with 2 fixes needs 15-20 lines, not 100. Scale depth with change magnitude.
No "Documentation" section — skip changelog/readme commits, they're noise in release notes
Link PRs where available:
([#36](https://github.com/alexei-led/ccgram/pull/36))
Present the draft release notes to the user for review before proceeding.
Step 5: Commit and Tag
git add CHANGELOG.md
git commit -m "docs: update CHANGELOG.md for vX.Y.Z"
git push origin main
git tag vX.Y.Z
git push origin vX.Y.Z
CRITICAL: The CHANGELOG commit message must NOT contain [skip ci] — it kills tag-triggered workflows.
Step 6: Update GitHub Release
Poll until the release exists (CI creates it), then edit with the crafted notes:
# Poll every 15s, up to 5 minutes
gh release view vX.Y.Z --json tagName 2>/dev/null
Once it exists:
gh release edit vX.Y.Z --notes "<crafted release notes>"
Report final status with link to the release.
Notes
- hatch-vcs generates version from tag:
v2.4.0→ PyPI2.4.0 - Release workflow:
.github/workflows/release.yml(3 jobs: PyPI, Homebrew, GitHub Release) - CI uses git-cliff
--latestfor baseline notes; this skill replaces them with rich notes - Re-tag if needed:
git tag -d vX.Y.Z && git push origin :refs/tags/vX.Y.Z