release
Automated release pipeline that generates tags and PRs while enforcing human approval gates.
Install
mkdir -p .claude/skills/release-usetheodev && curl -L -o skill.zip "https://agentskills.codes/api/skills/download/12337" && unzip -o skill.zip -d .claude/skills/release-usetheodev && rm skill.zipInstalls to .claude/skills/release-usetheodev
Activation
This is the description your AI agent reads to decide when to run this skill — the better it matches your request, the more reliably it fires.
Cuts a semver-tagged release from develop → main after /review returns READY_TO_MERGE. Auto-derives version from CHANGELOG sections (major/minor/patch), rewrites [Unreleased] under the new version header, commits chore(release), opens a PR develop→main with rendered release notes, and waits for human approval (the only manual gate — Unbreakable Rule 4). On merge, creates an annotated tag and a GitHub release. Single entry-point for cycle-release. Use after /review {slug} returned READY_TO_MERGE.Key capabilities
- →Automate semantic version bumping based on CHANGELOG.md
- →Rewrite CHANGELOG.md to promote unreleased changes to a new version
- →Create a chore(release) commit on the develop branch
- →Open a pull request from develop to main with rendered release notes
- →Create an annotated tag and GitHub release upon PR merge
How it works
The skill validates pre-conditions, computes the next semantic version from the CHANGELOG, updates the CHANGELOG, commits the changes, and creates a pull request for human approval.
Inputs & outputs
When to use release
- →Cut a new release version
- →Automate version bumping
- →Prepare production release branch
About this skill
Release — develop → main with semver tag
Single entry-point for cycle-release. Automates the release ritual end-to-end while keeping the human approval at PR merge — the only manual step Unbreakable Rule 4 mandates.
Cycle contract
This skill is the only phase of cycle-release. The cycle rule is the source of truth for pre-conditions, verdicts (RELEASED / PR_OPEN_AWAITING_APPROVAL / BLOCKED), hard gates (PR approval mandatory; no direct main commits; annotated-tag-only), stop conditions, and anti-patterns. Read cycle-release.md before invoking.
When to trigger
User invokes /release [bump-level] when:
- A
/review {slug}run emittedREADY_TO_MERGErecently (audit atknowledge-base/reviews/{slug}-review-{date}.md). - The working branch is
developwith commits ahead ofmain. CHANGELOG.mdhas content in[Unreleased].ghCLI is authenticated.
Refuse to start when any pre-condition declared in cycle-release.md § Pre-conditions fails.
Argument
{bump-level} is optional. When omitted, the skill derives the bump deterministically from CHANGELOG.md § [Unreleased]:
| Trigger in [Unreleased] | Bump |
|---|---|
### Removed non-empty OR ### Changed entry starts with BREAKING: | major |
### Added non-empty AND no major trigger | minor |
Only ### Fixed / ### Security entries | patch |
If derivation is ambiguous, the skill pauses and asks the human ONCE.
Workflow
Step 1 — Pre-condition validation (refuse if any fails)
# Branch is develop
[ "$(git branch --show-current)" = "develop" ]
# Clean tree
[ -z "$(git status --porcelain)" ]
# Latest /review verdict is READY_TO_MERGE
LATEST_REVIEW=$(ls -t knowledge-base/reviews/*-review-*.md 2>/dev/null | head -1)
grep -q '^\*\*Verdict:\*\* READY_TO_MERGE' "$LATEST_REVIEW"
# CHANGELOG [Unreleased] has content
python3 skills/release/scripts/changelog_section_nonempty.py --section Unreleased
# gh CLI authenticated
gh auth status >/dev/null 2>&1
# No release PR already open
[ -z "$(gh pr list --base main --head develop --state open --json number)" ]
If any HARD check fails, refuse with the missing piece surfaced honestly.
Step 2 — Detect current version and compute next
LAST_TAG=$(git describe --tags --abbrev=0 2>/dev/null || echo "v0.0.0")
NEXT_VERSION=$(python3 skills/release/scripts/compute_next_version.py \
--current "$LAST_TAG" \
--bump "${ARGUMENTS:-auto}" \
--changelog CHANGELOG.md)
If compute_next_version.py returns AMBIGUOUS, AskUserQuestion ONCE (major / minor / patch) and re-run with the chosen value.
If a tag for $NEXT_VERSION already exists, halt — never overwrite a published tag.
Step 3 — Rewrite CHANGELOG
python3 skills/release/scripts/promote_unreleased.py \
--changelog CHANGELOG.md \
--version "$NEXT_VERSION" \
--date "$(date -u +%Y-%m-%d)"
This script:
- Moves the current
[Unreleased]body under a new## [{version}] - {date}section. - Leaves a fresh empty
## [Unreleased]at the top. - Preserves Keep-a-Changelog category ordering (
Added→Changed→Deprecated→Removed→Fixed→Security).
Step 4 — Commit the release prep on develop
git add CHANGELOG.md
git commit -m "chore(release): ${NEXT_VERSION}"
git push origin develop
NO Co-Authored-By trailer (per hooks/validate-command.sh). NO --amend. The commit is plain and signed by user policy.
Step 5 — Open the release PR
RELEASE_NOTES=$(python3 skills/release/scripts/render_release_notes.py \
--changelog CHANGELOG.md \
--version "$NEXT_VERSION")
gh pr create \
--base main \
--head develop \
--title "release: ${NEXT_VERSION}" \
--body "$RELEASE_NOTES"
PR URL is captured; reported back to the user. The chain now pauses at the human-approval gate (verdict PR_OPEN_AWAITING_APPROVAL).
Step 6 — Wait for human approval (the only manual gate)
The skill does NOT auto-merge. The user reviews + approves + merges the PR through GitHub UI / gh pr merge of their choice.
When the user resumes by re-invoking /release --resume {pr-number} (or by running /release again with the same develop/main state), the skill:
# Detect merge state
MERGE_STATE=$(gh pr view "$PR_NUMBER" --json state,mergedAt --jq '.state')
[ "$MERGE_STATE" = "MERGED" ] || { echo "PR not merged yet — re-run after merge." ; exit 0 ; }
If the PR was closed without merge → emit BLOCKED and record the rationale in the release log.
Step 7 — Tag the merge commit + publish GitHub release
# Fetch the merge commit
git fetch origin main
MERGE_SHA=$(gh pr view "$PR_NUMBER" --json mergeCommit --jq '.mergeCommit.oid')
# Annotated tag pointing at the merge commit
git tag -a "v${NEXT_VERSION}" "$MERGE_SHA" -m "Release v${NEXT_VERSION}"
git push origin "v${NEXT_VERSION}"
# Publish GitHub release with the rendered notes
gh release create "v${NEXT_VERSION}" \
--title "v${NEXT_VERSION}" \
--notes "$RELEASE_NOTES" \
--target "$MERGE_SHA"
Step 7.5 — Flip ROADMAP.md milestone checkbox (post-merge)
Closes the cycle-roadmap super-loop. Runs after the tag + GitHub release are published.
# Extract the plan slug from the release context (passed from /auto-plan, or derived from the source review)
PLAN_FILE="knowledge-base/plans/${SLUG}-plan.md"
# Read milestone_id from the plan frontmatter
MILESTONE_ID=$(python3 -c "
import sys, yaml
with open('$PLAN_FILE') as f:
raw = f.read()
parts = raw.split('---', 2)
if len(parts) >= 3:
meta = yaml.safe_load(parts[1])
print(meta.get('milestone_id', ''))
")
if [ -z "$MILESTONE_ID" ]; then
echo "WARN roadmap-checkbox: plan has no milestone_id — skipping flip (ad-hoc release)"
else
python3 skills/release/scripts/flip_milestone_checkbox.py \
--roadmap ROADMAP.md \
--milestone-id "$MILESTONE_ID" \
--version "$NEXT_VERSION" \
--plan "$PLAN_FILE" \
--release-log "knowledge-base/releases/v${NEXT_VERSION}-release.md"
fi
flip_milestone_checkbox.py MUST:
- Locate the literal header
## ${MILESTONE_ID} — [ ] <name>inROADMAP.md. If not found, emitWARN roadmap-checkbox: $MILESTONE_ID not found in ROADMAP.md — skipping flipand exit 0. - If header is already
[x], emitINFO roadmap-checkbox: $MILESTONE_ID already [x] — no-opand exit 0 (idempotent). - Replace
[ ]→[x]in-place. NEVER use fuzzy matching. - Commit on
develop(NOTmain):chore(roadmap): mark $MILESTONE_ID done (v$NEXT_VERSION). - Append to
knowledge-base/roadmap-runs/${MILESTONE_ID}-$(date -I).md:status: completed,checkbox_flipped_at,flip_commit_sha, link to release log. Create the file if it does not exist.
Per cycle-release § Single-flip invariant, at most ONE checkbox flips per release. The script verifies its own diff before committing — if more than one [ ] → [x] transition would result, it aborts.
Step 8 — Record the release
Write knowledge-base/releases/v${NEXT_VERSION}-release.md:
# Release v{NEXT_VERSION}
**Date:** {YYYY-MM-DD}
**Verdict:** RELEASED
**Source review:** {path to /review report}
**PR:** {pr-url}
**Merge commit:** {merge-sha}
**Tag:** v{NEXT_VERSION}
**GitHub release:** {release-url}
## Release notes
{rendered notes}
Step 9 — Recommend next step
=== /release complete ===
Version: v{NEXT_VERSION}
PR: {url}
Merge commit: {sha}
Tag: v{NEXT_VERSION}
GitHub release: {url}
Next: nothing — release is published. Start a new cycle with /to-plan or /grill-me.
Hard gates (cannot proceed)
/reviewverdict is notREADY_TO_MERGE→ refuse. Re-run/reviewfirst.- PR approval mandatory — the skill NEVER auto-merges the release PR. Auto-merge violates Unbreakable Rule 4.
- Tag must be annotated (
git tag -a) — never lightweight tags. - CHANGELOG [Unreleased] non-empty — empty releases are forbidden.
- No duplicate version tags — if
v{X}already exists, halt. - Single-flip invariant — Step 7.5 flips at most ONE checkbox per release. Multi-milestone flips abort the script.
Soft gates (proceed with note)
- CI not green on develop — warn but proceed; the human catches it at PR approval.
- Bump-level ambiguous from CHANGELOG — AskUserQuestion ONCE per release run.
Anti-patterns
- Auto-merging the release PR — never. Unbreakable Rule 4.
- Skipping
cycle-review— every release traces to aREADY_TO_MERGEaudit. - Editing CHANGELOG entries during the release — discipline lives in the cycles that produce the entries.
- Cutting a release with unaddressed FAIL_HARD from
/code-quality— the review gate enforces this; never bypass. git push --forceon a release tag — tags are immutable once published; if wrong, deprecate and cut a new version.- Co-Authored-By trailer on the
chore(release)commit — blocked byhooks/validate-command.sh. - Fuzzy-matching the milestone for the checkbox flip in Step 7.5. Plan declares
milestone_id: M3→ flip M3 by literal header match, never M4. - Flipping multiple checkboxes from one release. Each release maps to one milestone via plan
milestone_id. - Blocking the release if
milestone_idis missing. Ad-hoc / hotfix work skips the flip with WARN — never blocks.
Cycle contract
This skill is phase 1 (only phase) of cycle-release. The cycle rule SoT is rules/cycle-release.md. Hard gates + soft gates + anti-patterns live there.
Related
- Cycle rule (SoT):
rules/cycle-release.md - Upstream cycle:
rules/cycle-review.md— consumesREADY_TO_MERGEverdict - Conventions:
rules/public-copy.md— release notes lint - Hooks enforced:
hooks/validate-command.sh(git safety + Co-Authored-By block),hooks/stop-validation.sh(CHANGELOG hard gate)
Content truncated.
When not to use it
- →When direct commits to main are allowed
- →When auto-merging release pull requests is desired
- →When editing CHANGELOG entries during the release process
Prerequisites
Limitations
- →It does not auto-merge the release PR
- →It requires a `READY_TO_MERGE` verdict from a `/review` run
- →It does not allow editing CHANGELOG entries during the release
How it compares
This skill automates the entire release ritual from version derivation to PR creation and tagging, while enforcing a human approval gate, unlike a manual release process.
Compared to similar skills
release side by side with the closest alternatives in the catalog.
| Skill | Installs | Updated | Safety | Difficulty |
|---|---|---|---|---|
| release (this skill) | 0 | 1mo | Review | Advanced |
| gcp-cloud-run | 5 | 5mo | Review | Intermediate |
| flow-nexus-platform | 6 | 4mo | Review | Beginner |
| smithery-mcp-deployment | 8 | 8mo | Review | Intermediate |
Try saying
Example prompts that trigger this skill in your AI assistant.
More by usetheodev
View all by usetheodev →You might also like
gcp-cloud-run
aj-geddes
Deploy containerized applications on Google Cloud Run with automatic scaling, traffic management, and service mesh integration. Use for container-based serverless computing.
flow-nexus-platform
ruvnet
Comprehensive Flow Nexus platform management - authentication, sandboxes, app deployment, payments, and challenges
smithery-mcp-deployment
CaullenOmdahl
Best practices for creating, optimizing, and deploying MCP servers to Smithery. Use this skill when:(1) Creating new MCP servers for Smithery deployment(2) Optimizing quality scores (achieving 90/100)(3) Troubleshooting deployment issues (0/0 tools, missing annotations, low scores)(4) Migrating existing MCP servers to Smithery format(5) Understanding Smithery's schema format requirements(6) Adding workflow prompts, tool annotations, or documentation resources(7) Configuring smithery.yaml and package.json for deployment
deployment-pipeline-design
wshobson
Design multi-stage CI/CD pipelines with approval gates, security checks, and deployment orchestration. Use when architecting deployment workflows, setting up continuous delivery, or implementing GitOps practices.
vercel-deployment
davila7
Expert knowledge for deploying to Vercel with Next.js Use when: vercel, deploy, deployment, hosting, production.
netlify-deploy
openai
Deploy web projects to Netlify using the Netlify CLI (`npx netlify`). Use when the user asks to deploy, host, publish, or link a site/repo on Netlify, including preview and production deploys.