Skip to main content
hooksSource-backedReview first Safety Privacy

Git Auto Commit On Stop - Hooks

Automatically commits all changes with a summary when Claude Code session ends.

by JSONbored·added 2025-09-19·
HarnessClaude Code
Trigger:Stop
Review first review before installing

Open the source and read safety notes before installing.

Citation facts

Source-backed facts for citing this resource, derived directly from the registry — also available as plain text for AI assistants.

Safety notes
Runs automatically at session end and stages all unignored repository changes with git add -A., Creates a local commit when changes are present unless SKIP_AUTO_COMMIT=true is set., Only warns on sensitive-looking filenames and does not block the commit by default.
Privacy notes
Reads git status, branch name, staged diff statistics, and changed file names to build the commit message., Can commit newly created or modified local files, including private work, when they are not excluded by .gitignore., Commit metadata uses the locally configured git user name and email.
Author
JSONbored
Claim status
unclaimed
Last verified
2025-09-19

Decision playbook

Review trust signals before you adopt

Signals are present but mixed. Use the checklist below to confirm the source and operational safety for your environment.

Compare context
Selected

0

Current score

78

Baseline

Delta

No baseline selected

No major trust-signal divergence detected in the current selection.

Source and provenance checks

Complete

Confirm ownership and provenance before trusting install instructions.

  • Source link availableRequired

    Open the canonical repository and verify ownership.

    Done
  • Source provenance statusRequired

    Marked as source-backed.

    Done
  • Metadata reviewed

    Registry metadata indicates a reviewed listing.

    Done

Safety and privacy checks

Complete

Validate risk disclosures before installation or API wiring.

  • Safety notes presentRequired

    Review the listed safety guidance before running commands.

    Done
  • Privacy notes presentRequired

    Review data handling notes before connecting accounts or secrets.

    Done
  • Trust level risk gateRequired

    Trust level does not block evaluation.

    Done

Package and install checks

Needs review

Check package metadata and artifact integrity signals.

  • Install payload available

    Install or copy payload is available for review.

    Done
  • Package verification flag

    No package verification flag provided.

    Pending
  • Checksum metadata

    No checksum provided for downloaded artifact.

    Pending

Compare-driven decision checks

Needs review

Use compare context to validate trade-offs before adoption.

  • Compare tray has multiple entries

    Add at least one more entry to compare trust differences.

    Pending
  • Baseline comparison available

    No baseline peer selected yet.

    Pending
  • Diverging trust signals identified

    No major trust-signal divergence found.

    Pending

Setup at a glance

CLI install

Copy-ready — paste the snippet to get started.

Install command

Provided

Config snippet

Provided

Copy snippet

Provided

Prerequisites

None

Platforms

1 listed

Difficulty

0/100

Adoption plan

Balanced adoption plan

Current risk score 16/100. Use staged verification before broader rollout.

Risk 16

Pre-adoption checks

Validate source and review signals before any execution.

  • Confirm source provenanceRequired

    Source URL/provenance metadata is present.

    Done
  • Confirm metadata review state

    Listing has review metadata.

    Done
  • Verify install payload

    Install/config payload exists and can be inspected.

    Done

Security checks

Confirm safety, privacy, and package integrity signals.

  • Review safety notesRequired

    Safety notes are present.

    Done
  • Review privacy notesRequired

    Privacy notes are present.

    Done
  • Verify package integrity metadata

    No package verification/checksum metadata.

    Pending

Rollout

Adopt in controlled steps based on the selected plan.

  • Run in isolated sandbox firstRequired

    Use a constrained sandbox and observe behavior across multiple tasks.

    Pending
  • Roll out graduallyRequired

    Roll out to a small cohort before wider usage.

    Pending
  • Set monitoring and fallback

    Define rollback path and monitor errors after adoption.

    Pending

Evidence readiness

Evidence readiness matrix · balanced

Required evidence gates are covered (5/6 signals complete).

Risk 15

Source provenance

Present

Source repository/provenance is listed.

Required in this preset

Metadata review

Present

Review metadata is present.

Required in this preset

Safety notes

Present

Safety notes are present.

Required in this preset

Privacy notes

Present

Privacy notes are present.

Optional in this preset

Package integrity

Missing

Package integrity metadata is missing.

Optional in this preset

Install payload

Present

Install payload is available.

Required in this preset

Required evidence gates are covered for this preset.

Decision timeline

Decision timeline · balanced

5/6 steps complete with no blocking gaps for this preset.

Risk 14

triage

Confirm source provenanceRequired

Source/provenance metadata is available.

Done

triage

Check metadata review statusRequired

Review metadata is available.

Done

verify

Review safety notesRequired

Safety notes are available.

Done

verify

Review privacy notes

Privacy notes are available.

Done

verify

Validate package integrity metadata

Package integrity metadata is missing.

Pending

