- Add PreToolUse hook intercepting Bash, Write, Edit - Block catastrophic commands (rm -rf /, mkfs, etc.) - Require confirmation for operations outside safe paths - Git-aware: operations in git repos are allowed - Session allowlist for user-confirmed operations - Audit logging to logs/guardrail.jsonl - Clear session allowlist on SessionEnd Config: state/guardrails.json Scripts: hooks/scripts/guardrail.py, guardrail-confirm.py 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
62 lines
2.1 KiB
Bash
Executable File
62 lines
2.1 KiB
Bash
Executable File
#!/bin/bash
|
|
# Session end hook - triggers summarization of the conversation
|
|
# Receives JSON via stdin with session_id, transcript_path, reason
|
|
#
|
|
# Uses Claude CLI with subscription credentials for LLM extraction.
|
|
# Heuristic extraction (paths, facts) always runs.
|
|
# LLM extraction (decisions, preferences) runs if claude CLI is available.
|
|
|
|
set -euo pipefail
|
|
|
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
LOG_FILE="${HOME}/.claude/logs/session-end.log"
|
|
|
|
# Ensure log directory exists
|
|
mkdir -p "$(dirname "$LOG_FILE")"
|
|
|
|
log() {
|
|
echo "[$(date -Iseconds)] $*" >> "$LOG_FILE"
|
|
}
|
|
|
|
# Read JSON input from stdin
|
|
INPUT=$(cat)
|
|
|
|
# Parse JSON fields
|
|
SESSION_ID=$(echo "$INPUT" | python3 -c "import sys, json; print(json.load(sys.stdin).get('session_id', ''))" 2>/dev/null || echo "")
|
|
TRANSCRIPT_PATH=$(echo "$INPUT" | python3 -c "import sys, json; print(json.load(sys.stdin).get('transcript_path', ''))" 2>/dev/null || echo "")
|
|
REASON=$(echo "$INPUT" | python3 -c "import sys, json; print(json.load(sys.stdin).get('reason', ''))" 2>/dev/null || echo "")
|
|
|
|
log "SessionEnd triggered: session=$SESSION_ID reason=$REASON"
|
|
|
|
# Clear guardrail session allowlist (confirmations don't persist across sessions)
|
|
GUARDRAIL_SESSION="${HOME}/.claude/state/guardrail-session.json"
|
|
if [[ -f "$GUARDRAIL_SESSION" ]]; then
|
|
rm -f "$GUARDRAIL_SESSION"
|
|
log "Cleared guardrail session allowlist"
|
|
fi
|
|
|
|
# Validate required fields
|
|
if [[ -z "$SESSION_ID" || -z "$TRANSCRIPT_PATH" ]]; then
|
|
log "ERROR: Missing session_id or transcript_path"
|
|
exit 0 # Exit cleanly - don't break session exit
|
|
fi
|
|
|
|
# Check if transcript exists
|
|
if [[ ! -f "$TRANSCRIPT_PATH" ]]; then
|
|
log "ERROR: Transcript not found at $TRANSCRIPT_PATH"
|
|
exit 0
|
|
fi
|
|
|
|
# Run summarization script in background to not block session exit
|
|
# The script will handle its own error logging
|
|
nohup python3 "${SCRIPT_DIR}/summarize-transcript.py" \
|
|
--session-id "$SESSION_ID" \
|
|
--transcript "$TRANSCRIPT_PATH" \
|
|
--reason "$REASON" \
|
|
>> "$LOG_FILE" 2>&1 &
|
|
|
|
log "Summarization started in background (PID: $!)"
|
|
|
|
# Return success - don't block session exit
|
|
exit 0
|