Your CLAUDE.md says, in plain imperative English, "Ask before adding a dependency." You open a fresh session, ask for a debounce on the search input, and get back a diff that installs lodash. The irritating part is that the assistant obviously read the file: it ran pnpm test without being told, and that line sits four rows below the dependency rule in the same file. So this is not an assistant ignoring CLAUDE.md in the sense of never loading it. It loaded it, used part of it, and dropped the part you cared about.

That distinction is the whole debugging exercise. "The file was never read" and "the file was read and lost an argument to something else" have different fixes, and most of the time it is the second one. Four causes cover nearly every case I have run into, and each has a narrow fix that takes about ten minutes.

When an assistant ignoring CLAUDE.md never loaded it at all

Before changing anything, rule out the boring failure. Start a session and ask it to list, verbatim, the rules from your instruction file that apply to the task you are about to give it. If it paraphrases vaguely or lists nothing, you have a loading problem: wrong filename, wrong directory, or an assistant that reads AGENTS.md while you have been editing CLAUDE.md. That is a five-second fix and worth eliminating before you rewrite 200 lines of prose.

If it quotes the rule back correctly and then violates it in the next message, keep reading.

The one rule that matters is buried on line 180

Instruction files grow by accretion. You add a line after each surprise, nothing ever gets deleted, and eighteen months later you have a 300-line document where the binding constraints are scattered between setup notes, a copy of your folder structure, three paragraphs about why the project exists, and a fact about a migration order that was true last March.

Everything in that file competes for the model's attention. A hard boundary written as the fourth bullet under "Notes" reads, structurally, exactly like a preference. What helps is not better wording but position and separation:

## Hard rules
- Never add a dependency without asking first.
- Never edit files under `generated/`.
- Never commit without running `pnpm test`.

## Commands
- Install: `pnpm install`
- Test: `pnpm test`

Short list, at the top, labelled as non-negotiable, nothing else in it. Five or six entries at most. If your hard-rules section has fifteen bullets, some of them are preferences and should be moved down.

The other half of this fix is removing what does not belong. Most bloated instruction files are half rules and half facts about the project's history, and the facts are what dilute the rules. Splitting them is covered in CLAUDE.md and project memory; the practical test is whether the line needs a date to make sense. If it does, it is memory, not an instruction.

Rules without the reason behind them

Compare two lines:

- Keep SQL portable.
- Keep SQL portable: the desktop build ships SQLite, the server runs Postgres,
  and the same queries run against both.

The first is a rule the assistant can only match literally. The second is a rule it can reason from, which means it also catches the cases you did not enumerate. With the reason attached, the assistant will flag a Postgres-specific JSON operator you never thought to forbid. Without it, it treats "portable" as a style preference and overrides it the moment a native function looks more efficient.

This is also why arbitrary-looking rules get broken most often. "Do not use the ORM's lazy loading" with no justification sits there looking like a leftover. Add "because the mobile client hits these endpoints on cold cache and the N+1 is measurable" and it becomes a constraint with teeth. You do not need a paragraph. One clause after a colon is enough, and it only has to go on rules where a competent developer would reasonably ask why.

An old decision quietly contradicting the new instruction

This is the one that wastes the most time, because nothing looks wrong. The instruction file says one thing. Something else in the repository says the opposite, and the assistant is reading both.

Typical shapes: the README still documents the npm workflow you abandoned for pnpm. A notes.md in the project root records "using the local Redis container for the queue while staging is down", with no date, so it reads as current policy nine months later. A nested CLAUDE.md in packages/api/ overrides the root file in that directory and nobody remembers writing it. A decision note says you chose approach A, and the instruction file, updated after you switched, says approach B.

Faced with two sources, an assistant tends to follow the one closest to the code it is editing, which is usually not your carefully maintained root file. So when a rule is being ignored, grep the repository for the opposite of the rule before you touch the rule itself:

grep -ril "redis" --include="*.md" .

Then fix the contradiction rather than restating the instruction more loudly. Dates and a status field prevent the recurrence: an entry marked Status: superseded by 2026-04-18 cannot be mistaken for a live constraint, which is most of the value of keeping lightweight decision records in the first place.

One instructions file, three assistants, three habits

If you use Claude Code in the morning and Codex in the afternoon, you have two files to keep honest. Claude Code reads CLAUDE.md, Codex and several other agents read AGENTS.md, and the usual outcome is that one of them is three weeks behind the other. You then spend an afternoon concluding that AGENTS.md rules are ignored when the rule in question simply was never copied across.

Keep one canonical file and make the other point at it, either with a symlink or with a one-line stub that says where the real content lives. Verify the stub is actually followed rather than assuming it, since behaviour differs between tools. The setup patterns are in running multiple assistants over one codebase.

There is a second layer here that is not a file problem. Different agents weigh instructions differently, and a rule that one follows reliably may need to be stated more explicitly for another. If a specific assistant keeps breaking a specific rule, write that rule in the negative and in the imperative for that file. "Never install a package. Propose it and wait" survives better than "dependencies should be discussed".

Make it quote the rule before it writes code

The quick test to run before trusting output again is the same one from the start of this piece, used as a habit rather than a diagnosis. At the beginning of any session where the rules matter:

Before writing code: list the rules from CLAUDE.md that apply to this task,
quote them verbatim, and tell me which files you plan to change.

You get three useful things out of it. Whether the file was loaded at all. Which rules the assistant considers relevant, which is often a narrower set than you expected. And the contradiction case, because a confused assistant will happily quote two conflicting lines without noticing they conflict.

When that happens, you want the contradicting note to be findable. We built PrjLab so instructions, project memory and the sessions you keep live in the same versioned repository as the code: when a rule stops being followed, you can open the version history and see the line diff for the moment that instruction changed, instead of reconstructing it from a chat log on another machine. The getting-started guide walks through the first push.

Most of the time, though, the fix is not tooling. It is a shorter hard-rules list, a reason attached to the rules that look arbitrary, and deleting the stale note that has been quietly arguing against you.