rollout

Verify install payload and commandsRequired

Install payload is available.

Done

No required blockers for this timeline preset.

Safety & privacy surface

Safety & privacy surface

3 safety and 3 privacy notes across 3 risk areas. Review closely: credentials & tokens.

3 areas
  • SafetyCredentials & tokensRuns automatically at session end and stages all unignored repository changes with git add -A.
  • SafetyGeneralCreates a local commit when changes are present unless SKIP_AUTO_COMMIT=true is set.
  • SafetyLocal filesOnly warns on sensitive-looking filenames and does not block the commit by default.
  • PrivacyLocal filesReads git status, branch name, staged diff statistics, and changed file names to build the commit message.
  • PrivacyLocal filesCan commit newly created or modified local files, including private work, when they are not excluded by .gitignore.
  • PrivacyGeneralCommit metadata uses the locally configured git user name and email.

Safety notes

  • Runs automatically at session end and stages all unignored repository changes with git add -A.
  • Creates a local commit when changes are present unless SKIP_AUTO_COMMIT=true is set.
  • Only warns on sensitive-looking filenames and does not block the commit by default.

Privacy notes

  • Reads git status, branch name, staged diff statistics, and changed file names to build the commit message.
  • Can commit newly created or modified local files, including private work, when they are not excluded by .gitignore.
  • Commit metadata uses the locally configured git user name and email.

Schema details

Install type
cli
Reading time
1 min
Difficulty score
0
Troubleshooting
Yes
Breaking changes
No
Runtime and command metadata
Trigger
Stop
Script language
bash
Script body
#!/usr/bin/env bash

echo "💾 Checking for changes to auto-commit..." >&2

# Check if we're in a git repository
if ! git rev-parse --git-dir > /dev/null 2>&1; then
  echo "⚠️ Not in a git repository - skipping auto-commit" >&2
  exit 0
fi

# Check if git is configured
if ! git config user.email > /dev/null 2>&1 || ! git config user.name > /dev/null 2>&1; then
  echo "⚠️ Git user not configured - skipping auto-commit" >&2
  echo "💡 Run: git config --global user.email 'your@email.com'" >&2
  echo "💡 Run: git config --global user.name 'Your Name'" >&2
  exit 0
fi

# Get current timestamp
TIMESTAMP=$(date +"%Y-%m-%d %H:%M:%S")
ISO_TIMESTAMP=$(date -u +"%Y-%m-%dT%H:%M:%SZ" 2>/dev/null || date +"%Y-%m-%d %H:%M:%S UTC")

# Get current branch
CURRENT_BRANCH=$(git branch --show-current 2>/dev/null || echo "unknown")

# Check for uncommitted changes
if [ -z "$(git status --porcelain 2>/dev/null)" ]; then
  echo "✨ No changes to commit - repository is clean" >&2
  exit 0
fi

echo "📊 Analyzing changes for auto-commit..." >&2

# Get status information
UNTRACKED_FILES=$(git status --porcelain 2>/dev/null | grep '^??' | wc -l | xargs)
MODIFIED_FILES=$(git status --porcelain 2>/dev/null | grep '^.M' | wc -l | xargs)
ADDED_FILES=$(git status --porcelain 2>/dev/null | grep '^A' | wc -l | xargs)
DELETED_FILES=$(git status --porcelain 2>/dev/null | grep '^.D' | wc -l | xargs)
RENAMED_FILES=$(git status --porcelain 2>/dev/null | grep '^R' | wc -l | xargs)

echo "📋 Change summary:" >&2
echo "   Branch: $CURRENT_BRANCH" >&2
echo "   Untracked: $UNTRACKED_FILES files" >&2
echo "   Modified: $MODIFIED_FILES files" >&2
echo "   Added: $ADDED_FILES files" >&2
echo "   Deleted: $DELETED_FILES files" >&2
echo "   Renamed: $RENAMED_FILES files" >&2

# Check for sensitive files before committing
echo "🔒 Checking for sensitive files..." >&2
SENSITIVE_PATTERNS=(
  "\.env"
  "\.env\.*"
  "*secret*"
  "*password*"
  "*key*"
  "id_rsa"
  "id_ed25519"
  "*.pem"
  "*.p12"
  "*.pfx"
)

SENSITIVE_FOUND=false
for pattern in "${SENSITIVE_PATTERNS[@]}"; do
  if git status --porcelain 2>/dev/null | grep -q "$pattern"; then
    SENSITIVE_FOUND=true
    echo "⚠️ Potentially sensitive file detected: $pattern" >&2
  fi
done

# Check if .gitignore exists and is respected
if [ ! -f ".gitignore" ]; then
  echo "💡 Consider creating a .gitignore file to exclude unwanted files" >&2
fi

