release

SkillAI & models

Create a release branch and PR to main with auto-extracted changes from staging

Available today. Use it from your connected AI after setup.

Connect ahel once, and every AI you use reads what you have installed.

Then ask your AI: use the release skill

What this skill tells your AI

The instructions your AI receives, as published by rlajous/claude-code-commands in skills/release/SKILL.md and read by ahel’s review.

Cross-runtime: follow runtime compatibility for invocation, delegation, configuration precedence, state paths, and permissions.

You are helping create a production release. Your task is to create a release branch from the development branch, bump the version, extract changes, and create a comprehensive release PR to the production branch.

Step 1: Load Configuration

Check for configuration:

if [ -f ".git-workflow/config.yaml" ]; then CONFIG_PATH=".git-workflow/config.yaml"; elif [ -f ".claude/config.yaml" ]; then CONFIG_PATH=".claude/config.yaml"; else CONFIG_PATH=""; fi

Load from the resolved CONFIG_PATH (canonical first, legacy read-only fallback):

workflow:
  type: staging # staging | tag-based | direct
  developmentBranch: staging
  productionBranch: main
branches:
  release: "release/{version}"
versioning:
  file: auto # auto | package.json | pyproject.toml | VERSION | Cargo.toml
release:
  watchFiles:
    openapi: docs/openapi.json
    migrations: prisma/migrations/**/migration.sql
    schema: prisma/schema.prisma
  generateChangelog: true

Default Values:

workflow:
  developmentBranch: staging
  productionBranch: main
branches:
  release: "release/{version}"
versioning:
  file: auto

Step 2: Verify Current State

Check that you're on the development branch and up-to-date:

# Get configured branches
DEV_BRANCH=$(config.workflow.developmentBranch || "staging")
PROD_BRANCH=$(config.workflow.productionBranch || "main")

# Check current branch
CURRENT=$(git branch --show-current)
echo "Current branch: $CURRENT"
echo "Expected: $DEV_BRANCH"

# Fetch latest
git fetch origin

# Check if up-to-date
git status

Validation:

  • If not on development branch:
    You must be on {DEV_BRANCH} branch to create a release.
    Run: git checkout {DEV_BRANCH} && git pull
    
  • If behind remote:
    Your {DEV_BRANCH} branch is behind origin.
    Run: git pull origin {DEV_BRANCH}
    
  • If there are uncommitted changes:
    You have uncommitted changes. Commit or stash them first.
    

Step 3: Detect Version File

Auto-detect or use configured version file:

# Check for version files in order of priority
if [ -f "package.json" ]; then
  VERSION_FILE="package.json"
  VERSION_TYPE="node"
elif [ -f "pyproject.toml" ]; then
  VERSION_FILE="pyproject.toml"
  VERSION_TYPE="python"
elif [ -f "Cargo.toml" ]; then
  VERSION_FILE="Cargo.toml"
  VERSION_TYPE="rust"
elif [ -f "VERSION" ]; then
  VERSION_FILE="VERSION"
  VERSION_TYPE="plain"
elif [ -f "build.gradle" ] || [ -f "build.gradle.kts" ]; then
  VERSION_FILE="build.gradle"
  VERSION_TYPE="gradle"
else
  VERSION_FILE="VERSION"
  VERSION_TYPE="plain"
fi

Read Current Version:

TypeCommand
Node.jsnode -p "require('./package.json').version"
Pythongrep -Po '(?<=version = ")[^"]*' pyproject.toml
Rustgrep -Po '(?<=^version = ")[^"]*' Cargo.toml
Plaincat VERSION
Gradlegrep -Po '(?<=version = ")[^"]*' build.gradle

Step 4: Ask for Version Type

Ask the user which version bump to perform (use the active host user-input mechanism):

Question: "What type of version bump for this release?"

Options:

  • patch: Bug fixes only (1.2.3 → 1.2.4)
  • minor: New features, backward compatible (1.2.3 → 1.3.0)
  • major: Breaking changes (1.2.3 → 2.0.0)

Display:

Current version: {CURRENT_VERSION}
Version file: {VERSION_FILE}

Select version bump:
- patch: {CURRENT} → {PATCH_VERSION}
- minor: {CURRENT} → {MINOR_VERSION}
- major: {CURRENT} → {MAJOR_VERSION}

Step 5: Calculate New Version

