Hook vs CLAUDE.md by trust level
What you'll learn
Use a hook when you can't tolerate the model ignoring the rule. Use CLAUDE.md when 'usually applies' is good enough.
- Single decision axis: trust requirement.
- Cannot accept model override → hook.
- Advice / nudge / preference → CLAUDE.md.
The choice between hook and CLAUDE.md (or memory, or system prompt) maps cleanly to a single axis: **trust requirement**. CLAUDE.md is *advisory* — the model reads it and interprets it. Hooks are *enforced* — the harness executes them regardless of the model's decision. If the rule must apply even when the model would rather skip it, the answer is hook. If 'usually applies' is fine, CLAUDE.md is lighter and equally appropriate.
The decision: ask 'what happens if the model decides to ignore this?' If the answer is 'a security incident', 'production data loss', 'compliance breach' — anything you cannot accept the model overriding — that's a hook. If the answer is 'the suggestion is slightly less aligned with our style' — that's CLAUDE.md.
Hooks have additional structural advantages even when both could work. They run synchronously and deterministically; they have access to event context (the candidate command for PreToolUse, the tool result for PostToolUse, etc.); they can return blocking decisions (PreToolUse can refuse a tool call). CLAUDE.md is read by the model, interpreted, possibly compressed alongside other context, and competes with everything else for attention.
The over-engineering trap is real in the other direction: putting *every* nudge in a hook is heavy machinery for what should be a CLAUDE.md sentence. Style preferences, naming conventions, 'we like comments to be terse' — these are advice, not enforcement. Putting them in hooks adds complexity without trust requirement. Match the mechanism to the trust level.
Key points
- Single decision axis: trust requirement.
- Cannot accept model override → hook.
- Advice / nudge / preference → CLAUDE.md.
- Hooks have synchronous determinism + event context + block primitive.
- Don't over-engineer: not every CLAUDE.md rule needs to be a hook.
Examples
If the model decides to run rm -rf, you have a destroyed filesystem. Trust requirement = absolute. Implementation: PreToolUse hook that pattern-matches the candidate command and returns a deny.
If the model uses 2 spaces in one file, the consequence is a style inconsistency, not a security event. Advisory is fine. Implementation: one line in CLAUDE.md.
If the model commits without linting, CI fails — annoying but recoverable. Trust requirement is non-zero (lint catches bugs). Implementation: PreToolUse on the git-commit shell call, or Stop hook that fails loudly.
Pitfalls
- Putting security guardrails in CLAUDE.md ('please don't run rm -rf'). Advisory ≠ enforcement; the model can rationalise around it.
- Putting style nudges in hooks. Heavy machinery; adds friction; obscures the actual policies.
- Conflating 'I want this to always happen' with 'I want this enforced.' Always-happen advice is CLAUDE.md; enforced is hook.
Source notes: 00-academy-basics/notes/06-claude-code-in-action.md
Ask Claude
Build a prompt with this lesson + your question, copy it, and open the Claude Project in a new tab.