Skill v1.0.0
currentAutomated scan100/100version: "1.0.0" name: changelog-auto description: Auto-generate changelogs from commit history disable-model-invocation: true
Automatic Changelog Generator
I'll generate professional changelogs from your git commit history, organized by version and category.
Arguments: $ARGUMENTS - version range, tag names, or changelog format
Changelog Philosophy
- User-Focused: Written for end users, not developers
- Categorized: Features, fixes, breaking changes
- Semantic Versioning: Follow semver principles
- Keep a Changelog: Follow keepachangelog.com format
Phase 1: Commit Analysis
First, let me analyze your git history:
#!/bin/bash# Analyze git commit history for changelog generationanalyze_git_history() {echo "=== Git History Analysis ==="echo ""# 1. Check if we're in a git repoif ! git rev-parse --git-dir > /dev/null 2>&1; thenecho "❌ Not a git repository"exit 1fi# 2. Get latest tagLATEST_TAG=$(git describe --tags --abbrev=0 2>/dev/null)if [ -z "$LATEST_TAG" ]; thenecho "No tags found. Analyzing all commits..."COMMIT_RANGE="HEAD"elseecho "Latest tag: $LATEST_TAG"COMMIT_RANGE="$LATEST_TAG..HEAD"fi# 3. Count commits by typeecho ""echo "Commits since $LATEST_TAG:"git log $COMMIT_RANGE --oneline | wc -lecho ""echo "Breakdown by type:"echo " Features: $(git log $COMMIT_RANGE --oneline | grep -c '^[a-f0-9]* feat' || echo 0)"echo " Fixes: $(git log $COMMIT_RANGE --oneline | grep -c '^[a-f0-9]* fix' || echo 0)"echo " Docs: $(git log $COMMIT_RANGE --oneline | grep -c '^[a-f0-9]* docs' || echo 0)"echo " Refactor: $(git log $COMMIT_RANGE --oneline | grep -c '^[a-f0-9]* refactor' || echo 0)"echo " Chore: $(git log $COMMIT_RANGE --oneline | grep -c '^[a-f0-9]* chore' || echo 0)"# 4. Check for breaking changesBREAKING_COUNT=$(git log $COMMIT_RANGE --oneline | grep -c '!' || echo 0)if [ $BREAKING_COUNT -gt 0 ]; thenecho ""echo "⚠️ WARNING: $BREAKING_COUNT breaking changes detected"fi}analyze_git_history
Phase 2: Version Detection
I'll determine the next version number:
#!/bin/bash# Determine next version using semantic versioningdetermine_next_version() {local commit_range="$1"# Get current versionCURRENT_VERSION=$(git describe --tags --abbrev=0 2>/dev/null || echo "0.0.0")echo "Current version: $CURRENT_VERSION"# Parse versionIFS='.' read -r MAJOR MINOR PATCH <<< "${CURRENT_VERSION#v}"# Check for breaking changesHAS_BREAKING=$(git log $commit_range --oneline | grep -E '(^[a-f0-9]* \w+!:|BREAKING CHANGE:)' || echo "")# Check for featuresHAS_FEATURES=$(git log $commit_range --oneline | grep '^[a-f0-9]* feat' || echo "")# Check for fixesHAS_FIXES=$(git log $commit_range --oneline | grep '^[a-f0-9]* fix' || echo "")# Determine version bumpif [ ! -z "$HAS_BREAKING" ]; thenNEXT_VERSION="$((MAJOR + 1)).0.0"BUMP_TYPE="MAJOR (breaking changes)"elif [ ! -z "$HAS_FEATURES" ]; thenNEXT_VERSION="$MAJOR.$((MINOR + 1)).0"BUMP_TYPE="MINOR (new features)"elif [ ! -z "$HAS_FIXES" ]; thenNEXT_VERSION="$MAJOR.$MINOR.$((PATCH + 1))"BUMP_TYPE="PATCH (bug fixes)"elseNEXT_VERSION="$CURRENT_VERSION"BUMP_TYPE="NONE (no releasable changes)"fiecho ""echo "Next version: v$NEXT_VERSION"echo "Bump type: $BUMP_TYPE"echo ""echo "$NEXT_VERSION"}NEXT_VERSION=$(determine_next_version "$COMMIT_RANGE")
Phase 3: Changelog Generation
I'll generate the changelog in Keep a Changelog format:
#!/bin/bash# Generate changelog from git commitsgenerate_changelog() {local version="$1"local commit_range="$2"local output_file="${3:-CHANGELOG.md}"echo "Generating changelog for version $version..."# Start changelogcat > "$output_file.new" << EOF# ChangelogAll notable changes to this project will be documented in this file.The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).## [${version}] - $(date +%Y-%m-%d)EOF# Extract breaking changesBREAKING=$(git log $commit_range --grep='BREAKING CHANGE' --format='- %s' || echo "")if [ ! -z "$BREAKING" ]; thenecho "### ⚠️ BREAKING CHANGES" >> "$output_file.new"echo "" >> "$output_file.new"git log $commit_range --grep='BREAKING CHANGE' --format='- %s%n%b' | \sed 's/^BREAKING CHANGE: //' | \sed '/^$/d' >> "$output_file.new"echo "" >> "$output_file.new"fi# Extract featuresFEATURES=$(git log $commit_range --oneline | grep '^[a-f0-9]* feat' || echo "")if [ ! -z "$FEATURES" ]; thenecho "### Added" >> "$output_file.new"echo "" >> "$output_file.new"git log $commit_range --oneline --format='- %s' | \grep '^- feat' | \sed 's/^- feat[(:]*/- /' | \sed 's/^- feat /- /' | \sed 's/:.*//' >> "$output_file.new"echo "" >> "$output_file.new"fi# Extract fixesFIXES=$(git log $commit_range --oneline | grep '^[a-f0-9]* fix' || echo "")if [ ! -z "$FIXES" ]; thenecho "### Fixed" >> "$output_file.new"echo "" >> "$output_file.new"git log $commit_range --oneline --format='- %s' | \grep '^- fix' | \sed 's/^- fix[(:]*/- /' | \sed 's/^- fix /- /' | \sed 's/:.*//' >> "$output_file.new"echo "" >> "$output_file.new"fi# Extract performance improvementsPERF=$(git log $commit_range --oneline | grep '^[a-f0-9]* perf' || echo "")if [ ! -z "$PERF" ]; thenecho "### Performance" >> "$output_file.new"echo "" >> "$output_file.new"git log $commit_range --oneline --format='- %s' | \grep '^- perf' | \sed 's/^- perf[(:]*/- /' | \sed 's/^- perf /- /' >> "$output_file.new"echo "" >> "$output_file.new"fi# Extract refactoringREFACTOR=$(git log $commit_range --oneline | grep '^[a-f0-9]* refactor' || echo "")if [ ! -z "$REFACTOR" ]; thenecho "### Changed" >> "$output_file.new"echo "" >> "$output_file.new"git log $commit_range --oneline --format='- %s' | \grep '^- refactor' | \sed 's/^- refactor[(:]*/- /' | \sed 's/^- refactor /- /' >> "$output_file.new"echo "" >> "$output_file.new"fi# Extract deprecationsDEPRECATED=$(git log $commit_range --grep='deprecate' -i --format='- %s' || echo "")if [ ! -z "$DEPRECATED" ]; thenecho "### Deprecated" >> "$output_file.new"echo "" >> "$output_file.new"echo "$DEPRECATED" >> "$output_file.new"echo "" >> "$output_file.new"fi# Extract removalsREMOVED=$(git log $commit_range --oneline | grep -E '^[a-f0-9]* (remove|delete)' -i || echo "")if [ ! -z "$REMOVED" ]; thenecho "### Removed" >> "$output_file.new"echo "" >> "$output_file.new"git log $commit_range --oneline --format='- %s' | \grep -E '^- (remove|delete)' -i | \sed 's/^- remove[(:]*/- /' | \sed 's/^- delete[(:]*/- /' >> "$output_file.new"echo "" >> "$output_file.new"fi# Add comparison linkif [ ! -z "$LATEST_TAG" ]; thenREPO_URL=$(git remote get-url origin | sed 's/\.git$//')echo "[${version}]: ${REPO_URL}/compare/${LATEST_TAG}...v${version}" >> "$output_file.new"fi# Prepend to existing changelog if it existsif [ -f "$output_file" ]; thenecho "" >> "$output_file.new"tail -n +2 "$output_file" >> "$output_file.new"fimv "$output_file.new" "$output_file"echo "✓ Changelog generated: $output_file"}generate_changelog "$NEXT_VERSION" "$COMMIT_RANGE" "CHANGELOG.md"
Phase 4: Enhanced Changelog Formats
I can generate different changelog formats:
Standard Format (Keep a Changelog)
# Changelog## [2.1.0] - 2026-01-25### Added-User profile customization-Dark mode support-Export data to CSV### Fixed-Login timeout issue-Memory leak in image processing-Incorrect timezone handling### Changed-Improved search performance by 40%-Updated UI components to new design system### Deprecated-Old API endpoints (v1) - use v2 instead### Removed-Legacy payment processor integration### Security-Fixed XSS vulnerability in user comments-Updated dependencies with security patches[2.1.0]: https://github.com/user/repo/compare/v2.0.0...v2.1.0
GitHub Releases Format
## What's Changed### 🚀 Features*Add user profile customization by @username in #123*Implement dark mode support by @username in #124*Add CSV export functionality by @username in #125### 🐛 Bug Fixes*Fix login timeout issue by @username in #126*Resolve memory leak in image processing by @username in #127*Correct timezone handling by @username in #128### ⚡ Performance*Improve search performance by 40% by @username in #129### 🔒 Security*Fix XSS vulnerability in comments by @username in #130**Full Changelog**: https://github.com/user/repo/compare/v2.0.0...v2.1.0
Detailed Format (with descriptions)
#!/bin/bash# Generate detailed changelog with commit bodiesgenerate_detailed_changelog() {local version="$1"local commit_range="$2"cat > CHANGELOG.md.new << EOF# Changelog## [${version}] - $(date +%Y-%m-%d)### AddedEOF# Features with descriptionsgit log $commit_range --format='%h|||%s|||%b' | grep '^[a-f0-9]*|||feat' | while IFS='|||' read -r hash subject body; doecho "#### $(echo $subject | sed 's/^feat[(:]*//' | sed 's/^feat //')" >> CHANGELOG.md.newif [ ! -z "$body" ]; thenecho "$body" | sed 's/^/ /' >> CHANGELOG.md.newfiecho " ([$(echo $hash | cut -c1-7)](https://github.com/user/repo/commit/$hash))" >> CHANGELOG.md.newecho "" >> CHANGELOG.md.newdone# Fixes with descriptionsecho "### Fixed" >> CHANGELOG.md.newecho "" >> CHANGELOG.md.newgit log $commit_range --format='%h|||%s|||%b' | grep '^[a-f0-9]*|||fix' | while IFS='|||' read -r hash subject body; doecho "#### $(echo $subject | sed 's/^fix[(:]*//' | sed 's/^fix //')" >> CHANGELOG.md.newif [ ! -z "$body" ]; thenecho "$body" | sed 's/^/ /' >> CHANGELOG.md.newfiecho " ([$(echo $hash | cut -c1-7)](https://github.com/user/repo/commit/$hash))" >> CHANGELOG.md.newecho "" >> CHANGELOG.md.newdone}
Phase 5: Changelog Validation
I'll validate the generated changelog:
#!/bin/bash# Validate changelog qualityvalidate_changelog() {local changelog="$1"echo "=== Changelog Validation ==="echo ""# Check for required sectionsif ! grep -q "## \[" "$changelog"; thenecho "⚠️ WARNING: No version headers found"elseecho "✓ Version headers present"fi# Check for datesif ! grep -q "[0-9]\{4\}-[0-9]\{2\}-[0-9]\{2\}" "$changelog"; thenecho "⚠️ WARNING: No dates found"elseecho "✓ Dates present"fi# Check for categoriesCATEGORIES=("Added" "Changed" "Deprecated" "Removed" "Fixed" "Security")for category in "${CATEGORIES[@]}"; doif grep -q "### $category" "$changelog"; thencount=$(grep -c "^- " "$changelog" | grep -A 20 "### $category" || echo 0)echo "✓ $category: found"fidone# Check for empty sectionsif grep -q "### .*\n\n###" "$changelog"; thenecho "⚠️ WARNING: Empty sections detected"fi# Check for comparison linksif grep -q "\[.*\]: http" "$changelog"; thenecho "✓ Comparison links present"elseecho "⚠️ INFO: No comparison links (add repository URLs)"fiecho ""echo "Validation complete"}validate_changelog "CHANGELOG.md"
Phase 6: Integration with Release Process
I'll integrate changelog generation with releases:
#!/bin/bash# Complete release workflow with changelogrelease_workflow() {local version="$1"echo "=== Release Workflow: v$version ==="echo ""# 1. Generate changelogecho "Step 1: Generating changelog..."/changelog-auto "$version"# 2. Stage changelogecho "Step 2: Staging changelog..."git add CHANGELOG.md# 3. Update version filesecho "Step 3: Updating version files..."if [ -f "package.json" ]; thennpm version $version --no-git-tag-versiongit add package.json package-lock.jsonelif [ -f "setup.py" ]; thensed -i "s/version=['\"][^'\"]*['\"]/version='$version'/" setup.pygit add setup.pyfi# 4. Commitecho "Step 4: Creating release commit..."git commit -m "chore(release): $version$(cat CHANGELOG.md | sed -n "/## \[$version\]/,/## \[/p" | head -n -1)"# 5. Create tagecho "Step 5: Creating git tag..."git tag -a "v$version" -m "Release v$version$(cat CHANGELOG.md | sed -n "/## \[$version\]/,/## \[/p" | head -n -1)"# 6. Pushecho "Step 6: Ready to push..."echo ""echo "Review the changes and run:"echo " git push origin main"echo " git push origin v$version"}release_workflow "$NEXT_VERSION"
Practical Examples
Auto-Generate:
/changelog-auto # Auto-detect version and generate/changelog-auto 2.1.0 # Generate for specific version/changelog-auto v1.0.0..HEAD # Generate for commit range
Different Formats:
/changelog-auto --format=github # GitHub releases format/changelog-auto --format=detailed # With commit descriptions/changelog-auto --format=simple # Simple bullet list
Release Integration:
/changelog-auto --release # Full release workflow/changelog-auto --dry-run # Preview without writing
Conventional Commits Reference
I recognize these commit types:
feat:→ Added section (new features)fix:→ Fixed section (bug fixes)docs:→ Documentation sectionstyle:→ Changed section (formatting)refactor:→ Changed section (code restructure)perf:→ Performance section (optimizations)test:→ Usually omitted from user changelogchore:→ Usually omitted from user changelog!orBREAKING CHANGE:→ Breaking Changes section
Best Practices
Good Changelog Entries:
- User-focused ("You can now..." instead of "Added method...")
- Clear and concise
- Links to issues/PRs
- Migration guides for breaking changes
- Security fixes prominently displayed
Changelog Anti-Patterns:
- Too technical ("Refactored BaseService class")
- Too vague ("Various improvements")
- Missing context
- Developer-focused language
What I'll Actually Do
- Analyze history - Parse git commits efficiently
- Detect version - Semantic versioning based on changes
- Categorize changes - Organize by type (features, fixes, etc.)
- Generate changelog - Keep a Changelog format
- Validate quality - Check for completeness
- Integrate release - Optional full release workflow
Important: I will NEVER:
- Modify commit history
- Create changelogs without git validation
- Skip breaking change detection
- Add AI attribution
The changelog will be professional, user-focused, and ready for immediate release.
Credits: Based on Keep a Changelog format and Conventional Commits specification.
Token Optimization
Expected range: 400–1,000 tokens (initial), 50 tokens (no new commits)
Caching: Caches last-version info in .claude/cache/changelog/last-version.json for 7 days. Invalidated on new tags.
Early exit: Returns immediately if no new commits exist since the last changelog entry.
Patterns used: Grep-before-Read, early exit, git diff scope default, caching