Claude Code Hooks: Automation That Can't Hallucinate

Published Aug 3, 2026

A CLAUDE.md instruction is a prompt — Claude reads it and decides how to apply it, which means in a long session it can be forgotten, deprioritized, or misapplied. A hook is different: it's a real script that runs automatically on a specific event, outside the model's interpretation entirely. It can't forget, and it can't talk itself out of running.

Why "Just Tell It in CLAUDE.md" Isn't Enough

CLAUDE.md works well for conventions and context — things where you want Claude to use judgment. It's the wrong tool for a rule that must hold every single time, because a prompt is still just a prompt: in a long session with a lot of context, an instruction from the top of the file can get less weight than something discussed five messages ago. A hook doesn't have that problem, because it isn't part of the conversation at all — it's code that runs whether or not the model "remembers" to check.

A Real Example: Blocking Edits to One File

Say a client project has one legacy config file you're deliberately not touching yet — refactoring it is a separate, scoped piece of work you haven't started. Instead of writing "don't touch legacy-config.js" in CLAUDE.md and hoping it holds for the whole session, a hook that runs before file edits can check the target path and exit with an error if it matches the protected file. The edit simply doesn't happen — no judgment call involved.

A Real Example: Enforcing a Lint Pass

Rather than asking Claude to "remember to run the linter after changes," a hook that fires after file edits can run the linter automatically and surface the result. This turns "please remember to lint" from a hope into a guarantee — it happens every time, regardless of how long the session has run or how many other things are being discussed.

#!/bin/bash
# Example: a post-edit hook that runs a linter and fails loudly
# if the edited file doesn't pass — read your own hooks config
# for the exact event name and input format Claude Code provides.

npx eslint "$CLAUDE_EDITED_FILE" || {
  echo "Lint failed on $CLAUDE_EDITED_FILE — fix before continuing."
  exit 1
}

Treat the exact variable names and event payload as something to confirm against Claude Code's own hooks documentation for your installed version — the concept (a script gated on a real event) is the durable part; the precise interface details change between releases.

Where This Matters Most on Client Work

The rules worth enforcing as hooks are the ones where a mistake is expensive: never commit directly to a client's main branch, never touch a payments-related file without a second look, never skip the test suite before marking something done. These are exactly the rules that are easy to state once and easy to forget by message thirty of a long session — which is precisely the gap a hook closes.

Want the Whole Toolchain in One Place?

Hooks, subagents, MCP, and Skills all solve different problems — the free guide covers the fundamentals first if you're still getting oriented.

Get the Free Guide →

Frequently Asked Questions

What's the difference between a hook and a CLAUDE.md instruction?

CLAUDE.md is a prompt — the model reads it and decides how to apply it, which means it can be forgotten, misread, or deprioritized in a long session. A hook is a real script that runs automatically on a specific event, outside the model's interpretation entirely. It cannot be talked out of running.

What events can trigger a hook?

Common trigger points include before a tool runs, after a tool runs, and around user prompt submission — letting you intercept an action before it happens or react to one right after. The exact set of available events is documented in Claude Code's own hooks reference; treat this as the concept, not the full list.

Can a hook block Claude Code from doing something?

Yes — a pre-action hook can inspect what's about to happen and exit with a failure to stop it, which is exactly how you'd enforce a rule like "never edit this file" as code instead of as an instruction the model might not apply consistently.

Do hooks need to be complicated to be useful?

No — the most useful hooks on client work tend to be small: a linter that runs after every edit, a guard that blocks writes to one protected path, a script that logs every command run for a same-day changelog. Small and specific beats clever and broad.