Hooks are the most powerful (and most mistyped) feature in Claude Code. Pick an event, set a matcher and command, and get a valid settings.json — auto-format on save, block dangerous edits, log every command, get notified.
{
"hooks": {
"PostToolUse": [
{
"hooks": [
{
"type": "command",
"command": "jq -r '.tool_input.file_path' | { read f; [[ \"$f\" == *.ts || \"$f\" == *.tsx ]] && npx prettier --write \"$f\"; } || true"
}
],
"matcher": "Edit|Write"
}
]
}
}100% client-side · hooks run shell commands — only use commands you understand
Hooks turn "please always run prettier" from a hope in CLAUDE.md into a guarantee — the app runs your command every time, deterministically.
Runs before a tool call and can block it: exit code 2 stops the action and sends stderr back to Claude. The place for guardrails — protect .env, block rm -rf, enforce your deploy process.
Runs after a tool succeeds. The classic: match Edit|Write and auto-format the touched file. Also great for type-checking, test-triggering, and change logs.
Inject context or validation when you submit a prompt; run cleanup, linters, or notifications when Claude finishes a response (or a subagent does).
SessionStart loads context when you begin or resume; PreCompact fires before Claude compresses history; SessionEnd is your teardown hook.
PostToolUse on Edit|Write → read the file path from the event JSON with jq, run prettier/ruff/gofmt on it. Claude's edits always land formatted.
PreToolUse on Edit|Write → if the path matches .env, keys, or lockfiles, exit 2 with a reason on stderr. Claude sees why and works around it.
PreToolUse on Bash → append the command + description to a log file. A complete audit trail of everything Claude ran, for free.
Notification → osascript (macOS) or notify-send (Linux). Walk away from long sessions; get pinged the moment Claude is waiting on you.
tool_input (for tool events the exact arguments, like .tool_input.file_path or .tool_input.command). jq is the standard way to pull fields out..claude/settings.json for team-shared project hooks (committed), .claude/settings.local.json for personal project hooks (gitignored), ~/.claude/settings.json for hooks you want everywhere.hooks key, the event name is exact (case-sensitive), the matcher matches the real tool name, and you restarted Claude Code — hooks are snapshotted at startup, so run /hooks to verify what's loaded."$CLAUDE_PROJECT_DIR"/.claude/hooks/check.sh) so it's versioned, testable, and readable instead of a one-line jq puzzle.The ClaudeThings kits ship complete Claude Code environments — agents, skills, and commands engineered to work together, hooks-friendly out of the box.
Battle-tested Claude skills & workflows for builders.
Turn Claude into your growth team.
Or grab all 89 agents, 103 skills & 181 commands in the Complete Bundle →