| name | release |
| description | Create software releases with version bumping, changelog updates, git tags, and GitHub releases. Use when: "create a release", "bump version", "tag release", "publish version", "/release". Handles VERSION files, package.json, Cargo.toml, pyproject.toml, and go.mod projects. |
| triggers | release, create release, bump version, tag version, publish release, cut a release, new version |
Release Skill
Create consistent, safe software releases across any project type.
Invocation
/release # Interactive - detect and prompt
/release patch # Bump patch version (0.0.X)
/release minor # Bump minor version (0.X.0)
/release major # Major version bump (X.0.0)
/release v2.5.0 # Set explicit version
/release --dry-run # Preview without executing
Workflow Overview
┌─────────────────────────────────────────────────────────────────┐
│ RELEASE WORKFLOW │
├─────────────────────────────────────────────────────────────────┤
│ │
│ Phase 1: Pre-flight Checks │
│ ├─ Clean working tree? │
│ ├─ On releasable branch? (main/master/release/*) │
│ ├─ Tests passing? │
│ └─ Detect project type & current version │
│ │
│ Phase 2: Version Bump │
│ ├─ Calculate new version │
│ ├─ Update version file(s) │
│ └─ Update version references in docs │
│ │
│ Phase 3: Changelog & Docs │
│ ├─ Generate changelog entry (if CHANGELOG.md exists) │
│ ├─ Update README.md badges/versions (if applicable) │
│ └─ Update CLAUDE.md version (if applicable) │
│ │
│ Phase 4: Build & Verify │
│ ├─ Run build command (make build, npm build, etc.) │
│ ├─ Run linters/formatters (gofmt, eslint, etc.) │
│ └─ Verify build succeeded │
│ │
│ Phase 5: Git Operations │
│ ├─ Stage all changes │
│ ├─ Commit: "chore(release): vX.Y.Z" │
│ ├─ Create annotated tag: vX.Y.Z │
│ └─ Push commits and tags │
│ │
│ Phase 6: GitHub Release (optional) │
│ ├─ Generate release notes from commits │
│ └─ Create GitHub release via gh CLI │
│ │
└─────────────────────────────────────────────────────────────────┘
Phase 1: Pre-flight Checks
1.1 Working Tree Status
git status --porcelain
STOP if uncommitted changes exist. Ask user to commit or stash first.
Exception: If --dry-run flag, continue but warn.
1.2 Branch Check
git branch --show-current
Allowed branches:
main,master- production releasesrelease/*- release branchesdevelop- pre-releases only (append-beta.Nor-rc.N)
If on feature branch:
- Ask user: "Merge to main first?"
- If yes:
git checkout main && git merge <feature-branch> --ff-only - Continue release from main
1.3 Test Suite
Run tests if test command is detectable:
| Project Type | Test Command |
|---|---|
| Go | go test ./... |
| Node.js | npm test or yarn test |
| Rust | cargo test |
| Python | pytest or python -m pytest |
| Make-based | make test (if target exists) |
STOP if tests fail. Do not proceed with broken tests.
1.4 Project Detection
Detect project type by scanning for these files (in order):
| File | Type | Version Location | Build Command |
|---|---|---|---|
VERSION |
Generic | File contents | make build (if Makefile) |
package.json |
Node.js | .version field |
npm run build |
Cargo.toml |
Rust | version = "X.Y.Z" |
cargo build --release |
pyproject.toml |
Python | version = "X.Y.Z" |
python -m build |
go.mod |
Go | Git tags only | go build ./cmd/... |
build.gradle |
Java/Gradle | version 'X.Y.Z' |
./gradlew build |
pom.xml |
Java/Maven | <version> tag |
mvn package |
Extract current version from the detected source.
If no version file found, check latest git tag:
git describe --tags --abbrev=0 2>/dev/null || echo "v0.0.0"
Phase 2: Version Bump
2.1 Parse Current Version
Extract semantic version components: MAJOR.MINOR.PATCH[-PRERELEASE]
Examples:
2.31.0→ major=2, minor=31, patch=01.0.0-beta.1→ major=1, minor=0, patch=0, pre=beta.1
2.2 Calculate New Version
| Bump Type | Current | New |
|---|---|---|
patch |
2.31.0 | 2.31.1 |
minor |
2.31.0 | 2.32.0 |
major |
2.31.0 | 3.0.0 |
explicit v2.35.0 |
2.31.0 | 2.35.0 |
Pre-release handling:
- If current is
2.0.0-beta.1and bump ispatch→2.0.0-beta.2 - To exit pre-release: use explicit version or
--graduate
2.3 Update Version Files
Update ALL version locations found:
VERSION file:
echo "X.Y.Z" > VERSION
package.json:
npm version X.Y.Z --no-git-tag-version
# Or edit directly with jq/sed
Cargo.toml:
version = "X.Y.Z"
pyproject.toml:
version = "X.Y.Z"
Go projects: Version comes from git tag, no file update needed.
Phase 3: Changelog & Documentation
3.1 CHANGELOG.md (if exists)
Generate changelog entry from commits since last tag:
git log $(git describe --tags --abbrev=0)..HEAD --oneline --no-merges
Format (Keep a Changelog style):
## [X.Y.Z] - YYYY-MM-DD
### Added
- New feature descriptions (from feat: commits)
### Changed
- Change descriptions (from refactor:, chore: commits)
### Fixed
- Bug fix descriptions (from fix: commits)
Categorize by conventional commit prefix:
feat:→ Addedfix:→ Fixedrefactor:,perf:→ Changeddocs:→ Documentationchore:,build:,ci:→ Maintenance (optional section)
Insert new section after # Changelog header, before previous releases.
3.2 README.md Updates
Search for version badges or references:

Update to new version if found.
3.3 CLAUDE.md Updates
If CLAUDE.md exists and contains version reference, update it:
**Current**: v2.31.0 - Description here
Update to:
**Current**: vX.Y.Z - Description here
Phase 4: Build & Verify
4.1 Detect Build Command
| Condition | Command |
|---|---|
Makefile with build target |
make build |
Makefile with build-patch/minor/major |
Use appropriate target |
package.json with build script |
npm run build |
| Cargo.toml | cargo build --release |
| go.mod | go build ./... |
| pyproject.toml | python -m build |
4.2 Execute Build
Run the detected build command. STOP if build fails.
# Example for Make-based projects
make build
4.3 Verify Artifacts
Check that expected artifacts exist:
- Binary in expected location
- No error output
- Exit code 0
4.4 Run Linters/Formatters (CI Parity)
Run the same checks CI will run to avoid post-push failures:
| Language | Commands |
|---|---|
| Go | gofmt -l . && go vet ./... |
| Node.js | npm run lint (if exists) |
| Rust | cargo fmt --check && cargo clippy |
| Python | ruff check . && black --check . |
STOP if linting fails. Fix before proceeding.
# Example for Go projects
gofmt -w . # Auto-fix formatting
go vet ./...
Phase 5: Git Operations
5.1 Stage Changes
git add -A
5.2 Create Release Commit
git commit -m "chore(release): v${VERSION}
Release version ${VERSION}
Changes in this release:
$(git log $(git describe --tags --abbrev=0 2>/dev/null || echo "")..HEAD~1 --oneline --no-merges | head -20)
"
5.3 Create Annotated Tag
git tag -a "v${VERSION}" -m "Release v${VERSION}"
Tag format: Always prefix with v (e.g., v2.32.0)
5.4 Push to Remote
git push origin $(git branch --show-current)
git push origin "v${VERSION}"
Ask for confirmation before push unless --yes flag provided.
Phase 6: GitHub Release (Optional)
6.1 Check for gh CLI
gh --version
Skip this phase if gh not installed or not authenticated.
6.2 Generate Release Notes
gh api repos/{owner}/{repo}/releases/generate-notes \
-f tag_name="v${VERSION}" \
-f target_commitish="$(git branch --show-current)" \
--jq '.body'
Or generate from commit log if API unavailable.
6.3 Create Release
gh release create "v${VERSION}" \
--title "v${VERSION}" \
--notes "${RELEASE_NOTES}" \
--latest
For pre-releases:
gh release create "v${VERSION}" --prerelease
Flags Reference
| Flag | Effect |
|---|---|
--dry-run |
Show what would happen, don't execute |
--skip-tests |
Skip test suite execution |
--skip-build |
Skip build step |
--skip-changelog |
Don't update CHANGELOG.md |
--skip-push |
Create commit/tag locally, don't push |
--skip-gh |
Skip GitHub release creation |
--yes, -y |
Skip all confirmations |
--prerelease |
Mark as pre-release (beta/rc) |
Safety Mechanisms
- Dirty tree protection - Won't release with uncommitted changes
- Branch protection - Warns on non-release branches
- Test gate - Fails if tests don't pass
- Build verification - Fails if build breaks
- Confirmation prompts - Asks before destructive operations
- Dry-run mode - Preview entire workflow safely
Examples
Basic Patch Release
User: /release patch
Claude:
1. Detected Go project with VERSION file (current: 2.31.0)
2. New version: 2.31.1
3. Running tests... ✓
4. Updating VERSION file... ✓
5. Building... ✓
6. Creating commit and tag... ✓
7. Push to origin? [Y/n]
Minor Release with Changelog
User: /release minor
Claude:
1. Current version: 1.5.2 → New: 1.6.0
2. Found 12 commits since v1.5.2
3. Generated CHANGELOG.md entry with 3 features, 2 fixes
4. [Shows preview]
5. Proceed? [Y/n]
Dry Run
User: /release major --dry-run
Claude:
[DRY RUN] Would perform:
- Bump version: 2.31.0 → 3.0.0
- Update: VERSION, CLAUDE.md
- Run: make build
- Commit: "chore(release): v3.0.0"
- Tag: v3.0.0
- Push to origin/main
- Create GitHub release
No changes made.
Error Recovery
| Error | Recovery |
|---|---|
| Tests failed | Fix tests, re-run /release |
| Build failed | Fix build, re-run /release |
| Push rejected | git pull --rebase, then git push |
| Tag exists | Delete with git tag -d vX.Y.Z, re-run |
| GH release failed | Run gh release create manually |
If release partially completed:
# Undo commit (if not pushed)
git reset --soft HEAD~1
# Delete tag (if created)
git tag -d vX.Y.Z
# Start fresh
/release
Project-Specific Notes
Go Projects
- Version lives in git tags, not files
- If VERSION file exists, update it too
- Build:
go build ./cmd/...ormake build
Node.js Projects
- Use
npm versionfor atomic version + tag - Or update package.json + package-lock.json manually
- Build:
npm run buildif script exists
Rust Projects
- Update Cargo.toml version field
- Also update Cargo.lock:
cargo update - Build:
cargo build --release
Python Projects
- Update pyproject.toml or setup.py
- Build:
python -m build - Consider PyPI publish:
twine upload
Monorepos
- May need to update multiple package.json/Cargo.toml
- Consider workspace version commands
- Tag format:
package-name@X.Y.ZorvX.Y.Z