# Option to skip auto-commit if environment variable is set
if [ "$SKIP_AUTO_COMMIT" = "true" ]; then
  echo "⏭️ Auto-commit skipped (SKIP_AUTO_COMMIT=true)" >&2
  exit 0
fi

# Warn about sensitive files but don't block (user choice)
if [ "$SENSITIVE_FOUND" = true ]; then
  echo "⚠️ Sensitive files detected - proceeding with caution" >&2
  echo "💡 Set SKIP_AUTO_COMMIT=true to disable auto-commits" >&2
fi

# Add all changes (respecting .gitignore)
echo "📥 Staging changes for commit..." >&2
git add -A

# Double-check that we have staged changes
if [ -z "$(git diff --cached --name-only)" ]; then
  echo "ℹ️ No changes staged after git add - nothing to commit" >&2
  exit 0
fi

# Calculate detailed statistics
echo "📊 Calculating commit statistics..." >&2

FILES_CHANGED=$(git diff --cached --numstat | wc -l | xargs)
INSERTIONS=0
DELETIONS=0

# Calculate insertions and deletions more reliably
if command -v awk &> /dev/null; then
  STATS=$(git diff --cached --numstat | awk '{insertions+=$1; deletions+=$2} END {print insertions " " deletions}')
  read -r INSERTIONS DELETIONS <<< "$STATS"
else
  # Fallback method
  INSERTIONS=$(git diff --cached --stat | grep -oE '[0-9]+ insertion' | grep -oE '[0-9]+' | paste -sd+ | bc 2>/dev/null || echo '0')
  DELETIONS=$(git diff --cached --stat | grep -oE '[0-9]+ deletion' | grep -oE '[0-9]+' | paste -sd+ | bc 2>/dev/null || echo '0')
fi

# Generate commit message
COMMIT_MSG="🤖 Claude Code auto-commit: Session ended"

# Add detailed commit body
COMMIT_BODY=$(cat <<EOF

Session Summary:
- Branch: $CURRENT_BRANCH
- Files changed: $FILES_CHANGED
- Insertions: +$INSERTIONS
- Deletions: -$DELETIONS
- Timestamp: $TIMESTAMP

Changes by type:
- Modified files: $MODIFIED_FILES
- New files: $UNTRACKED_FILES
- Deleted files: $DELETED_FILES
- Renamed files: $RENAMED_FILES

🤖 Generated with Claude Code
EOF
)

# Show what will be committed
echo "📝 Files to be committed:" >&2
git diff --cached --name-status | head -10 | while read status file; do
  case $status in
    A) echo "   ✅ Added: $file" >&2 ;;
    M) echo "   ✏️  Modified: $file" >&2 ;;
    D) echo "   ❌ Deleted: $file" >&2 ;;
    R*) echo "   🔄 Renamed: $file" >&2 ;;
    *) echo "   📄 $status: $file" >&2 ;;
  esac
done

if [ "$FILES_CHANGED" -gt 10 ]; then
  echo "   ... and $((FILES_CHANGED - 10)) more files" >&2
fi

echo "" >&2
echo "💾 Creating auto-commit..." >&2

# Create the commit
if echo "$COMMIT_BODY" | git commit -F -; then
  echo "✅ Auto-commit successful!" >&2
  
  # Show commit info
  COMMIT_HASH=$(git rev-parse --short HEAD)
  echo "📝 Commit: $COMMIT_HASH" >&2
  echo "🌿 Branch: $CURRENT_BRANCH" >&2
  
  # Check if we should push (optional)
  if [ "$AUTO_PUSH" = "true" ]; then
    echo "📤 Auto-pushing to remote..." >&2
    if git push 2>/dev/null; then
      echo "✅ Pushed to remote successfully" >&2
    else
      echo "⚠️ Push failed - commit created locally" >&2
      echo "💡 Run 'git push' manually when ready" >&2
    fi
  else
    echo "💡 Set AUTO_PUSH=true to automatically push commits" >&2
  fi
  
else
  echo "❌ Auto-commit failed" >&2
  echo "💡 You may need to resolve conflicts or check git status" >&2
  exit 1
fi

echo "" >&2
echo "📋 Auto-Commit Summary:" >&2
echo "   ✅ $FILES_CHANGED files committed" >&2
echo "   📈 +$INSERTIONS insertions, -$DELETIONS deletions" >&2
echo "   ⏰ $TIMESTAMP" >&2
echo "" >&2
echo "💡 Git Auto-Commit Tips:" >&2
echo "   • Set SKIP_AUTO_COMMIT=true to disable" >&2
echo "   • Set AUTO_PUSH=true to auto-push commits" >&2
echo "   • Review commits with 'git log --oneline'" >&2
echo "   • Use .gitignore to exclude sensitive files" >&2

exit 0
Full copyable content
{
  "hooks": {
    "stop": {
      "script": "./.claude/hooks/git-auto-commit-on-stop.sh"
    }
  }
}

