VI EN
1 / 7
Claude Code Feature

Hooks
>_

Automate workflows with shell commands — run guaranteed at specific lifecycle points when Claude edits files, finishes tasks, or needs input.

⚙️ 20+ lifecycle events
🔌 5 hook types
🎯 Deterministic, not LLM best-effort
What are hooks? 3 pillars
🎯 DETERMINISTIC CONTROL
User-defined shell commands that execute at specific lifecycle points — guaranteed to run, not left to the LLM.
⚡ EVENT-DRIVEN
Hooks fire on events like PreToolUse, PostToolUse, Notification, SessionStart — 20+ types.
🔌 MULTIPLE TYPES
command · http · mcp_tool · prompt · agent — pick the right execution model for each use case.
Lifecycle events
SessionStartSession begins or resumes
UserPromptSubmitBefore Claude processes your prompt
PreToolUseBefore a tool call executes — can block it
PostToolUseAfter a tool call succeeds
NotificationWhen Claude needs your input
PermissionRequestWhen a permission dialog appears
FileChangedA watched file changes on disk
PreCompactBefore context compaction
StopWhen Claude finishes or errors out
First hook: Notification

Desktop notification when Claude needs input — never miss a prompt. Add to ~/.claude/settings.json:

// ~/.claude/settings.json { "hooks": { "Notification": [{ "matcher": "", "hooks": [{ "type": "command", "command": "osascript -e 'display notification \"Claude needs input\" with title \"Claude Code\"'" }] }] } }

→ Open /hooks to see registered events. Ask Claude something, switch tabs — notification fires.

Common automation patterns
🔔
NOTIFICATIONS
Desktop alert when input is needed via Notification
AUTO-FORMAT
Prettier/ESLint after Edit|Write via PostToolUse
🔒
PROTECT FILES
Block edits to .env, .git via PreToolUse
💾
RELOAD CONTEXT
Re-inject reminders after compaction
📋
AUDIT LOG
Log every ConfigChange to a file
AUTO-APPROVE
Skip prompts for trusted tools
How hooks communicate

Claude sends JSON via stdin. Your script replies via exit code + stdout/stderr:

exit 0 Action proceeds normally
exit 2 Blocked — stderr is sent to Claude as feedback
JSON Structured stdout: allow/deny + reason
// PreToolUse — deny + reason { "hookSpecificOutput": { "hookEventName": "PreToolUse", "permissionDecision": "deny", "permissionDecisionReason": "Use rg instead of grep" } }
Filter with matchers

The matcher field scopes which hooks run — keep it as narrow as possible.

PostToolUse · "Edit|Write"
Runs only for file-editing tools
PreToolUse · "Bash"
Fires only when Claude runs Bash
SessionStart · "compact"
Triggers only after compaction
PermissionRequest · "ExitPlanMode"
Auto-approve plan completion only
3 things to remember:
exit 2 blocks · exit 0 + JSON for structured decisions
• Use matcher to scope hooks — avoid over-broad automation
• Verify with /hooks, debug via log, iterate fast