You can ask an agent to always run the formatter after editing a file, and it will, usually, most of the time, until a long session buries the instruction under fifty other things. That gap between "usually" and "always" is why hooks exist. A hook is a shell command the Claude Code harness itself executes at a fixed lifecycle moment, deterministically, regardless of what the model remembers or decides. Instructions suggest; hooks enforce.
Hooks sit in the Claude Code Configuration & Workflows domain (20% of the CCA-F exam), and questions about them cluster around two skills: knowing which lifecycle event fires when, and knowing when a hook is the right tool versus an instruction, a permission rule, or a skill. This guide covers both. For the domain map, see the exam domains breakdown.
The Mental Model: Instructions vs Hooks
Everything in CLAUDE.md is advisory: the model reads it and generally follows it, but compliance is probabilistic, and it degrades as context fills. A hook is code, not prose. It runs outside the model, triggered by the harness at defined events, and its output flows back into the loop as data the model must confront.
The exam tests this distinction directly. When a requirement reads "must," "always," "never," or "block," the answer is a hook (or a permission rule). When it reads "prefer," "by convention," or "usually," CLAUDE.md instructions are the lighter, correct tool.
Preparing for CCA-F? Practice with 390+ exam questions
The Lifecycle Events
Hooks are configured in settings files (.claude/settings.json and friends) and attach to lifecycle events. The ones the exam expects you to know:
| Event | Fires | Canonical use |
|---|---|---|
PreToolUse | Before a tool call executes | Gate or block dangerous actions (can prevent the call) |
PostToolUse | After a tool call completes | Auto-format after edits, run linters, log actions |
UserPromptSubmit | When the user submits a prompt | Inject context, validate or annotate requests |
Stop | When the main agent finishes responding | Enforce completion criteria, trigger follow-up checks |
SubagentStop | When a subagent finishes | Validate delegated work as it returns |
PreCompact | Before context compaction runs | Preserve critical state ahead of summarization |
SessionStart | When a session begins | Load environment context, warm state |
Notification | When Claude Code sends a notification | Route alerts (idle, permission requests) elsewhere |
Matchers refine the trigger: a PostToolUse hook can match only Edit|Write tool calls, so the formatter runs after file changes and not after every ls.
Exit Codes: How a Hook Talks Back
A hook is a process, and its exit code is its verdict. This is the most-tested mechanic:
- Exit 0: success. stdout is shown in transcript mode (and for some events, fed to the model as context).
- Exit 2: blocking error. For
PreToolUse, this blocks the tool call, and stderr is fed back to Claude so it can adapt. ForStop, it tells the agent it is not actually done. - Other non-zero: non-blocking error. stderr surfaces to the user; the loop continues.
The canonical enforcement pair: a PreToolUse hook that exits 2 when the agent tries to edit a protected path (the edit never happens), and a PostToolUse hook that runs prettier after every successful edit (the format always happens). One prevents, one guarantees.
Hooks receive a JSON payload on stdin describing the event (tool name, tool input, session info), so a gate script can inspect exactly what the agent is about to do before ruling on it. More advanced hooks can return structured JSON for finer control, but exit-code semantics answer most exam questions.
Master These Concepts with Practice
Our CCA-F practice bundle includes:
- 6 full practice exams (390+ questions)
- Detailed explanations for every answer
- Domain-by-domain performance tracking
30-day money-back guarantee
Hook or Something Else? The Decision the Exam Actually Tests
CCA-F scenario questions hand you a requirement and four mechanisms. The sorting logic:
- "Block any edit to
/prod/config":PreToolUsehook (or a permissiondenyrule; the hook wins when the logic needs conditions a static rule cannot express) - "Run tests after every change to
src/":PostToolUsehook with a matcher - "Prefer functional style in this repo": CLAUDE.md instruction; style preferences are advisory by nature
- "The agent should know our deploy procedure when asked": a skill, loaded on demand, keeping the procedure out of every session's context
- "Ask before running
npm install": permission rule (ask), which is the permission system's job rather than a hook's
The trap answers pair a hard requirement with an advisory mechanism ("add it to CLAUDE.md" for a security boundary) or a soft preference with heavy machinery (a hook to enforce a naming convention the linter already checks). See the permissions and settings guide for the permission system's half of this decision.
Security Footnote the Exam Cares About
Hooks run arbitrary shell commands with your credentials, automatically. Two consequences:
- Review hooks like code, because they are code. A malicious or careless hook in a cloned repo's checked-in settings is an attack surface. Claude Code requires reviewing hooks and captures a snapshot of them at startup so mid-session tampering does not take effect silently.
- Hooks are the enforcement layer for untrusted content. Instructions can be prompt-injected; a
PreToolUsegate cannot be talked out of its exit code. Reliability and safety questions reward moving hard guarantees out of prose and into hooks.
Worked Example: The Format-and-Verify Pair
A team wants every edited TypeScript file formatted, and wants the agent blocked from touching anything under infra/:
{
"hooks": {
"PreToolUse": [{
"matcher": "Edit|Write",
"hooks": [{ "type": "command", "command": "block-protected-paths.sh" }]
}],
"PostToolUse": [{
"matcher": "Edit|Write",
"hooks": [{ "type": "command", "command": "npx prettier --write \"$FILE\" 2>/dev/null || true" }]
}]
}
}
block-protected-paths.sh reads the JSON payload from stdin, checks the target path, and exits 2 with a stderr message when it matches infra/. The agent sees the refusal reason and routes around it. The formatter runs unconditionally after real edits and stays silent otherwise. This exact shape (gate + guarantee) is the pattern to reach for across most exam enforcement scenarios.
Build enforcement you can't prompt-inject away
The same enforcement thinking, applied to agent safety: build NeMo Guardrails jailbreak and topical rails around a live agent, then try to break them.
Key Takeaways
- Hooks are deterministic shell commands at lifecycle events; instructions are probabilistic prose. Hard requirements go in hooks.
- Know the event table cold, especially
PreToolUse(can block) versusPostToolUse(reacts after). - Exit 0 = proceed, exit 2 = block with feedback to the model, other non-zero = non-blocking error.
- Sort requirements across hooks, permission rules, CLAUDE.md, and skills by how hard the guarantee must be.
- Hooks execute with your credentials: review them like the code they are.
The Claude Code course covers hooks in Level 5 with an interactive lifecycle widget and a graded enforcement project. To drill the exam angle, Preporato's CCA-F practice tests test hook mechanics across all 6 exams, and the 500-card flashcard deck keeps the event table fresh through your prep.
Sources:
Last updated: July 10, 2026
Ready to Pass the CCA-F Exam?
Join thousands who passed with Preporato practice tests
