Tag And Release
Orchestrate a carn release with human-readable release notes.
# Tag and Release
Orchestrate a carn release with human-readable release notes.
Walk through each step below interactively. Do not skip steps or batch
multiple confirmations. Wait for user input where indicated.
## Step 0 — Preflight checks
Before starting, verify the working tree is ready for a release:
1. Run `git status` — the working tree must be clean (no staged,
unstaged, or untracked changes). If dirty, stop and ask the user
to commit or stash before continuing.
2. Run `git fetch origin` and compare `git rev-parse HEAD` with
`git rev-parse @{upstream}`. If HEAD is behind the remote, stop
and ask the user to pull. If ahead, warn that unpushed commits
exist and confirm they should be included in the release.
## Step 1 — Gather context
Run these commands to understand what changed since the last release.
Find the last tag:
```bash
LAST_TAG=$(git describe --tags --abbrev=0)
Then list commits since that tag with full bodies:
git log "${LAST_TAG}..HEAD" --format='%h %s%n%b---'
Categorize commits by type (feat, fix, refactor, perf, chore,
docs, style) and by scope. Count features and fixes.
Step 2 — Determine version
Present the user with a short summary of what changed (number of features, fixes, improvements). Suggest a version number:
- Any
featcommits → suggest minor bump (e.g. v0.1.0 → v0.2.0) - Only
fixcommits → suggest patch bump (e.g. v0.1.0 → v0.1.1) - Any commit body containing
BREAKING CHANGE→ suggest major bump
Ask the user what version this should be. Accept their explicit version or their confirmation of the suggestion.
Step 3 — Update project documents
Skip this step for patch releases. Fixes rarely introduce new types, change package structure, or move performance baselines. Proceed directly to Step 4.
For minor or major releases, update the project's baseline documents so they reflect the code being tagged. Work through each document below and make the necessary edits.
PERF_BASELINE.md
Run the full benchmark suite from CLAUDE.md — one command at a time,
sequentially. Replace the results table with fresh numbers and update the
"Refreshed on" date. If any benchmark moved more than 5% in either
direction, update the Delta Summary section comparing old vs. new values.
Remove delta entries that are no longer relevant.
CLAUDE.md
Check the Package map section against the actual files on disk:
- Verify every file path listed still exists. Remove stale entries.
- Glob
internal/**/*.go(excluding*_test.go) and check for files that are not mentioned in the package map. Add missing entries under the appropriate group. - Check the Core types list against
internal/conversation/*.goexports. Add new types and remove deleted ones.
VOCABULARY.md
Review for completeness against changes since the last tag:
- Check for new exported types, concepts, or UI elements introduced
since
$LAST_TAG. - Add any missing terms to the appropriate section.
- Remove terms for features or concepts that no longer exist.
Commit
If any documents changed, stage and commit them before proceeding:
TMPFILE=$(mktemp)
cat > "$TMPFILE" << EOF
docs: refresh baseline documents for release
Update PERF_BASELINE.md, CLAUDE.md, and VOCABULARY.md to reflect
the current state of the codebase ahead of tagging.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
EOF
git add PERF_BASELINE.md CLAUDE.md VOCABULARY.md
git commit -F "$TMPFILE"
rm "$TMPFILE"
If nothing changed, skip the commit and continue.
Step 4 — Draft release notes
Write human-readable release notes describing the final shipped state, not the development journey.
Grouping rules
- Fixes to a new feature introduced in this release are absorbed into that feature's description. For example, if stats is new in this release, stats chart color fixes belong in the stats feature entry, not in a separate Fixes section.
- The Fixes section only contains fixes to functionality that existed before this release.
- The Improvements section only covers changes to pre-existing behavior.
Format
## What's new in v{version}
<1-3 paragraphs of prose summary describing the release from a user
perspective. Focus on what changed and why it matters. Do not list commits.>
### Features
- **Feature name** — description of what it does and why it matters.
Include relevant details that were refined during development.
### Fixes
- Description of what was broken and how it now works.
### Improvements
- Description of the improvement and its user-visible effect.
### Breaking Changes
- What changed and what users need to do.
Rules:
- Use
##(H2) for the top heading (GitHub prepends the release name as H1) - Bold lead-in phrases for each entry
- No commit hashes, author names, or PR numbers
- Omit empty sections entirely
Present the full draft and ask the user to review. Wait for them to say "looks good" or request changes. Iterate until approved.
Step 5 — Visual content
Ask the user: "Do you want to add screenshots, ASCII art, or neither for this release?"
If screenshots
- Ask for file paths
- Create
releases/assets/v{version}/directory - Copy files there
- Insert image references in the release notes using:

If ASCII art
Ask the user to provide the ASCII art (e.g. from https://monosketch.io/) or offer to create a simple text representation. Inline it in a fenced code block in the release notes.
If neither
Proceed with prose only.
Step 6 — Write and commit release notes
After the user approves the final draft:
- Create
releases/directory if it does not exist - Write the release notes to
releases/v{version}.md - If
CHANGELOG.mdexists, prepend the n
Maintain Tag And Release?
Let people know it's listed here — add the badge (live metrics, light/dark aware) or a plain link to your README or docs.
[Tag And Release on getagentictools](https://getagentictools.com/loops/rkuska-tag-and-release?ref=badge)