Log tool failures for debugging
Writes a structured JSONL record whenever a Bash, Edit, or Write call fails - the debugging trail you wish you had last week.
PostToolUseFailureBash|Edit|Writelow riskneeds manual checkWhat it does
Fires on PostToolUseFailure. Appends {ts, session_id, tool_name, tool_use_id, error} to .claude/tool-failures.jsonl. Deliberately does NOT log full tool inputs: commands and file contents can contain secrets. When something breaks, tail this file instead of scrolling the transcript.
When it runs
| Event | PostToolUseFailure |
| Matcher | Bash|Edit|Write |
| Scope | project |
| Platforms | macos, linux |
| Timeout | 10s |
| Requires | jq |
| Failure mode | observe |
| Verified against | Claude Code hooks reference, event/matcher schema checked 2026-09-10 |
| Test status | needs manual check - run the test steps below before relying on it |
Config
Merge this into .claude/settings.json - or use the generator to combine hooks.
{
"hooks": {
"PostToolUseFailure": [
{
"hooks": [
{
"type": "command",
"command": "${CLAUDE_PROJECT_DIR}/.claude/hooks/log-tool-failures.sh",
"timeout": 10
}
],
"matcher": "Bash|Edit|Write"
}
]
}
}Script
Save as .claude/hooks/log-tool-failures.sh and chmod +x it.
#!/bin/bash
# log-tool-failures: structured failure log, inputs redacted by design.
set -u
input=$(cat)
log="${CLAUDE_PROJECT_DIR:-.}/.claude/tool-failures.jsonl"
mkdir -p "$(dirname "$log")"
printf '%s' "$input" | jq -c --arg ts "$(date -u +%Y-%m-%dT%H:%M:%SZ)" '{ts: $ts, session: .session_id, tool: .tool_name, tool_use_id: .tool_use_id, error: (.error // .tool_use_error // "unknown")}' >> "$log"
exit 0
Install
- Save the script to .claude/hooks/log-tool-failures.sh and chmod +x it.
- Add the config fragment to .claude/settings.json (and the log path to .gitignore).
Test it
- Positive: make a Bash call fail (e.g. run a command that does not exist via Claude), then tail .claude/tool-failures.jsonl.
- Negative: successful tool calls write nothing.
Sources
- Claude Code hooks reference (checked 2026-09-10)
Related hooks
Compact audit trail on stop
Appends a one-line JSON record to a local audit log every time Claude finishes a turn.
Stoplow riskneeds manual checkPro Pack (later)
Framework bundles, cross-platform scripts, tested blocking policies, and a test harness. Free recipes and the generator stay free.
Waitlist opens soon.