/t · guide · why rules get skipped

Why Claude skips rules in your CLAUDE.md

M
Matthew Diakonov
6 min read

A common confusion: people read that CLAUDE.md is in the system prompt for every turn, watch Claude ignore half of it anyway, and conclude the file is broken or Claude is broken. Neither is true. The bytes are firing. They're just not making it through the model's pass over the system prompt into a gated action.

This page walks the six line shapes that cause that failure, each one with the analyzer detector that flags it and a short note on how to reshape the rule so it survives. Run the same check on your own file at ccmd.dev.

1. The line is too long

The single most common skip cause we see. A rule written as a 30-to-50-word sentence ("we use Next.js, Postgres on Neon, Stripe for payments, Resend for transactional email, and we deploy to Vercel from main with preview deploys on every PR which means we have to be careful about migrations") lands as one signal in the model's attention. The first part survives, the second part gets compressed away. The threshold the analyzer uses is 28 words.

src/lib/analyzer.ts

The fix is mechanical: split the long sentence into 2 to 3 short directives, each one independently actionable. "Stack: Next.js, Postgres on Neon, Stripe." "Deploys: Vercel main, preview per PR." "Migrations: confirm before destructive ops." Three short rules survive; one long paragraph does not.

2. The rule has no testable success condition

"Write clean code." "Handle edge cases appropriately." "Use modern best practices." The model fires the rule, reads it, and has no way to tell when it succeeded. The rule effectively collapses to "do whatever you were going to do, but try harder," which is a no-op. The analyzer tracks 14 of these terms by name.

src/lib/analyzer.ts

The fix is to replace the vague term with something the model can check against. Instead of "write clean code", write "no function longer than 40 lines; no file longer than 300." Instead of "handle edge cases appropriately", write "for every public function, add at least one test for the error path." A concrete rule survives because the model can detect when it's satisfied; a vague rule gets dropped because there's nothing to satisfy.

ignored

Honestly, I haven't found CLAUDE.md to be all that useful. There's so much information in there that gets ignored.

HN commenter, thread 47581701

3. The rule uses an absolute with no escape clause

Real codebases have exceptions to almost every absolute. "Always write tests." Except for the one-line script that runs once and gets deleted. "Never use any." Except in a type-narrowing helper. When the model reads an absolute and immediately encounters a context that violates it, it has no resolution path. It picks one (usually whichever path is easier on the current task) and silently drops the rule.

src/lib/analyzer.ts

The fix is to bake the exception into the rule. "Always write tests, unless the file is under 30 lines and has no logic." "Never use any, except in narrowing helpers where the next line refines it." The analyzer recognizes four exception shapes (unless, except, but if, when X then) and stops flagging the line once one is present.

4. The prohibition has no stated reason

A prohibition without a "Why:" gets followed in the obvious case and dropped in the edge case. "NEVER commit secrets" gets followed when there's a literal API key in a diff and skipped when the model encounters a config-shaped value it can't confidently classify. The reason matters because the model uses it to pattern-match against the situation in front of it.

src/lib/analyzer.ts

The fix: every DO NOT or NEVER line gets one short follow-up that names the constraint or the past incident. "NEVER commit secrets. Why: leaked Stripe key in March 2026." The analyzer scans 4 lines forward from the prohibition looking for one of seven tokens (because, why, reason, past, got burned, incident, happened, caused). One short sentence is enough.

5 and 6. The rule is duplicated or contradicts another rule

The last two skip causes are about coherence across the file. A rule duplicated with slightly different wording forces the model to pick which version applies. A rule that contradicts another rule has no resolution path. In both cases the model picks one and drops the other, and which one gets dropped is hard to predict from the prompt.

Featureleave the contradictionsreshape the file
Same rule appears in two sectionsDifferent wording for the 'same' rule. The model picks the weaker version.One canonical phrasing. Delete the copy. Analyzer's duplicate detector flags it.
Two rules that contradict each other'never use comments' and 'add comments to public APIs'. Model picks one per turn.Scope by context: 'no comments in business logic; document public exports'.
Same prohibition in different forms'don't use any' + 'avoid any' + 'never use any'. Three duplicates.Single rule with the why: 'NEVER use any. Why: it disables type narrowing.'
Aspiration plus concrete rule'Always write good code' + 'Functions under 40 lines'. The vague one shadows the concrete one.Delete the aspiration. Keep the concrete rule.

What this looks like on a real file

A 4,318-token CLAUDE.md from a TypeScript repo. The first run flags 19 findings, six of which are skip causes from the patterns above. The bytes are firing on every one of those lines, but the rules are not making it through.

ccmd · skip-cause findings

How to triage your file

Open your file and walk it once with these six patterns in mind. Most skip causes resolve in a single edit per line.

1

Search for the longest line

Find any line over 28 words and split it. The mechanical test: count words, if over 25 split, target 8 to 15 words per directive. Stack paragraphs, style paragraphs, and onboarding sentences are the usual culprits.

2

Grep for vague terms

Search the file for: appropriate, properly, carefully, thoughtfully, good, best, well, nicely, cleanly, as needed, where applicable, if relevant, when possible. Each hit is either replaced with a concrete rule or deleted.

3

Grep for absolutes without an exception

Search for: always, never, must, should always, in all cases, every time. For each hit, check whether the same line contains unless, except, but if, or when X then. If not, either add the exception or drop the absolute.

4

Add a Why to every prohibition

Find every line starting with DO NOT, NEVER, or don't. Add a one-sentence Why immediately after, naming the constraint or the past incident. The analyzer scans 4 lines forward looking for a reason token.

5

Dedupe and resolve contradictions