About this resource

Features

  • Automatic git commit creation when session ends with comprehensive change detection including untracked files, modified files, added files, deleted files, and renamed files with detailed status analysis
  • Detailed commit statistics (files changed, insertions, deletions) with accurate line count calculations using git diff --numstat and awk for reliable statistics across all file types including binary files
  • Smart commit message generation with timestamps including ISO 8601 timestamps, session summaries, branch information, file change breakdowns, and customizable commit message templates with environment variable support
  • Pre-commit validation and safety checks including sensitive file detection (.env, secrets, keys, certificates) with pattern matching, Git configuration validation (user.name, user.email), and repository state verification
  • Branch and repository state verification with current branch detection, Git repository validation, clean repository detection, and branch state checking before commit creation
  • Customizable commit message templates with environment variable overrides (SKIP_AUTO_COMMIT, AUTO_PUSH) and support for custom commit message formats with detailed session summaries and change breakdowns
  • Untracked file handling and gitignore respect with automatic .gitignore validation, untracked file detection, and proper handling of ignored files with recommendations for .gitignore creation when missing
  • Error handling with informative feedback including commit failure recovery, Git configuration error messages, repository state error handling, and push failure recovery with manual push recommendations

Use Cases

  • Automatic version control for development sessions providing seamless Git integration without manual commit creation and comprehensive session tracking with detailed change summaries
  • Backup and history preservation of work progress automatically preserving all development work with timestamped commits and detailed change tracking for progress recovery and session history
  • Collaborative development with session tracking enabling team members to track development sessions with automatic commits and detailed change summaries for collaboration and code review
  • CI/CD integration with automated commits automatically committing changes for CI/CD pipeline integration with detailed commit messages and statistics for build tracking and deployment automation
  • Project milestone and progress documentation providing automatic documentation of development milestones with timestamped commits and detailed change summaries for project progress tracking
  • Development workflow integration seamlessly integrating automatic Git commits into development workflows without manual Git operations or separate version control tools

Installation

  1. Create hooks directory: mkdir -p .claude/hooks
  2. Create hook file: touch .claude/hooks/git-auto-commit-on-stop.sh
  3. Make executable: chmod +x .claude/hooks/git-auto-commit-on-stop.sh
  4. Add configuration from Hook Configuration section above to .claude/settings.json or ~/.claude/settings.json
  5. Alternative: Use the interactive /hooks command in Claude Code

Config paths

  • Local (not committed): .claude/settings.local.json
  • User settings (global): ~/.claude/settings.json
  • Project-wide (committed): .claude/settings.json

Requirements

  • Claude Code CLI installed
  • Project directory initialized
  • Git repository initialized
  • Git configured (user.name and user.email)
  • Bash shell available
  • Standard Unix utilities: awk (for parsing git diff --numstat), grep (for sensitive file detection), and Git write access for commit and push operations

Hook Configuration

{
  "hooks": {
    "stop": {
      "script": "./.claude/hooks/git-auto-commit-on-stop.sh"
    }
  }
}

Hook Script

#!/usr/bin/env bash

echo "💾 Checking for changes to auto-commit..." >&2

# Check if we're in a git repository
if ! git rev-parse --git-dir > /dev/null 2>&1; then
  echo "⚠️ Not in a git repository - skipping auto-commit" >&2
  exit 0
fi

# Check if git is configured
if ! git config user.email > /dev/null 2>&1 || ! git config user.name > /dev/null 2>&1; then
  echo "⚠️ Git user not configured - skipping auto-commit" >&2
  echo "💡 Run: git config --global user.email 'your@email.com'" >&2
  echo "💡 Run: git config --global user.name 'Your Name'" >&2
  exit 0
fi

# Get current timestamp
TIMESTAMP=$(date +"%Y-%m-%d %H:%M:%S")
ISO_TIMESTAMP=$(date -u +"%Y-%m-%dT%H:%M:%SZ" 2>/dev/null || date +"%Y-%m-%d %H:%M:%S UTC")

# Get current branch
CURRENT_BRANCH=$(git branch --show-current 2>/dev/null || echo "unknown")

# Check for uncommitted changes
if [ -z "$(git status --porcelain 2>/dev/null)" ]; then
  echo "✨ No changes to commit - repository is clean" >&2
  exit 0
fi

echo "📊 Analyzing changes for auto-commit..." >&2

# Get status information
UNTRACKED_FILES=$(git status --porcelain 2>/dev/null | grep '^??' | wc -l | xargs)
MODIFIED_FILES=$(git status --porcelain 2>/dev/null | grep '^.M' | wc -l | xargs)
ADDED_FILES=$(git status --porcelain 2>/dev/null | grep '^A' | wc -l | xargs)
DELETED_FILES=$(git status --porcelain 2>/dev/null | grep '^.D' | wc -l | xargs)
RENAMED_FILES=$(git status --porcelain 2>/dev/null | grep '^R' | wc -l | xargs)

