51 lines
1.8 KiB
Bash
51 lines
1.8 KiB
Bash
#!/bin/bash
|
|
# post-tool-use.sh: Append an audit log entry after every tool call.
|
|
#
|
|
# Claude Code calls this script AFTER every tool execution.
|
|
# The script receives a JSON object on stdin with two fields:
|
|
# - tool_name: the name of the tool that ran (e.g., "Bash", "Read", "Write")
|
|
# - tool_input: the arguments passed to the tool
|
|
#
|
|
# This script writes one line to hooks/audit.log:
|
|
# 2026-03-30T04:12:33Z | Bash | ls -la /tmp
|
|
#
|
|
# The log is append-only. It grows during the session and persists between sessions.
|
|
# Read it any time with: cat hooks/audit.log
|
|
#
|
|
# Exit code:
|
|
# 0 Always. This hook does not block anything.
|
|
#
|
|
# Make this script executable: chmod +x hooks/post-tool-use.sh
|
|
|
|
# Read the full JSON payload from stdin
|
|
input=$(cat)
|
|
|
|
# Extract the tool name
|
|
tool_name=$(echo "$input" | python3 -c "import sys,json; print(json.load(sys.stdin).get('tool_name','unknown'))" 2>/dev/null || echo "unknown")
|
|
|
|
# Extract the most relevant part of the tool input.
|
|
# Different tools use different argument keys:
|
|
# Bash -> command
|
|
# Read -> file_path
|
|
# Write -> file_path
|
|
# Grep -> pattern
|
|
# Fall back to a truncated string representation of the entire input dict.
|
|
tool_input=$(echo "$input" | python3 -c "
|
|
import sys, json
|
|
d = json.load(sys.stdin).get('tool_input', {})
|
|
value = d.get('command') or d.get('file_path') or d.get('pattern') or str(d)[:120]
|
|
print(value)
|
|
" 2>/dev/null || echo "(parse error)")
|
|
|
|
# Timestamp in UTC ISO 8601
|
|
timestamp=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
|
|
|
|
# Write the log directory relative to this script's location.
|
|
# This keeps the log inside the repo regardless of where Claude Code is invoked from.
|
|
log_dir="$(dirname "$0")"
|
|
log_file="$log_dir/audit.log"
|
|
|
|
# Append one line to the log file
|
|
echo "$timestamp | $tool_name | $tool_input" >> "$log_file"
|
|
|
|
exit 0
|