Two rules saying almost the same thing: delete the weaker one. Two rules contradicting each other: scope them by context, or pick one. Analyzer detects same-text duplicates automatically.

6

Re-run the analyzer

Paste the edited file back into ccmd.dev. The number of skip-cause findings drops to near zero. The same rules are now in shapes the model can act on.

Want a second pair of eyes on the rules getting skipped?

15 minutes, walk through your CLAUDE.md, leave with a marked-up file showing which rules are in shapes that survive and which need reshaping. Free.

Frequently asked questions

Why does Claude skip rules in my CLAUDE.md?

Firing is not the same as following. Every line of CLAUDE.md gets concatenated into the system prompt at session start and re-sent on every turn for the session (the analyzer codifies this at src/lib/analyzer.ts line 264 as estimatedTokensFireEveryTurn = totalTokens). So the bytes are always there. But six specific line shapes make a rule unfollowable even when the model reads it: lines over 28 words (the second half gets dropped), 14 vague words like 'appropriately' (no testable success condition), 6 absolutes like 'always' without an escape clause, prohibitions missing a 'Why:' that names the constraint, duplicates, and conflicting absolutes. Each one is detected per-line by ccmd's analyzer.

Doesn't Claude always read CLAUDE.md? People say it does.

Yes, it reads it. The file is in the system prompt for every turn. 'Read' is the wrong verb to anchor on. What matters is whether a specific rule survives the model's pass over the system prompt and ends up gating an action. A 38-word stack paragraph is in the prompt and is also functionally invisible because the model treats long sentences as one signal and the middle gets compressed away. The fix isn't to remove the rule. It's to reshape it so the model can't compress it.

Why does the bloat threshold sit at 28 words?

It's empirical. The constant lives at src/lib/analyzer.ts line 150. Rule lines over 25 words consistently get treated as one signal by the model, and the second half of the line tends to be dropped. 28 is the comfortable upper bound before the failure mode starts to dominate. Split a 34-word stack paragraph into three 8-word rules and the agent follows all three; leave it as one sentence and Claude follows the first half and silently skips the rest.

Why are 'always' and 'never' rules so easily skipped?

Real codebases have exceptions to almost every absolute. When the model reads 'always write clean code' and then encounters a one-line throwaway script where over-engineering would be wrong, it has no resolution path. It can't ask, so it picks one and moves on, often by silently dropping the rule. The analyzer's aspirational detector at line 177 fires when it sees one of six absolutes (always, never, must, should always, in all cases, every time) on a line under 25 words that doesn't contain an exception (unless, except, but if, when X then). Add the escape clause and the model has a procedure for resolving the edge case.

What does 'missing why' have to do with rules getting skipped?

Prohibitions without a stated reason get followed in the easy cases and dropped in the edge cases. The analyzer's missing_why detector at line 227 scans every line starting with DO NOT, NEVER, or don't, then looks at the next 4 lines for one of seven tokens (because, why, reason, past, got burned, incident, happened, caused). If none of them appear, the finding fires. 'NEVER commit secrets' alone gets followed in the obvious case (a literal API key in code) and skipped when the model sees a config-shaped secret that's already in an .env-like file. 'NEVER commit secrets. Why: leaked Stripe key in March 2026.' gets followed in both cases because the model can pattern-match against the named incident.

Are duplicate rules actually a problem?

Yes, in two ways. First, the duplicate burns tokens every turn (the analyzer's duplicate finding at line 207 sets tokenSavings to the full line, not a fraction). Second, duplicate rules create the false impression of redundancy without resolution: when the duplicates have slightly different wording, the model has to decide which version applies and frequently picks the weaker one. Single canonical phrasing wins.

How do conflicting rules cause skips?

The model has no resolution path. The analyzer ships one example at src/lib/analyzer.ts line 244: a file containing both 'never use comments' and 'add comments' triggers the conflict finding because there's no scoping logic to tell the model which rule applies when. In practice the model picks one rule per turn and silently drops the other. Either rule can be the one that gets skipped, depending on what else is in the prompt. Scope the rules ('never use comments in business logic; document public exports') or pick one.

What about position decay? Doesn't that also cause skips?

There's research suggesting attention is U-shaped over long contexts and rules in the middle get less weight. The analyzer doesn't detect this directly because it can't tell where the middle of your conversation will be. But you can hedge: put the rules that must survive every turn at the top or bottom of CLAUDE.md, not buried in the middle. The 'cache_bust' detector at line 193 indirectly addresses this by forcing volatile text (which mostly appears at the top) to move elsewhere.

If a rule keeps getting skipped, should I just delete it?

Sometimes. Aspirational lines with no escape clause and no concrete test fire, fail to resolve, and waste bytes. Delete or rewrite. But for rules that genuinely matter (security prohibitions, stack constraints, hard prohibitions with a named past incident) the fix isn't deletion. It's either reshaping the line (split, add 'Why:', add 'unless') or moving the rule to a different firing surface where it loads only when relevant (a skill .md, a settings.json hook, or an MCP tool description). The analyzer flags candidates; the user decides which lane.

How do I run this check on my own file?

Paste your CLAUDE.md, AGENTS.md, .cursorrules, or .grokrules into the textarea on ccmd.dev. The analyzer runs entirely in your browser, no upload, no signup. You'll see total tokens, the Karpathy 12-rule pass rate, and a line-by-line list of findings. The six skip-cause checks (bloat, vague, aspirational, missing_why, duplicate, conflict) cover most of the file shapes that cause silent rule skipping. Same detector across all four file formats; detection is by content, not filename.

How did this page land for you?

React to reveal totals

Comments ()

Leave a comment to see what others are saying.

Public and anonymous. No signup.