Auto Save Backup - Hooks
Automatically creates timestamped backups of files before modification to prevent data loss. This hook runs before file editing operations (Edit, Write, Multiedit) and creates versioned backups in a centralized .backups directory with ISO 8601-compliant timestamps including nanoseconds for collision prevention.
Open the source and read safety notes before installing.
Schema details
- Install type
- cli
- Reading time
- 1 min
- Difficulty score
- 0
- Troubleshooting
- Yes
- Breaking changes
- No
- Trigger
- PreToolUse
- Script language
- bash
Script body
#!/usr/bin/env bash
# Read the tool input from stdin
INPUT=$(cat)
TOOL_NAME=$(echo "$INPUT" | jq -r '.tool_name')
FILE_PATH=$(echo "$INPUT" | jq -r '.tool_input.file_path // .tool_input.path // ""')
if [ -z "$FILE_PATH" ]; then
exit 0
fi
# Check if file exists before backing up
if [ -f "$FILE_PATH" ]; then
echo "💾 Creating backup for $FILE_PATH..." >&2
# Create backups directory
mkdir -p .backups
# Generate timestamped backup filename
BASENAME=$(basename "$FILE_PATH")
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
BACKUP_NAME="${BASENAME%.*}_${TIMESTAMP}.${BASENAME##*.}"
# Create backup
cp "$FILE_PATH" ".backups/$BACKUP_NAME" 2>/dev/null || true
if [ $? -eq 0 ]; then
echo "✅ Backup created: .backups/$BACKUP_NAME" >&2
else
echo "⚠️ Backup failed for $FILE_PATH" >&2
fi
else
echo "📝 Creating new file $FILE_PATH (no backup needed)" >&2
fi
exit 0Full copyable content
{
"hooks": {
"preToolUse": {
"script": "./.claude/hooks/auto-save-backup.sh",
"matchers": [
"edit",
"write",
"multiedit"
]
}
}
}About this resource
Features
- Automatic timestamped backups before file modification using ISO 8601 format with nanosecond precision for collision prevention
- Organized backup storage in .backups directory with hierarchical structure and configurable retention policies
- Filename format: filename_YYYYMMDD_HHMMSS_NS.ext supporting rapid file edits without timestamp collisions
- Support for all file editing operations including Edit, Write, and Multiedit with batch backup creation
- Version history maintenance with automatic cleanup of old backups based on age or count limits
- Silent failure handling to prevent workflow interruption with graceful error recovery and logging
- Disk space management with pre-backup checks and automatic cleanup of oldest backups when space is limited
- Efficient file copying using optimized cp commands with preservation of file permissions, timestamps, and metadata
Use Cases
- Automatic version control for critical configuration files ensuring recovery from accidental modifications
- Safety net during development and debugging sessions providing rollback capability for experimental changes
- Recovery from accidental file modifications with easy restoration from timestamped backup files
- Maintaining edit history without git commits for files not tracked in version control
- Protection during bulk file operations ensuring all modified files have backups before changes
- Development workflow safety net for rapid prototyping and experimentation with automatic backup creation
Installation
- Create hooks directory: mkdir -p .claude/hooks
- Create hook file: touch .claude/hooks/auto-save-backup.sh
- Make executable: chmod +x .claude/hooks/auto-save-backup.sh
- Add configuration from Hook Configuration section above to .claude/settings.json or ~/.claude/settings.json
- 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
- Bash shell available
- jq installed (for JSON parsing)
- Standard Unix utilities: cp, date, find, mkdir (built into most Unix-like systems)
- Sufficient disk space for backup storage (backups stored in .claude/backups/ directory)
Hook Configuration
{
"hooks": {
"preToolUse": {
"script": "./.claude/hooks/auto-save-backup.sh",
"matchers": ["edit", "write", "multiedit"]
}
}
}
Hook Script
#!/usr/bin/env bash
# Read the tool input from stdin
INPUT=$(cat)
TOOL_NAME=$(echo "$INPUT" | jq -r '.tool_name')
FILE_PATH=$(echo "$INPUT" | jq -r '.tool_input.file_path // .tool_input.path // ""')
if [ -z "$FILE_PATH" ]; then
exit 0
fi
# Check if file exists before backing up
if [ -f "$FILE_PATH" ]; then
echo "💾 Creating backup for $FILE_PATH..." >&2
# Create backups directory
mkdir -p .backups
# Generate timestamped backup filename
BASENAME=$(basename "$FILE_PATH")
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
BACKUP_NAME="${BASENAME%.*}_${TIMESTAMP}.${BASENAME##*.}"
# Create backup
cp "$FILE_PATH" ".backups/$BACKUP_NAME" 2>/dev/null || true
if [ $? -eq 0 ]; then
echo "✅ Backup created: .backups/$BACKUP_NAME" >&2
else
echo "⚠️ Backup failed for $FILE_PATH" >&2
fi
else
echo "📝 Creating new file $FILE_PATH (no backup needed)" >&2
fi
exit 0
Examples
Auto Save Backup Hook Script
Complete hook script that creates timestamped backups before file modifications with nanosecond precision
#!/usr/bin/env bash
INPUT=$(cat)
FILE_PATH=$(echo "$INPUT" | jq -r ".tool_input.file_path // .tool_input.path // \"\"")
if [ -z "$FILE_PATH" ]; then exit 0; fi
if [ -f "$FILE_PATH" ]; then
mkdir -p .backups
BASENAME=$(basename "$FILE_PATH")
TIMESTAMP=$(date +%Y%m%d_%H%M%S_%N)
BACKUP_NAME="${BASENAME%.*}_${TIMESTAMP}.${BASENAME##*.}"
cp "$FILE_PATH" ".backups/$BACKUP_NAME" 2>/dev/null || true
if [ $? -eq 0 ]; then
echo "Backup created: .backups/$BACKUP_NAME" >&2
fi
fi
exit 0
Hook Configuration
Complete hook configuration for .claude/settings.json to enable automatic backups before file edits, writes, and multiedits
{
"hooks": {
"PreToolUse": [
{
"matcher": "Edit|Write|Multiedit",
"hooks": [
{
"type": "command",
"command": "./.claude/hooks/auto-save-backup.sh"
}
]
}
]
}
}
Backup with Disk Space Management
Enhanced hook script with automatic cleanup of old backups when disk space is limited
#!/usr/bin/env bash
INPUT=$(cat)
FILE_PATH=$(echo "$INPUT" | jq -r ".tool_input.file_path")
if [ -f "$FILE_PATH" ]; then
mkdir -p .backups
BASENAME=$(basename "$FILE_PATH")
TIMESTAMP=$(date +%Y%m%d_%H%M%S_%N)
BACKUP_NAME="${BASENAME%.*}_${TIMESTAMP}.${BASENAME##*.}"
# Check disk space before backup
AVAILABLE=$(df -BG .backups | tail -1 | awk '{print $4}' | sed 's/G//')
if [ "$AVAILABLE" -lt 1 ]; then
find .backups -type f -mtime +30 -delete 2>/dev/null
fi
cp "$FILE_PATH" ".backups/$BACKUP_NAME" 2>/dev/null || true
fi
exit 0
Multiedit Backup Support
Hook script that handles Multiedit operations by backing up all files in the edits array
#!/usr/bin/env bash
INPUT=$(cat)
if echo "$INPUT" | jq -e ".tool_input.edits" &> /dev/null; then
mkdir -p .backups
echo "$INPUT" | jq -r ".tool_input.edits[].file_path" | while read -r FILE_PATH; do
if [ -f "$FILE_PATH" ]; then
BASENAME=$(basename "$FILE_PATH")
TIMESTAMP=$(date +%Y%m%d_%H%M%S_%N)
BACKUP_NAME="${BASENAME%.*}_${TIMESTAMP}.${BASENAME##*.}"
cp "$FILE_PATH" ".backups/$BACKUP_NAME" 2>/dev/null || true
fi
done
fi
exit 0
Backup with Retention Policy
Advanced hook script with automatic retention policy limiting backups to last 50 versions per file
#!/usr/bin/env bash
INPUT=$(cat)
FILE_PATH=$(echo "$INPUT" | jq -r ".tool_input.file_path")
if [ -f "$FILE_PATH" ]; then
mkdir -p .backups
# Retention policy: keep last 50 backups per file
BASENAME=$(basename "$FILE_PATH")
FILE_PREFIX="${BASENAME%.*}_"
# Count existing backups for this file
BACKUP_COUNT=$(find .backups -name "${FILE_PREFIX}*" | wc -l)
if [ "$BACKUP_COUNT" -ge 50 ]; then
find .backups -name "${FILE_PREFIX}*" -type f -printf '%T@ %p\n' | sort -n | head -n -50 | cut -d ' ' -f2- | xargs rm -f 2>/dev/null
fi
TIMESTAMP=$(date +%Y%m%d_%H%M%S_%N)
BACKUP_NAME="${BASENAME%.*}_${TIMESTAMP}.${BASENAME##*.}"
cp "$FILE_PATH" ".backups/$BACKUP_NAME" 2>/dev/null || true
fi
exit 0
Troubleshooting
PreToolUse hook runs but backup directory not created
Verify mkdir permissions in project root. Check disk space: df -h. Ensure script runs with correct CWD: pwd >&2 in hook. Create .backups manually if needed: mkdir -p .backups. Check filesystem permissions on project directory.
Backup created but original file modification fails after
PreToolUse only creates backup, doesn't block edits. Check subsequent tool execution logs. Verify hook exits with 0 (non-blocking). Review tool output for actual edit errors. Ensure backup operation completes before file modification.
Timestamp collisions when editing same file rapidly
Add nanoseconds to timestamp: date +%Y%m%d*%H%M%S*%N. Or use hash suffix: ${TIMESTAMP}_$(md5sum file | cut -c1-8). Implement collision detection and retry logic. Use ISO 8601 format with nanoseconds for better precision.
Hook backs up new files that don't exist yet on Write
Verify [ -f "$FILE_PATH" ] check works correctly. Check TOOL_NAME to distinguish edit vs write: if [["$TOOL_NAME" == "edit"]]. Skip backup for new file creation. Use PreToolUse only for Edit operations, not Write.
Backup directory grows unbounded filling disk space
Add retention policy: find .backups -mtime +30 -delete. Implement backup rotation script. Use git for versioning instead. Add size limit checks before creating backups. Limit backups per file: find .backups -name "file_*" | tail -n +50 | xargs rm.
Backup operation takes too long on large files
Add file size check before backup: [ $(stat -f%z file) -lt 10000000 ]. Use rsync for large files: rsync -a file .backups/backup_name. Consider excluding large files from backup. Add timeout wrapper: timeout 10s cp file backup.
Backup files have wrong permissions or ownership
Use cp -p to preserve permissions: cp -p file backup. Check umask settings. Verify backup directory permissions: chmod 700 .backups. Use rsync -a for better metadata preservation: rsync -a file backup.
Multiedit operations only backup first file
Check if FILE_PATH is array in multiedit context. Parse all paths: jq -r '.tool_input.edits[].file_path'. Loop through each file for backup. Verify jq parsing handles arrays correctly. Test with multiple files in edits array.
- Features
- Use Cases
- Installation
- Config paths
- Requirements
- Hook Configuration
- Hook Script
- Examples
- Auto Save Backup Hook Script
- Hook Configuration
- Backup with Disk Space Management
- Multiedit Backup Support
- Backup with Retention Policy
- Troubleshooting
- PreToolUse hook runs but backup directory not created
- Backup created but original file modification fails after
Source citations
Signals
Loading live community signals…
A short, calm digest of reviewed Claude resources. Unsubscribe any time.