echo "📋 Change summary:" >&2
echo "   Branch: $CURRENT_BRANCH" >&2
echo "   Untracked: $UNTRACKED_FILES files" >&2
echo "   Modified: $MODIFIED_FILES files" >&2
echo "   Added: $ADDED_FILES files" >&2
echo "   Deleted: $DELETED_FILES files" >&2
echo "   Renamed: $RENAMED_FILES files" >&2

# Check for sensitive files before committing
echo "🔒 Checking for sensitive files..." >&2
SENSITIVE_PATTERNS=(
  "\.env"
  "\.env\.*"
  "*secret*"
  "*password*"
  "*key*"
  "id_rsa"
  "id_ed25519"
  "*.pem"
  "*.p12"
  "*.pfx"
)

SENSITIVE_FOUND=false
for pattern in "${SENSITIVE_PATTERNS[@]}"; do
  if git status --porcelain 2>/dev/null | grep -q "$pattern"; then
    SENSITIVE_FOUND=true
    echo "⚠️ Potentially sensitive file detected: $pattern" >&2
  fi
done

# Check if .gitignore exists and is respected
if [ ! -f ".gitignore" ]; then
  echo "💡 Consider creating a .gitignore file to exclude unwanted files" >&2
fi

# Option to skip auto-commit if environment variable is set
if [ "$SKIP_AUTO_COMMIT" = "true" ]; then
  echo "⏭️ Auto-commit skipped (SKIP_AUTO_COMMIT=true)" >&2
  exit 0
fi

# Warn about sensitive files but don't block (user choice)
if [ "$SENSITIVE_FOUND" = true ]; then
  echo "⚠️ Sensitive files detected - proceeding with caution" >&2
  echo "💡 Set SKIP_AUTO_COMMIT=true to disable auto-commits" >&2
fi

# Add all changes (respecting .gitignore)
echo "📥 Staging changes for commit..." >&2
git add -A

# Double-check that we have staged changes
if [ -z "$(git diff --cached --name-only)" ]; then
  echo "ℹ️ No changes staged after git add - nothing to commit" >&2
  exit 0
fi

# Calculate detailed statistics
echo "📊 Calculating commit statistics..." >&2

FILES_CHANGED=$(git diff --cached --numstat | wc -l | xargs)
INSERTIONS=0
DELETIONS=0

# Calculate insertions and deletions more reliably
if command -v awk &> /dev/null; then
  STATS=$(git diff --cached --numstat | awk '{insertions+=$1; deletions+=$2} END {print insertions " " deletions}')
  read -r INSERTIONS DELETIONS <<< "$STATS"
else
  # Fallback method
  INSERTIONS=$(git diff --cached --stat | grep -oE '[0-9]+ insertion' | grep -oE '[0-9]+' | paste -sd+ | bc 2>/dev/null || echo '0')
  DELETIONS=$(git diff --cached --stat | grep -oE '[0-9]+ deletion' | grep -oE '[0-9]+' | paste -sd+ | bc 2>/dev/null || echo '0')
fi

# Generate commit message
COMMIT_MSG="🤖 Claude Code auto-commit: Session ended"

# Add detailed commit body
COMMIT_BODY=$(cat <<EOF

Session Summary:
- Branch: $CURRENT_BRANCH
- Files changed: $FILES_CHANGED
- Insertions: +$INSERTIONS
- Deletions: -$DELETIONS
- Timestamp: $TIMESTAMP

Changes by type:
- Modified files: $MODIFIED_FILES
- New files: $UNTRACKED_FILES
- Deleted files: $DELETED_FILES
- Renamed files: $RENAMED_FILES

🤖 Generated with Claude Code
EOF
)

# Show what will be committed
echo "📝 Files to be committed:" >&2
git diff --cached --name-status | head -10 | while read status file; do
  case $status in
    A) echo "   ✅ Added: $file" >&2 ;;
    M) echo "   ✏️  Modified: $file" >&2 ;;
    D) echo "   ❌ Deleted: $file" >&2 ;;
    R*) echo "   🔄 Renamed: $file" >&2 ;;
    *) echo "   📄 $status: $file" >&2 ;;
  esac
done

if [ "$FILES_CHANGED" -gt 10 ]; then
  echo "   ... and $((FILES_CHANGED - 10)) more files" >&2
fi

echo "" >&2
echo "💾 Creating auto-commit..." >&2

