Blog
Claude Code Hooks Enforce Behavior. They Can't Tell the Model What's True.
10 min read
Once people learn that CLAUDE.md is advisory, the natural next move is hooks — and they are right to make it. Hooks are the real enforcement layer in Claude Code: deterministic shell commands the harness runs, not suggestions the model can skip. If you need "this action must never happen," a hook delivers it every time. But enforcement and knowledge are different things. A hook can stop Claude from editing the wrong file. It cannot tell Claude which file is right.
Hooks are the guarantee CLAUDE.md isn't
Credit where due — hooks are excellent at what they do:
What hooks are genuinely great at
PreToolUse -> block an edit to a forbidden path. Every time.
PostToolUse -> run the formatter / tests after every change
exit code 2 -> reject the action, feed stderr back as feedback
Deterministic. Harness-run, not model-judged. If you need
"X must never happen," this is the only thing that guarantees it.Because the harness runs them rather than the model deciding whether to comply, hooks are not subject to the probabilistic drift that makes an instruction file unreliable. A PreToolUse hook that blocks writes to a protected path blocks them on turn one and turn fifty alike. This is genuinely the right tool for hard rules, and it is why the docs point you here for enforcement.
But a guardrail is not knowledge
The limit shows the moment the question shifts from "what is forbidden" to "what is true":
What a hook can't do
A hook can check: "is this path in the blocklist?"
A hook can't know: "which path is the RIGHT one to edit?"
-> it can block writing to generated/, but can't tell Claude
the schema moved to prisma/schema.prisma last week
-> it can require a test run, but can't supply the service
boundary the test should respect
-> rules operate on patterns; grounding requires current factsA hook is a function over an action — it sees a tool call and decides allow or block. It has no model of your codebase. It cannot tell the agent that the auth helper migrated to v2, that the schema moved, or which service owns a boundary. You can hand-code a hook with a hardcoded fact, but now that fact is a static rule that goes stale exactly like a stale CLAUDE.md — you have just moved the drift problem into a shell script.
Enforcing the wrong fact is still wrong
Here is the trap people fall into: they enforce hard, assume they have solved reliability, and miss that enforcement without grounding just makes wrong work consistent. If the agent believes data access goes through a pattern that was deprecated last month, a hook that reliably runs the test suite will reliably test the wrong implementation. Determinism is only a virtue when what you are enforcing is correct. A guardrail around a stale assumption produces stale output every single time — reliability pointed at the wrong target.
You need both layers
Enforcement and grounding are complementary, not substitutes:
Enforcement and grounding are different layers
Hooks (enforcement):
-> deterministic guardrails on ACTIONS
-> "don't do that" / "always run this"
Index (grounding):
-> current KNOWLEDGE about the code
-> "here is how this actually works today"
You need both. A guardrail around a wrong fact still
produces wrong work — just reliably.Hooks govern what the agent is allowed to do. Grounding governs what the agent knows. The mistake is expecting either one to cover for the other — advisory text that cannot enforce, or hooks that cannot inform. The reliable setup uses hooks for the guardrails and a current source of truth for the facts, the same division of labor we draw in context grounding as the real fix for hallucination.
Where Kognita fits
Kognita is the grounding half of that pairing. It maintains a semantic index of your repositories, re-indexed as the code changes, and serves current codebase facts to the agent on demand over MCP. Keep your hooks for hard enforcement — protected paths, mandatory formatters, required checks — and let Kognita supply the knowledge a hook cannot: which file is right, how the service actually behaves today, where the boundary really sits. Enforce the rules with hooks; ground the facts with an index designed to stay true.
Final take
Hooks fix the enforcement gap that CLAUDE.md leaves open, and you should use them. Just do not mistake a guardrail for understanding. A hook can guarantee the agent does not touch the wrong file; it cannot tell the agent which file is right, and hardcoding that into the hook only relocates the staleness problem.
Hooks enforce behavior; they cannot supply current truth. Reliable agents need both — deterministic guardrails and grounding that stays accurate as the code moves.