## Definition A **hook** is a shell command the agentic CLI runs on a specific lifecycle event — before a tool call, after a tool call, on session start, on `Stop`, etc. Hooks are **deterministic**: they do not go through the model. They run because the event fired. ## Lifecycle Events (Claude Code) 25 distinct points. Key events: - **UserPromptSubmit** — fires when a prompt is submitted. Can block or modify. - **PreToolUse** — primary security checkpoint before any tool executes. - **PostToolUse** — fires after a tool runs. - **PermissionRequest** — fires when permission is requested; can auto-approve or deny. - **Stop** — fires when the session ends. ## Configuration ```jsonc { "hooks": { "PostToolUse": [{ "matcher": "Edit|Write|MultiEdit", "hooks": [ { "type": "command", "command": "npm run lint:fix --silent || true" }, { "type": "command", "command": "scripts/check-secrets.sh" } ] }] } } ``` ## Exit Code Semantics - **0** — silent success. - **2** — block; surface stderr to the model so it can correct. - Other non-zero — visible error to the user. ## When Hooks Beat Asking the Model If you put "always run the linter after editing" in `AGENTS.md`, the model *usually* remembers. Usually is not good enough for safety-critical behaviour. A hook fires **every time**, and you can prove it. > Every "always" or "never" rule in `AGENTS.md` that involves running a command is a candidate for promotion to a hook. ## Failure Patterns - *Hooks that block silently.* A non-zero exit with no stderr produces "the session just stops working." Always emit a message. - *Hooks that swallow errors.* `|| true` is convenient but masks real failures; use deliberately. ## Related - [[Extension Trifecta]] - [[AGENTS.md Convention File]] - [[Permission Policy]]