# Create the commit
if echo "$COMMIT_BODY" | git commit -F -; then
  echo "✅ Auto-commit successful!" >&2

  # Show commit info
  COMMIT_HASH=$(git rev-parse --short HEAD)
  echo "📝 Commit: $COMMIT_HASH" >&2
  echo "🌿 Branch: $CURRENT_BRANCH" >&2

  # Check if we should push (optional)
  if [ "$AUTO_PUSH" = "true" ]; then
    echo "📤 Auto-pushing to remote..." >&2
    if git push 2>/dev/null; then
      echo "✅ Pushed to remote successfully" >&2
    else
      echo "⚠️ Push failed - commit created locally" >&2
      echo "💡 Run 'git push' manually when ready" >&2
    fi
  else
    echo "💡 Set AUTO_PUSH=true to automatically push commits" >&2
  fi

else
  echo "❌ Auto-commit failed" >&2
  echo "💡 You may need to resolve conflicts or check git status" >&2
  exit 1
fi

echo "" >&2
echo "📋 Auto-Commit Summary:" >&2
echo "   ✅ $FILES_CHANGED files committed" >&2
echo "   📈 +$INSERTIONS insertions, -$DELETIONS deletions" >&2
echo "   ⏰ $TIMESTAMP" >&2
echo "" >&2
echo "💡 Git Auto-Commit Tips:" >&2
echo "   • Set SKIP_AUTO_COMMIT=true to disable" >&2
echo "   • Set AUTO_PUSH=true to auto-push commits" >&2
echo "   • Review commits with 'git log --oneline'" >&2
echo "   • Use .gitignore to exclude sensitive files" >&2

exit 0

Examples

Git Auto Commit On Stop Hook Script

Complete hook script that performs automatic Git commit when development session ends

#!/usr/bin/env bash
echo "💾 Checking for changes to auto-commit..." >&2
if ! git rev-parse --git-dir > /dev/null 2>&1; then
  echo "⚠️ Not in a git repository - skipping auto-commit" >&2
  exit 0
fi
if [ -z "$(git status --porcelain 2>/dev/null)" ]; then
  echo "✨ No changes to commit - repository is clean" >&2
  exit 0
fi
TIMESTAMP=$(date +"%Y-%m-%d %H:%M:%S")
CURRENT_BRANCH=$(git branch --show-current 2>/dev/null || echo "unknown")
git add -A
FILES_CHANGED=$(git diff --cached --numstat | wc -l | xargs)
COMMIT_MSG="🤖 Claude Code auto-commit: Session ended at $TIMESTAMP"
if git commit -m "$COMMIT_MSG" -m "Branch: $CURRENT_BRANCH" -m "Files changed: $FILES_CHANGED"; then
  echo "✅ Auto-commit successful!" >&2
else
  echo "❌ Auto-commit failed" >&2
  exit 1
fi
exit 0

Sensitive File Detection and Skip Control

Enhanced hook script for sensitive file detection and environment variable skip control

#!/usr/bin/env bash
if [ "$SKIP_AUTO_COMMIT" = "true" ]; then
  echo "⏭️ Auto-commit skipped (SKIP_AUTO_COMMIT=true)" >&2
  exit 0
fi
if ! git rev-parse --git-dir > /dev/null 2>&1; then
  exit 0
fi
if [ -z "$(git status --porcelain 2>/dev/null)" ]; then
  exit 0
fi
SENSITIVE_PATTERNS=(".env" ".env.*" "*secret*" "*password*" "*key*" "id_rsa" "id_ed25519" "*.pem")
SENSITIVE_FOUND=false
for pattern in "${SENSITIVE_PATTERNS[@]}"; do
  if git status --porcelain 2>/dev/null | grep -q "$pattern"; then
    SENSITIVE_FOUND=true
    echo "⚠️ Potentially sensitive file detected: $pattern" >&2
  fi
done
if [ "$SENSITIVE_FOUND" = true ]; then
  echo "⚠️ Sensitive files detected - proceeding with caution" >&2
  echo "💡 Set SKIP_AUTO_COMMIT=true to disable auto-commits" >&2
fi
git add -A
git commit -m "Auto-commit: $(date +'%Y-%m-%d %H:%M:%S')"
exit 0

Detailed Commit Statistics

Enhanced hook script for detailed commit statistics with accurate line count calculations

#!/usr/bin/env bash
if ! git rev-parse --git-dir > /dev/null 2>&1; then
  exit 0
fi
if [ -z "$(git status --porcelain 2>/dev/null)" ]; then
  exit 0
fi
FILES_CHANGED=$(git status --porcelain 2>/dev/null | wc -l | xargs)
MODIFIED_FILES=$(git status --porcelain 2>/dev/null | grep '^.M' | wc -l | xargs)
ADDED_FILES=$(git status --porcelain 2>/dev/null | grep '^A' | wc -l | xargs)
DELETED_FILES=$(git status --porcelain 2>/dev/null | grep '^.D' | wc -l | xargs)
if command -v awk &> /dev/null; then
  STATS=$(git diff --cached --numstat 2>/dev/null | awk '{insertions+=$1; deletions+=$2} END {print insertions " " deletions}')
  read -r INSERTIONS DELETIONS <<< "$STATS"
