Guide for developing Claude Code hooks with proper output visibility patterns.
When to Use This Skill
-
Creating a new PostToolUse or PreToolUse hook
-
Hook output is not visible to Claude (most common issue)
-
User asks about
decision: blockpattern -
Debugging why hook messages don't appear
-
User mentions "Claude Code hooks" or "hook visibility"
Quick Reference: Visibility Patterns
Critical insight: PostToolUse hook stdout is only visible to Claude when JSON contains "decision": "block".
| Plain text | Not visible
| JSON without decision: block
| Not visible
| JSON with decision: block
| Visible
Exit code behavior:
| 0
| JSON parsed, shown in verbose mode only
| Only if "decision": "block"
| 2 | Ignored, uses stderr instead | stderr shown to Claude
| Other | stderr shown in verbose mode | Not shown to Claude
Minimal Working Pattern
/usr/bin/env bash << 'SKILL_SCRIPT_EOF'
#!/usr/bin/env bash
set -euo pipefail
# Read hook payload from stdin
PAYLOAD=$(cat)
FILE_PATH=$(echo "$PAYLOAD" | jq -r '.tool_input.file_path // empty')
[[ -z "$FILE_PATH" ]] && exit 0
# Your condition here
if [[ condition_met ]]; then
jq -n \
--arg reason "[HOOK] Your message to Claude" \
'{decision: "block", reason: $reason}'
fi
exit 0
SKILL_SCRIPT_EOF
Key points:
-
Use
jq -nto generate valid JSON -
Include
"decision": "block"for visibility -
Exit with code 0
-
The "blocking error" label is cosmetic - operation continues
TodoWrite Templates
Creating a PostToolUse Hook
1. [pending] Create hook script with shebang and set -euo pipefail
2. [pending] Parse PAYLOAD from stdin with jq
3. [pending] Add condition check for when to trigger
4. [pending] Output JSON with decision:block pattern
5. [pending] Register hook in hooks.json with matcher
6. [pending] Test by editing a matching file
7. [pending] Verify Claude sees the message in system-reminder
Debugging Invisible Hook Output
1. [pending] Verify hook executes (add debug log to /tmp)
2. [pending] Check JSON format is valid (pipe to jq .)
3. [pending] Confirm decision:block is present in output
4. [pending] Verify exit code is 0
5. [pending] Check hooks.json matcher pattern
6. [pending] Restart Claude Code session
Reference Documentation
-
Lifecycle Reference - All 10 hook events, diagrams, use cases, configuration pitfalls
-
Visibility Patterns - Full exit code and JSON schema details
-
Hook Templates - Copy-paste templates for common patterns
-
Debugging Guide - Troubleshooting invisible output
Post-Change Checklist (Self-Evolution)
When this skill is updated:
Update evolution-log.md with discovery Verify code examples still work Check if ADR needs updating: PostToolUse Hook Visibility ADR
Related Resources
-
GitHub Issue #3983 - Original bug report
-
Claude Code Hooks Reference - Official documentation