Skill v1.0.1
currentAutomated scan100/100+3 new
version: "1.0.1" name: release description: 'Automated release flow — bump version, changelog, tag, push, GitHub release. Use when user says "release", "ship", "bump version", "tag", or "publish".' argument-hint: "<patch|minor|major> [--dry-run | --alpha | --no-push]" zombie: true archived_reason: 'moved to zombie tier via #327 (usage audit, 3,685 sessions mined)' archived_date: 2026-05-13 metadata: internal: true
/release — Automated Release Flow
Ship sharp. Ship clean. Ship now.
Automates the full release cycle: version bump, changelog generation, git tag, push, and GitHub release creation. No more manual copy-paste release rituals.
Usage
/release patch # Bump patch (1.2.3 → 1.2.4), tag, push, release/release minor # Bump minor (1.2.3 → 1.3.0)/release major # Bump major (1.2.3 → 2.0.0)/release patch --alpha # Pre-release (1.2.3 → 1.2.4-alpha.1)/release patch --dry-run # Show what would happen, don't do it/release patch --no-push # Tag locally, skip push + GH release/release status # Show current version + unreleased changes
Step 0: Preflight
Checks
date "+🕐 %H:%M %Z (%A %d %B %Y)" && BRANCH=$(git branch --show-current)if [ "$BRANCH" != "main" ]; thenecho "⚠️ On branch '$BRANCH' — releases should be from main"echo "Continue anyway? [y/N]"# WAIT for user confirmationfi# Must be clean working treeif [ -n "$(git status --porcelain | grep -v '^?? ψ/')" ]; thenecho "❌ Uncommitted changes (excluding ψ/ vault files):"git status --short | grep -v '^?? ψ/'echo ""echo "Commit or stash first."exit 1fi# Must be up to date with remotegit fetch origin main --quiet 2>/dev/nullLOCAL=$(git rev-parse HEAD)REMOTE=$(git rev-parse origin/main 2>/dev/null)if [ "$LOCAL" != "$REMOTE" ]; thenecho "⚠️ Local is not in sync with origin/main"echo " Local: $LOCAL"echo " Remote: $REMOTE"echo "Pull first? [Y/n]"fi
Step 1: Detect Current Version
# Try package.json firstif [ -f package.json ]; thenCURRENT=$(python3 -c "import json; print(json.load(open('package.json'))['version'])")VERSION_FILE="package.json"# Try Cargo.tomlelif [ -f Cargo.toml ]; thenCURRENT=$(grep '^version' Cargo.toml | head -1 | sed 's/.*"\(.*\)".*/\1/')VERSION_FILE="Cargo.toml"# Try VERSION fileelif [ -f VERSION ]; thenCURRENT=$(cat VERSION)VERSION_FILE="VERSION"elseecho "❌ Can't find version. Supported: package.json, Cargo.toml, VERSION"exit 1fiecho "📦 Current version: v$CURRENT ($VERSION_FILE)"
Step 2: Calculate Next Version
Parse current version and bump:
IFS='.' read -r MAJOR MINOR PATCH <<< "${CURRENT%-*}"case "$BUMP_TYPE" inpatch) PATCH=$((PATCH + 1)) ;;minor) MINOR=$((MINOR + 1)); PATCH=0 ;;major) MAJOR=$((MAJOR + 1)); MINOR=0; PATCH=0 ;;esacNEXT="$MAJOR.$MINOR.$PATCH"# Alpha suffixif [ "$ALPHA" = true ]; then# Check existing alpha tagsALPHA_NUM=$(git tag -l "v${NEXT}-alpha.*" | wc -l)ALPHA_NUM=$((ALPHA_NUM + 1))NEXT="${NEXT}-alpha.${ALPHA_NUM}"fiecho "🚀 Next version: v$NEXT"
Step 3: Generate Changelog
Collect commits since last tag:
LAST_TAG=$(git describe --tags --abbrev=0 2>/dev/null || echo "")if [ -n "$LAST_TAG" ]; thenecho "📝 Changes since $LAST_TAG:"echo ""git log "$LAST_TAG"..HEAD --oneline --no-merges | while read hash msg; do# Categorize by conventional commit prefixcase "$msg" infeat*) echo " ✨ $msg" ;;fix*) echo " 🐛 $msg" ;;docs*) echo " 📚 $msg" ;;soul*) echo " 🧬 $msg" ;;chore*) echo " 🔧 $msg" ;;*) echo " · $msg" ;;esacdoneelseecho "📝 First release — all commits included"git log --oneline -20 --no-mergesfi
Step 4: Confirm
ALWAYS wait for user confirmation before proceeding.
🚀 Release PlanVersion: v$CURRENT → v$NEXTBranch: $BRANCHChanges: N commits since $LAST_TAGActions:1. Update version in $VERSION_FILE2. Create git tag v$NEXT3. Push to origin (main + tag)4. Create GitHub release with changelogProceed? [Y/n]
If --dry-run, show the plan and stop here.
Step 5: Execute Release
Bump Version
# package.jsonif [ "$VERSION_FILE" = "package.json" ]; thenpython3 -c "import jsondata = json.load(open('package.json'))data['version'] = '$NEXT'json.dump(data, open('package.json', 'w'), indent=2)print('✅ package.json updated')"fi# Cargo.tomlif [ "$VERSION_FILE" = "Cargo.toml" ]; thensed -i "0,/^version = .*/s//version = \"$NEXT\"/" Cargo.tomlecho "✅ Cargo.toml updated"fi# VERSION fileif [ "$VERSION_FILE" = "VERSION" ]; thenecho "$NEXT" > VERSIONecho "✅ VERSION updated"fi
Commit & Tag
git add "$VERSION_FILE"git commit -m "release: v$NEXTCo-Authored-By: Oracle <noreply@soulbrews.studio>"git tag -a "v$NEXT" -m "v$NEXT$(git log "$LAST_TAG"..HEAD --oneline --no-merges 2>/dev/null)"
Push (unless --no-push)
git push origin main --follow-tags
GitHub Release
CHANGELOG=$(git log "$LAST_TAG"..HEAD~1 --oneline --no-merges | while read hash msg; doecho "- $msg"done)gh release create "v$NEXT" \--title "v$NEXT" \--notes "$CHANGELOG" \--latest
Step 6: Summary
🎉 Released v$NEXT📦 Version: v$NEXT🏷️ Tag: v$NEXT📡 Pushed: origin/main🔗 Release: https://github.com/OWNER/REPO/releases/tag/v$NEXT**From**: [Oracle Name]**Rule 6**: Oracle Never Pretends to Be Human
/release status
Show current state without releasing:
📦 Release StatusCurrent: v$CURRENTBranch: $BRANCHLast tag: $LAST_TAG (N commits ago)Unreleased changes:✨ feat: ...🐛 fix: ...💡 /release patch — ship these changes
Rules
- Confirm before release — never auto-release without explicit user approval
- Clean tree required — no uncommitted changes (ψ/ vault files excluded)
- Main branch preferred — warn but allow release from other branches
- Tag format — always
vX.Y.ZorvX.Y.Z-alpha.N - Rule 6 signed — release notes attributed to Oracle
- No force push — if tag exists, fail and ask user
- Conventional commits — categorize changelog by prefix
ARGUMENTS: $ARGUMENTS