else
  INSERTIONS=0
  DELETIONS=0
fi
COMMIT_MSG="Auto-commit: $(date +'%Y-%m-%d %H:%M:%S')"
COMMIT_BODY="Files changed: $FILES_CHANGED
Modified: $MODIFIED_FILES
Added: $ADDED_FILES
Deleted: $DELETED_FILES
Insertions: +$INSERTIONS
Deletions: -$DELETIONS"
git add -A
git commit -m "$COMMIT_MSG" -m "$COMMIT_BODY"
exit 0

Automatic Push to Remote

Enhanced hook script for automatic push to remote repository with error handling

#!/usr/bin/env bash
if ! git rev-parse --git-dir > /dev/null 2>&1; then
  exit 0
fi
if [ -z "$(git status --porcelain 2>/dev/null)" ]; then
  exit 0
fi
CURRENT_BRANCH=$(git branch --show-current 2>/dev/null || echo "unknown")
git add -A
git commit -m "Auto-commit: $(date +'%Y-%m-%d %H:%M:%S')" -m "Branch: $CURRENT_BRANCH"
if [ "$AUTO_PUSH" = "true" ]; then
  echo "📤 Auto-pushing to remote..." >&2
  if git push 2>/dev/null; then
    echo "✅ Pushed to remote successfully" >&2
  else
    echo "⚠️ Push failed - commit created locally" >&2
    echo "💡 Run 'git push' manually when ready" >&2
  fi
fi
exit 0

Troubleshooting

Hook creates commits even when no meaningful changes made

git status --porcelain check shows temp files. Update .gitignore excluding: '.DS_Store', '.swp', 'node_modules/'. Or add file count threshold: 'if [ "$MODIFIED_FILES" -lt 2 ]; then exit 0; fi'. Verify .gitignore patterns match temporary files. Use git status --ignored to check ignored files.

Sensitive files (.env) committed despite pattern detection warnings

Pattern match non-blocking by design. Add hard block: 'if [ "$SENSITIVE_FOUND" = true ]; then exit 1; fi' before git add. Or use git-secrets: 'git secrets --scan' pre-commit. Update .gitignore to exclude sensitive file patterns. Use git-secrets or similar tools for automatic detection.

Auto-commit fails with empty commit message or malformed body

COMMIT_BODY uses cat with EOF delimiter requiring proper quoting. Replace with: 'git commit -m "Auto-commit: $TIMESTAMP" -m "Files: $FILES_CHANGED" -m "Branch: $CURRENT_BRANCH"' avoiding heredoc issues. Verify commit message variables are not empty. Use git commit with multiple -m flags for multi-line messages.

SKIP_AUTO_COMMIT environment variable ignored when set

Variable not exported to subprocess. Use: 'export SKIP_AUTO_COMMIT=true' before Claude session. Or add to shell profile: 'echo "export SKIP_AUTO_COMMIT=true" >> ~/.bashrc'. Verify: 'env | grep SKIP'. Check environment variable is set in correct shell context. Use export command to ensure variable is available to subprocesses.

Statistics show zero insertions/deletions despite file changes

git diff --stat fails on binary files or first commit. Add: '--ignore-all-space --ignore-blank-lines' flags. Or use: 'git diff --numstat | awk "{add+=$1; del+=$2} END {print add, del}"' for accurate counts. Verify files are staged before calculating statistics. Check for binary file detection issues.

Auto-commit fails on detached HEAD state

Hook doesn't check for detached HEAD. Add check: 'if git symbolic-ref -q HEAD > /dev/null 2>&1; then echo "On branch"; else echo "Detached HEAD - skipping commit"; exit 0; fi'. Verify repository is on a valid branch before committing. Use git checkout to switch to a branch if needed.

AUTO_PUSH fails with authentication errors

Git push requires authentication. Configure Git credentials: 'git config --global credential.helper store'. Or use SSH keys: 'ssh-keygen -t ed25519 -C "your@email.com"'. Verify remote URL is correct: 'git remote -v'. Check SSH key is added to Git provider. Use credential helper for HTTPS authentication.

Commit messages don't include expected information

Verify commit message generation logic. Check timestamp format: 'date +"%Y-%m-%d %H:%M:%S"'. Verify branch detection: 'git branch --show-current'. Check file statistics calculation. Use git commit with multiple -m flags for structured commit messages. Verify all variables are properly set before commit creation.

Source citations

Add this badge to your README

Show that Git Auto Commit On Stop - Hooks is listed on HeyClaude. Paste this Markdown into your README — it renders the badge and links back to this page.

