What you’ll be able to do
- Configure a PreToolUse or PostToolUse hook to enforce a team policy
- Explain why a hook is more reliable than an instruction for a hard rule
- Distinguish Claude Code’s product-level hooks from an Agent SDK’s lifecycle hooks
What you need to know
A hook is enforcement outside the model’s judgment
Claude Code hooks are shell commands configured in settings.json that run at defined points in the tool-use lifecycle — before a tool runs (PreToolUse), after one completes (PostToolUse), and other lifecycle points. A PreToolUse hook can inspect a proposed command and block it before it executes; a PostToolUse hook can run after a file edit to lint it or log it.
The architectural point is that a hook is deterministic configuration, not an instruction the model has to remember and choose to follow. "Please don't run destructive commands in the production directory" is a request the model is asked to honor every time. A PreToolUse hook that inspects the command and refuses to let it execute is a rule that holds regardless of what the model reasoned its way into wanting to do.
Designing a hook: what to check, and how strict to be
A useful hook is specific about what it blocks and permissive about everything else. A hook that inspects a bash command for a destructive pattern (rm -rf against an unexpected path, a force-push to a protected branch) and blocks only that is enforcing a real policy. A hook that blocks broadly "to be safe" turns into friction that gets disabled the first time it stops legitimate work — and a disabled hook enforces nothing.
The CLAUDE.md line is a good reminder. It is not enforcement — nothing stops a session that's reasoned its way to "this force-push is the right call" from making it anyway. The hook stops the command regardless of the reasoning that preceded it.
A different layer from an Agent SDK’s lifecycle hooks
Claude Code's hooks (in settings.json) govern the Claude Code product itself — the interactive coding tool a developer runs. An Agent SDK's lifecycle hooks (covered under Agentic Architecture & Orchestration) govern a custom-built agent application assembled from the SDK. They share a name and a similar before/after shape, but they configure different systems, at different layers, for different audiences — one is a team's IDE-adjacent tool policy, the other is a product architect's runtime guardrail for an application they're shipping to end users.
Key concept
A hook enforces a rule deterministically, outside the model’s judgment — the fix for anything that must never happen, not just something you’d prefer didn’t.
When a scenario describes a hard rule that keeps getting violated despite being stated clearly in instructions, the fix is a hook, not a stronger or more repeated instruction.
Practice scenario
Work it through, then open this
An instruction in CLAUDE.md is a request the model is expected to honor, and a session that talks itself into an exception will still act on that exception. A PreToolUse hook that inspects git commands and blocks a commit targeting the main branch enforces the rule regardless of the reasoning that preceded it — there’s no “small enough to skip it” exception available once the hook is in place.
Build exercise — Decide instruction versus hook for a set of rules
Intermediate · 20 min
What you’ll learn
- Sorting team rules into “should be a hook” versus “fine as an instruction”
- Scoping a hook narrowly enough that it doesn’t block legitimate work
- Naming the lifecycle point (PreToolUse vs PostToolUse) a given rule needs
-
List a team’s stated CLAUDE.md rules and mark which ones describe something that must never happen versus something that’s merely preferred.
- Why: “Must never happen” rules belong in a hook; preferences are fine left as instructions.
- You should see: At least one rule serious enough to deserve enforcement, not just a request.
-
For a rule that needs a hook, decide whether it needs to run before the action (to block it) or after (to check or log its result).
- Why: Blocking a destructive command requires PreToolUse; auditing or linting a completed change fits PostToolUse.
- You should see: A clear match between the rule’s intent and the lifecycle point it needs.
Exam traps
Writing “never run rm -rf” as an instruction instead of a blocking hook
An instruction can be reasoned around. A PreToolUse hook enforces the rule regardless of the model’s reasoning.
Confusing Claude Code’s settings.json hooks with a custom Agent SDK’s lifecycle hooks
They’re different layers: one governs the Claude Code product, the other governs a custom-built agent application.
Making a hook so aggressive it blocks legitimate, safe operations
An overly broad hook creates friction, gets disabled, and then enforces nothing at all.
Forgetting that a hook is configuration, not something the model can talk itself out of
That’s precisely its value over an instruction — it holds regardless of what reasoning preceded the action.