Based on user selection:

Current: 1.2.3
Patch:   1.2.4
Minor:   1.3.0
Major:   2.0.0

Version Calculation Logic:

// Parse version
const [major, minor, patch] = currentVersion.split('.').map(Number);

// Calculate new version based on type
switch (bumpType) {
  case 'patch':
    return `${major}.${minor}.${patch + 1}`;
  case 'minor':
    return `${major}.${minor + 1}.0`;
  case 'major':
    return `${major + 1}.0.0`;
}

Confirm with user:

Current version: 1.2.3
New version: 1.3.0

Proceed with release v1.3.0?

Step 6: Extract Changes from Development Branch

Get commits between production and development:

PROD_BRANCH=$(config.workflow.productionBranch || "main")
DEV_BRANCH=$(config.workflow.developmentBranch || "staging")

git log origin/${PROD_BRANCH}..origin/${DEV_BRANCH} --pretty=format:"%s" --no-merges

Categorize Commits:

Parse commits and group by type:

CategoryMatch Patterns
Bug Fixes[Fix], [FIX], fix:, fix(
Features[Feature], feat:, feat(
Improvements[Refactor], [Perf], improve, enhance
Documentation[Docs], docs:
OtherEverything else

Extract PR Numbers:

# Extract PR references: #123, (#456)
echo "$COMMIT_MSG" | grep -oE '#[0-9]+' | sort -u

Example Output:

### Bug Fixes

- Fix trending coins endpoint and date formatting (#662)
- Improve holder analysis accuracy (#655)

### Features

- Add cross-chain risk tag aggregation (#648)

### Improvements

- Preserve holder concentration precision (#647)

Step 7: Detect Special Changes

Validate readiness first. Delegate a pre-release check to the release-validator agent through the active host subagent mechanism (it checks tests, build, lint, types, dependency audit, changelog, and git state) and fold any blockers into the checklist. When the release bumps a dependency/framework/API version or changes a public API, also delegate to the version-delta-analyst agent to catalog breaking changes and populate the PR's "Breaking Changes" section. Start both applicable agents before waiting, then wait for every delegated report.

OpenAPI Changes

If release.watchFiles.openapi is configured:

OPENAPI_FILE=$(config.release.watchFiles.openapi || "docs/openapi.json")

if git diff --quiet origin/${PROD_BRANCH}..origin/${DEV_BRANCH} -- "${OPENAPI_FILE}"; then
  OPENAPI_CHANGED=false
else
  OPENAPI_CHANGED=true
  # Extract version from OpenAPI spec if present
  OPENAPI_VERSION=$(jq -r '.info.version // "unknown"' "${OPENAPI_FILE}" 2>/dev/null)
fi

Database Migrations

If release.watchFiles.migrations is configured:

MIGRATION_PATTERN=$(config.release.watchFiles.migrations || "prisma/migrations/**/migration.sql")

MIGRATION_FILES=$(git diff --name-only --diff-filter=A origin/${PROD_BRANCH}..origin/${DEV_BRANCH} -- "${MIGRATION_PATTERN}")
MIGRATION_COUNT=$(echo "$MIGRATION_FILES" | grep -c . || echo 0)

if [ "$MIGRATION_COUNT" -gt 0 ]; then
  MIGRATIONS_CHANGED=true
  MIGRATION_NAMES=$(echo "$MIGRATION_FILES" | xargs -n1 dirname | xargs -n1 basename | paste -sd "," -)
fi

Schema Changes

SCHEMA_FILE=$(config.release.watchFiles.schema || "prisma/schema.prisma")

if git diff --quiet origin/${PROD_BRANCH}..origin/${DEV_BRANCH} -- "${SCHEMA_FILE}"; then
  SCHEMA_CHANGED=false
else
  SCHEMA_CHANGED=true
fi

Step 8: Extract Contributors

Get list of contributors:

git log origin/${PROD_BRANCH}..origin/${DEV_BRANCH} --format='%an' --no-merges | sort -u

Format as GitHub mentions: @username1 @username2 @username3

Step 9: Create Release Branch

RELEASE_BRANCH_PATTERN=$(config.branches.release || "release/{version}")
RELEASE_BRANCH=${RELEASE_BRANCH_PATTERN/\{version\}/${NEW_VERSION}}

# Create release branch from development
git checkout -b ${RELEASE_BRANCH}

Example: release/1.3.0

Step 10: Merge Production into Release

Ensure release branch has any hotfixes from production:

git fetch origin ${PROD_BRANCH}
git merge origin/${PROD_BRANCH} --no-edit

This ensures the release includes:

  • All development changes
  • Any hotfixes that went directly to production

Step 11: Bump Version

Based on detected version file type:

Node.js (package.json)

npm version ${BUMP_TYPE} --no-git-tag-version
git add package.json package-lock.json
git commit -m "${NEW_VERSION}"
git tag "v${NEW_VERSION}"

Python (pyproject.toml)

# Using poetry
poetry version ${BUMP_TYPE}
git add pyproject.toml
git commit -m "${NEW_VERSION}"
git tag "v${NEW_VERSION}"

# Or using hatch
hatch version ${BUMP_TYPE}

# Or manual sed
sed -i 's/version = "[^"]*"/version = "'${NEW_VERSION}'"/' pyproject.toml

Rust (Cargo.toml)

# Using cargo-edit
cargo set-version ${NEW_VERSION}
git add Cargo.toml Cargo.lock
git commit -m "${NEW_VERSION}"
git tag "v${NEW_VERSION}"

Plain VERSION file

echo "${NEW_VERSION}" > VERSION
git add VERSION
git commit -m "${NEW_VERSION}"
git tag "v${NEW_VERSION}"

Step 12: Push Release Branch

git push -u origin ${RELEASE_BRANCH} --follow-tags

Step 13: Generate Release PR Description

Use this template:

## Release v{VERSION}

This release includes {summary of changes} from {DEV_BRANCH}.

### Key Changes

{CATEGORIZED_CHANGES}

### Contributors

{CONTRIBUTORS_LIST}

### Testing & QA

All changes have been tested on {DEV_BRANCH} environment and are ready for production deployment.

---

**Release Checklist:**

- [x] Version bumped to {VERSION}
- [x] All tests passing on {DEV_BRANCH}
- [ ] Code review completed
- [ ] CI checks passing
- [ ] Ready for production deployment

If Migrations Detected:

## Database Migration Alert

This release includes {MIGRATION_COUNT} database migration(s):
{MIGRATION_NAMES}

**Pre-Deployment:**

- [ ] Verify migrations ran successfully in {DEV_BRANCH}
- [ ] Review migration SQL for issues
- [ ] Coordinate deployment timing with team
- [ ] Prepare rollback plan

**Post-Deployment:**

- [ ] Monitor deployment logs
- [ ] Verify database schema
- [ ] Run smoke tests

If OpenAPI Changed:

## API Documentation Update

The OpenAPI specification was modified in this release.
Current spec version: {OPENAPI_VERSION}

After merge, create documentation tag:

```bash
git tag docs-v{OPENAPI_VERSION}
git push origin docs-v{OPENAPI_VERSION}

## Step 14: Create PR to Production

```bash
PROD_BRANCH=$(config.workflow.productionBranch || "main")

gh pr create \
  --base ${PROD_BRANCH} \
  --title "[RELEASE] v${NEW_VERSION}" \
  --body "$(cat <<'EOF'
{GENERATED_DESCRIPTION}
EOF
)"

Important: Release PRs always target production branch (main).

Step 15: Confirm and Next Steps

Release branch created: {RELEASE_BRANCH}
Version bumped: {OLD_VERSION} → {NEW_VERSION}
PR created: {PR_URL}
Title: [RELEASE] v{NEW_VERSION}

Next steps:
1. Review the PR for accuracy
2. Get team approval
3. Merge PR to {PROD_BRANCH} (use "Squash and merge")
4. Run /release-notes to create GitHub release
5. Run /sync to back-merge {PROD_BRANCH} to {DEV_BRANCH}

Configuration Reference

Full settings table: see references/configuration.md.

Error Handling

Full error-scenario table: see references/error-handling.md.

Version File Examples

Example package.json, pyproject.toml, Cargo.toml, and VERSION snippets: see references/version-file-examples.md.

Example Complete Flow

Full worked example of a complete /release run: see references/examples.md.

Signals

GitHub stars
30
Forks
2
Last commit
Aug 2026
Hacker News mentions
20
Advanced
Catalog kind
skill
Gateway key
release-rlajous
Source
github.com/rlajous/claude-code-commands