Listed on HeyClaude
[![Listed on HeyClaude](https://heyclau.de/badge/hooks/git-auto-commit-on-stop.svg)](https://heyclau.de/entry/hooks/git-auto-commit-on-stop)

How it compares

Git Auto Commit On Stop - Hooks side by side with 3 alternatives on trust, install, platform support, and disclosed safety notes — all from reviewed registry metadata.

Field

Automatically commits all changes with a summary when Claude Code session ends.

Open dossier

Automatically generates or updates project documentation when session ends.

Open dossier

A Stop hook that syncs your changed files to cloud storage when a Claude Code session ends, using rclone to push to S3, Google Cloud Storage, or any of its 70+ supported backends.

Open dossier

A Stop hook that runs npm audit, pip-audit, safety, or bundler-audit automatically at the end of every Claude Code session, detecting CVEs and outdated packages across Node.js, Python, and Ruby projects.

Open dossier
Next steps
Trust
Review statusReviewedMaintainer reviewedReviewedMaintainer reviewedReviewedMaintainer reviewedReviewedMaintainer reviewed
Package trustPackage not verifiedPackage not verifiedPackage not verifiedPackage not verified
Source provenanceSource-backedSource-backedSource-backedSource-backed
Submitter
Install riskReview firstReview firstReview firstReview first
Notes Safety Privacy Safety Privacy Safety Privacy Safety Privacy
BrandAWS logoAWS
Categoryhookshookshookshooks
Sourcesource-backedsource-backedsource-backedsource-backed
AuthorJSONboredJSONboredJSONboredJSONbored
Added2025-09-192025-09-192025-09-192025-09-19
Platforms
Claude Code
Claude Code
Claude Code
Claude Code
Source repo
Safety notesRuns automatically at session end and stages all unignored repository changes with git add -A. Creates a local commit when changes are present unless SKIP_AUTO_COMMIT=true is set. Only warns on sensitive-looking filenames and does not block the commit by default.Runs automatically on its configured Claude Code hook event and executes shell logic that can read, modify, or delete files in your project (and may run builds, installs, or network calls); review the script and scope it to expected paths before enabling.Runs automatically at session end and can create compressed archives of modified git files. Uploads backups through AWS CLI, Google Cloud SDK, or rclone when those tools and bucket variables are configured. Writes a temporary archive under /tmp when using the rclone fallback and removes it after the copy attempt.Runs automatically at session end and invokes local package-manager audit tools when dependency lockfiles are present. May contact package registries or vulnerability advisory services through npm, yarn, safety, pip, or bundler-audit. Writes a timestamped security-audit log in the current working directory.
Privacy notesReads git status, branch name, staged diff statistics, and changed file names to build the commit message. Can commit newly created or modified local files, including private work, when they are not excluded by .gitignore. Commit metadata uses the locally configured git user name and email.Receives Claude Code hook input (session metadata, file paths, and tool output) and reads local project files; review what the script logs or forwards to external services and keep credentials out of its output.Sends modified file contents to the configured cloud storage destination. Uses locally configured cloud credentials and bucket environment variables but does not define or manage them. Backup archives may include source code, docs, generated files, and any unignored local changes listed by git diff.Reads dependency manifests and lockfiles to identify package managers and audit targets. The generated audit log may include package names, versions, vulnerability identifiers, and remediation output. External audit tools may send package metadata to their configured registries or advisory services.
Prerequisites— none listed— none listed— none listed— none listed
Install
mkdir -p .claude/hooks && touch .claude/hooks/git-auto-commit-on-stop.sh && chmod +x .claude/hooks/git-auto-commit-on-stop.sh
mkdir -p .claude/hooks && touch .claude/hooks/documentation-auto-generator-on-stop.sh && chmod +x .claude/hooks/documentation-auto-generator-on-stop.sh
mkdir -p .claude/hooks && touch .claude/hooks/cloud-backup-on-session-stop.sh && chmod +x .claude/hooks/cloud-backup-on-session-stop.sh
mkdir -p .claude/hooks && touch .claude/hooks/dependency-security-audit-on-stop.sh && chmod +x .claude/hooks/dependency-security-audit-on-stop.sh
Config
{
  "hooks": {
    "stop": {
      "script": "./.claude/hooks/git-auto-commit-on-stop.sh"
    }
  }
}
{
  "hooks": {
    "stop": {
      "script": "./.claude/hooks/documentation-auto-generator-on-stop.sh"
    }
  }
}
{
  "hooks": {
    "stop": {
      "script": "./.claude/hooks/cloud-backup-on-session-stop.sh"
    }
  }
}
{
  "hooks": {
    "stop": {
      "script": "./.claude/hooks/dependency-security-audit-on-stop.sh"
    }
  }
}
Citations
ClaimUnclaimedUnclaimedUnclaimedUnclaimed
Open 4 picks in the interactive comparison tool

Related guides

Signals

Loading live community signals…

More like this, weekly

A short, calm digest of reviewed Claude resources. Unsubscribe any time.