#!/usr/bin/env bash # Pre-compact hook: save a copy of the session transcript before compaction. # Claude Code pipes JSON with session_id, cwd, hook_event_name (no transcript_path). # Derives the transcript location from session_id + cwd. # After saving, registers the backup in ~/.claude/transcript-backups/tracking.json. set -euo pipefail # Parse stdin JSON INPUT="$(cat)" SESSION_ID="$(echo "$INPUT" | python3 -c "import sys,json; print(json.load(sys.stdin).get('session_id',''))" 2>/dev/null)" CWD="$(echo "$INPUT" | python3 -c "import sys,json; print(json.load(sys.stdin).get('cwd',''))" 2>/dev/null)" PROVIDED_PATH="$(echo "$INPUT" | python3 -c "import sys,json; print(json.load(sys.stdin).get('transcript_path',''))" 2>/dev/null)" if [ -z "$SESSION_ID" ]; then echo "pre-compact-backup: missing session_id in hook input, skipping" >&2 exit 0 fi # Try provided path first (older Claude Code versions), then derive from session_id + cwd if [ -n "$PROVIDED_PATH" ] && [ -f "$PROVIDED_PATH" ]; then TRANSCRIPT_PATH="$PROVIDED_PATH" elif [ -n "$CWD" ]; then # Derive transcript path: /home/paul/dev/claude -> -home-paul-dev-claude PROJECT_DIR="$(echo "$CWD" | tr '/' '-')" TRANSCRIPT_PATH="$HOME/.claude/projects/${PROJECT_DIR}/${SESSION_ID}.jsonl" else echo "pre-compact-backup: cannot locate transcript (no cwd or transcript_path), skipping" >&2 exit 0 fi if [ ! -f "$TRANSCRIPT_PATH" ]; then echo "pre-compact-backup: transcript not found at ${TRANSCRIPT_PATH}, skipping" >&2 exit 0 fi # Save to ~/.claude/transcript-backups/ with timestamp BACKUP_DIR="$HOME/.claude/transcript-backups" mkdir -p "$BACKUP_DIR" TIMESTAMP="$(date +%Y%m%d-%H%M%S)" BACKUP_NAME="${TIMESTAMP}-${SESSION_ID:0:8}.jsonl" BACKUP_FILE="${BACKUP_DIR}/${BACKUP_NAME}" cp "$TRANSCRIPT_PATH" "$BACKUP_FILE" # Prune backups older than 30 days find "$BACKUP_DIR" -name "*.jsonl" -mtime +30 -delete 2>/dev/null || true # Register backup in tracking.json using the register helper python3 "$HOME/.claude/scripts/extract-transcripts.py" \ --register "$BACKUP_NAME" \ --session-id "$SESSION_ID" \ --cwd "$CWD" \ 2>/dev/null \ && TRACKED=" [tracked]" \ || TRACKED=" [tracking failed]" echo "pre-compact-backup: saved $(wc -l < "$BACKUP_FILE") lines to ${BACKUP_NAME} [project: ${CWD}]${TRACKED}" >&2