What Are Claude Code Hooks? Run Shell Commands Deterministically
Claude Code hooks are user-defined shell commands that run automatically at specific points in Claude Code's lifecycle, making "this must always happen" real and deterministic without relying on the LLM's judgment. The classic events are nine—SessionStart, UserPromptSubmit, PreToolUse, PostToolUse, Notification, Stop, SubagentStop, SessionEnd, PreCompact—of which PreToolUse and others can block (stopping protected-file edits or dangerous commands). You configure them in settings.json under the "hooks" key as event name -> matcher -> type + command. The I/O contract: a hook receives JSON on stdin (session_id, tool_input, etc.) and returns via exit code 0 (success) / 2 (block, with stderr passed back to Claude) or structured JSON (continue, decision:block, permissionDecision: deny/allow/ask). The key principle is "hooks can tighten but not loosen restrictions" (deny always wins, blocks even under bypassPermissions; a plugin mod can override this in some setups). Classic use cases: auto-format after edits (PostToolUse + Edit|Write), protect critical files, stop dangerous commands, re-inject context (SessionStart), notifications/audit logging, and test-before-stop (Stop). On security, hooks run arbitrary shell commands with your privileges, so only configure trusted ones and validate/quote inputs; in interactive sessions, settings-file hooks do not run until you trust the folder (a safety feature), and direct edits to settings files are normally picked up automatically. Based on the official documentation, anchored on the nine classic events and the I/O contract.