CClaude Code Catalog
All Hooks

Auto Changelog Appender

Post-ToolAdvancedHook Type: post-tool-use

Auto Changelog Appender triggers after git commit commands and automatically maintains your CHANGELOG.md. It extracts the commit message, classifies the change type (feat, fix, refactor, docs, etc.) from conventional commit prefixes, and appends a formatted entry under the current version's Unreleased section. It groups entries by type (Added, Fixed, Changed, etc.) following the Keep a Changelog convention. If no CHANGELOG.md exists, it creates one with proper formatting. This eliminates the tedious manual work of maintaining changelogs while ensuring every commit is documented.

changelogdocumentationgitconventional-commitsautomation

Hook Code

#!/bin/bash # Auto Changelog Appender Hook # Maintains CHANGELOG.md from commit messages # Only trigger on Bash tool with git commit if [[ "$TOOL_NAME" != "Bash" ]] || ! echo "$TOOL_INPUT" | grep -q "git commit"; then exit 0 fi # Verify commit actually happened LAST_COMMIT=$(git log -1 --format="%H %s" 2>/dev/null) if [ -z "$LAST_COMMIT" ]; then exit 0 fi COMMIT_MSG=$(echo "$LAST_COMMIT" | cut -d' ' -f2-) COMMIT_HASH=$(echo "$LAST_COMMIT" | cut -d' ' -f1 | cut -c1-7) TODAY=$(date +%Y-%m-%d) CHANGELOG="CHANGELOG.md" # Classify commit type classify_commit() { local msg="$1" case "$msg" in feat:*|feat(*) echo "Added" ;; fix:*|fix(*) echo "Fixed" ;; docs:*|docs(*) echo "Documentation" ;; refactor:*|refactor(*) echo "Changed" ;; perf:*|perf(*) echo "Performance" ;; test:*|test(*) echo "Testing" ;; chore:*|chore(*) echo "Maintenance" ;; BREAKING*|!:*) echo "Breaking Changes" ;; *) echo "Changed" ;; esac } # Strip conventional commit prefix clean_message() { echo "$1" | sed -E 's/^(feat|fix|docs|refactor|perf|test|chore)(\([^)]*\))?!?:\s*//' } CATEGORY=$(classify_commit "$COMMIT_MSG") CLEAN_MSG=$(clean_message "$COMMIT_MSG") # Create CHANGELOG if it doesn't exist if [ ! -f "$CHANGELOG" ]; then cat > "$CHANGELOG" << 'TMPL' # Changelog All notable changes to this project will be documented in this file. ## [Unreleased] TMPL fi # Check if Unreleased section exists if ! grep -q "## \[Unreleased\]" "$CHANGELOG"; then sed -i.bak '3a\n## [Unreleased]\n' "$CHANGELOG" rm -f "$CHANGELOG.bak" fi # Check if category subsection exists under Unreleased UNRELEASED_LINE=$(grep -n "## \[Unreleased\]" "$CHANGELOG" | head -1 | cut -d: -f1) NEXT_VERSION_LINE=$(awk "NR>$UNRELEASED_LINE && /^## \[/{print NR; exit}" "$CHANGELOG") NEXT_VERSION_LINE=${NEXT_VERSION_LINE:-$(wc -l < "$CHANGELOG")} ENTRY="- $CLEAN_MSG (\`$COMMIT_HASH\`)" # Insert entry under the appropriate category if grep -q "### $CATEGORY" "$CHANGELOG"; then CATEGORY_LINE=$(grep -n "### $CATEGORY" "$CHANGELOG" | head -1 | cut -d: -f1) sed -i.bak "${CATEGORY_LINE}a\ $ENTRY" "$CHANGELOG" else sed -i.bak "/## \[Unreleased\]/a\ \\n### $CATEGORY\ $ENTRY" "$CHANGELOG" fi rm -f "$CHANGELOG.bak" echo "Changelog updated: [$CATEGORY] $CLEAN_MSG" exit 0

Add this hook to your Claude Code settings or .claude/settings.json to activate.

Terminal Preview

Auto Changelog Appender

About Auto Changelog Appender

Claude Code hooks let you run custom shell commands automatically in response to specific events during Claude's operation. Auto Changelog Appender is a Post-Tool hook at the Advanced level that automates tasks at key moments in your development workflow, reducing manual steps and enforcing consistency across your team.

Related Hooks