## 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]]