Claude Code hooks are shell commands that fire at specific lifecycle events. They're configured in .claude/settings.json and run automatically — no manual intervention.
I use 5 hooks across all my projects. Here's each one with the exact config.
1. Auto-Format After Every File Write
Every time Claude writes or edits a file, Prettier runs on it automatically.
{
"hooks": {
"PostToolUse": [{
"matcher": "Write|Edit",
"hooks": [{
"type": "command",
"command": "jq -r '.tool_response.filePath // .tool_input.file_path' | { read -r f; prettier --write \"$f\"; } 2>/dev/null || true"
}]
}]
}
}
Why: Claude's code formatting is inconsistent. Sometimes it uses 2 spaces, sometimes 4. Prettier fixes it instantly. The || true ensures the hook never blocks Claude if Prettier fails.
2. Inbox Check on Every Message
Every time I send a message, Claude checks its message bus inbox for tasks from other agents.
{
"hooks": {
"UserPromptSubmit": [{
"hooks": [{
"type": "command",
"command": "~/.claude/bus/check-inbox.sh my-agent"
}]
}]
}
}
The script checks if ~/.claude/bus/inbox-my-agent.md has content. If yes, it prints the messages. Claude sees them and acts on them before responding to my message.
Why: This is how my 6 agents communicate. No polling interval — messages are delivered the moment I interact with any agent.
3. Session Context on Start
When a new session starts, automatically load the last session's state.
{
"hooks": {
"SessionStart": [{
"hooks": [{
"type": "command",
"command": "cat docs/SESSION-HANDOFF.md 2>/dev/null && echo '---' && cat .claude/rules/known-issues.md 2>/dev/null || true"
}]
}]
}
}
Why: Claude reads the handoff file and known issues automatically. No need to say "read the handoff file" at the start of every session. It just knows what happened last time.
4. Reminder Before Session Ends
When Claude stops (session end, context limit, or user stops), remind it to save state.
{
"hooks": {
"Stop": [{
"hooks": [{
"type": "command",
"command": "echo '{\"systemMessage\": \"REMINDER: Update docs/SESSION-HANDOFF.md with what was done, what failed, and what is next.\"}'"
}]
}]
}
}
Why: Without this, Claude often stops mid-task without saving context. The reminder fires every time, so the handoff file stays current.
5. Protect Critical Files
Before any edit to protected files, block the write.
{
"hooks": {
"PreToolUse": [{
"matcher": "Edit|Write",
"hooks": [{
"type": "command",
"command": "jq -r '.tool_input.file_path // \"\"' | grep -qE '(\\.env|credentials|secrets)' && echo '{\"decision\": \"block\", \"reason\": \"Cannot edit sensitive files\"}' || true"
}]
}]
}
}
Why: Claude occasionally tries to write API keys or modify .env files. This hook blocks any edit to files matching sensitive patterns. It's a safety net you set once and forget.
The Hook Lifecycle
Here's when each hook type fires:
| Event | When | Use case |
|---|---|---|
SessionStart |
New session begins | Load context |
UserPromptSubmit |
You send a message | Check inbox |
PreToolUse |
Before a tool runs | Block dangerous actions |
PostToolUse |
After a tool succeeds | Format code, run tests |
Stop |
Session ends | Save state |
PreCompact |
Before context compression | Preserve critical info |
Setting It Up
All hooks go in .claude/settings.json (project-level) or ~/.claude/settings.json (global).
# Create project settings
mkdir -p .claude
cat > .claude/settings.json << 'EOF'
{
"hooks": {
"PostToolUse": [{
"matcher": "Write|Edit",
"hooks": [{
"type": "command",
"command": "echo 'file written'"
}]
}]
}
}
EOF
Start simple. Add one hook. Verify it fires. Then add more.
Common Mistakes
1. Missing || true — If your hook command fails, it can block Claude entirely. Always add || true unless you intentionally want to block on failure.
2. Hooks that are too slow — Hooks run synchronously by default. A hook that takes 10 seconds runs on every single tool call. Keep them fast.
3. Forgetting the JSON output format — Stop hooks need to output JSON with systemMessage field. Plain text won't show up.
These 5 hooks run across 16 projects. Once set up, they work silently in the background. The best automation is the kind you forget exists.
Top comments (0)