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...
Create consistent, safe software releases across any project type.
/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
┌─────────────────────────────────────────────────────────────────┐
│ 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 │
│ │
└─────────────────────────────────────────────────────────────────┘
git status --porcelain
STOP if uncommitted changes exist. Ask user to commit or stash first.
Exception: If --dry-run flag, continue but warn.
git branch --show-current
Allowed branches:
main, master - production releasesrelease/* - release branchesdevelop - pre-releases only (append -beta.N or -rc.N)If on feature branch:
git checkout main && git merge <feature-branch> --ff-onlyRun 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.
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"
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| 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:
2.0.0-beta.1 and bump is patch → 2.0.0-beta.2--graduateUpdate 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.
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.
Search for version badges or references:

Update to new version if found.
If CLAUDE.md exists and contains version reference, update it:
**Current**: v2.31.0 - Description here
Update to:
**Current**: vX.Y.Z - Description here
| 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 |
Run the detected build command. STOP if build fails.
# Example for Make-based projects
make build
Check that expected artifacts exist:
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 ./...
git add -A
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)
"
git tag -a "v${VERSION}" -m "Release v${VERSION}"
Tag format: Always prefix with v (e.g., v2.32.0)
git push origin $(git branch --show-current)
git push origin "v${VERSION}"
Ask for confirmation before push unless --yes flag provided.
gh --version
Skip this phase if gh not installed or not authenticated.
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.
gh release create "v${VERSION}" \
--title "v${VERSION}" \
--notes "${RELEASE_NOTES}" \
--latest
For pre-releases:
gh release create "v${VERSION}" --prerelease
| 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) |
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]
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]
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 |
|---|---|
| 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
go build ./cmd/... or make buildnpm version for atomic version + tagnpm run build if script existscargo updatecargo build --releasepython -m buildtwine uploadpackage-name@X.Y.Z or vX.Y.Z