DEV Community

Clément Creuzenet
Clément Creuzenet

Posted on Fully Autonomous

Why Claude Code skips your CLAUDE.md rules, and what doesn't get skipped

Every rule I care about was in my CLAUDE.md. "Never git add -A." "Never print .env." "Check the URL before saying a deploy is live." "Never kill processes by pattern." Claude Code broke each of them at least once in a few months.

I don't think it ignores them. I think they lose.

Why rules lose

CLAUDE.md is loaded at the start of the session as part of the context. Then the session fills up: files read, command outputs, errors, your corrections. By the time Claude decides how to commit, your rule is one sentence among tens of thousands of tokens, and the strongest signal in front of it is "the user wants this committed". git add -A is the shortest way to do that.

Longer sessions, more pressure, more skipped rules. Writing the rule in capitals helps a bit. Repeating it helps a bit. Neither turns "usually" into "always".

Hooks don't compete

A hook isn't in the context. It's a script Claude Code runs before (or after) a tool call, outside the model. It sees the exact command and decides. It doesn't get tired at the end of a long session.

The split I use now:

Goes in CLAUDE.md Goes in a hook
Style, conventions, preferences Anything that destroys work
How the project is organised Anything that leaks a secret
What to do when unsure Anything you can't undo
Things where "usually" is fine Things where "usually" isn't

The test: if Claude skips this rule once, can you fix it in a minute? Then CLAUDE.md is fine. If it costs you an afternoon, a leaked key or a client's data, it needs a hook.

Write the reason for Claude

A blocked command comes back to Claude with whatever your hook printed. Use it. "Blocked" makes it retry or stall. "git add -A sweeps in other sessions' work, add files by name" makes it fix the command on the next try. Most of my blocks resolve themselves in one step, without me reading them.

Start small

Take your CLAUDE.md, find the rules where "usually" isn't good enough, and turn each into a ten-line hook. Some of mine are free as a plugin, seatbelt-lite: the deploy check, the Supabase view rule and three shell rules. The full set, with a secret guard, more SQL rules and a longer shell list, is Seatbelt.

Top comments (1)

Collapse
 
reidmarlow profile image
Reid Marlow •

Returning the reason and safe alternative from the hook ("git add -A sweeps in other sessions' work, add files by name") is what lets the model adjust on the next turn instead of retrying the same blocked call.

One seam to watch when moving critical rules out of CLAUDE.md into PreToolUse hooks is command indirection. A pattern matcher watching Bash invocations can miss a chained subshell, an inline script written via Edit, or a flag alias like git add --all. Backing the tool hook with a standard git pre-commit check that inspects staged file paths and diff size catches anything that slips past string matching.