learnaiwithrafa
ClaudeSetup

Why Claude Ignores Your CLAUDE.md

Your CLAUDE.md is not configuration — it is a user message Claude reads and tries to follow. That one fact explains every rule it keeps breaking, and it changes how you write the file.

5 min read2 sources
  • #claude-code
  • #claude-md
  • #context-engineering

Here is the detail almost nobody knows, and it explains the frustration completely: CLAUDE.md is delivered as a user message after the system prompt, not as part of it. Anthropic's own docs say so, and they are blunt about the consequence — Claude "reads it and tries to follow it, but there's no guarantee of strict compliance."

So when you write "NEVER push to main" in caps and Claude pushes to main, that is not a bug. You wrote a request into a document that is, by design, context — not enforcement. Every team I have seen struggle with Claude Code is fighting this one confusion.

Context vs. enforcement — pick the right layer

The docs draw a clean line that is worth memorizing, because it tells you which file a rule belongs in:

  • Behavioral guidance — code style, conventions, architecture, "prefer X over Y" → CLAUDE.md.
  • Technical enforcement — blocking a command, a path, a tool → permissions.deny in settings.json.
  • Must happen at a specific moment — before every commit, after each edit → a hook.

The docs put it plainly: settings rules "are enforced by the client regardless of what Claude decides to do." CLAUDE.md is not a hard enforcement layer. If a rule matters enough that violating it costs you money or data, it does not belong in CLAUDE.md at all.

The 200-line budget

CLAUDE.md loads into your context window at the start of every session, spending tokens before you type a word. The docs give a target: under 200 lines per file, because "longer files consume more context and reduce adherence."

That last clause is the interesting one. A longer CLAUDE.md is not just more expensive — it is less obeyed. Which inverts how most people write the file. The instinct is to document everything; the correct instinct is to fight for every line.

Two things that do not solve a bloated file:

  • @path imports. Great for organization, useless for context. Imported files are expanded and loaded at launch anyway (up to four hops deep). You have moved the tokens, not saved them.
  • Splitting into more CLAUDE.md files up the tree. All discovered files get concatenated, not overridden. You now have more context and more chances for two rules to contradict each other — and when they do, the docs warn Claude "may pick one arbitrarily."

What does work is .claude/rules/ with paths frontmatter. A rule scoped to src/api/**/*.ts only enters context when Claude actually touches an API file. That is real savings, not reorganization.

The template

Four sections, and a hard rule that every line must be verifiable:

# <project> — one line on what this is and who it's for

## Stack
Node 22 / pnpm 11 / Next.js 14 App Router / Postgres via Prisma.
Package manager is pnpm — never npm.

## Commands
- Test: `pnpm --filter web test`
- Lint: `pnpm lint`
- Migrate: `pnpm db:migrate`

## Layout
- `apps/web/` — Next.js frontend
- `packages/shared/` — zod schemas, the contract between apps
- `db/` — Prisma schema + migrations

## Conventions
- Import the shared client from `@repo/db`, never `@prisma/client` directly.
- 2-space indentation.
- Every new API route needs a zod schema in `packages/shared/`.

## Boundaries
- Do not touch `db/prisma/migrations/` without asking.
- Do not edit generated files (`*.gen.ts`).

The docs give the specificity test, and it is a good one: "Use 2-space indentation" beats "format code properly." "API handlers live in src/api/handlers/" beats "keep files organized." If a line cannot be checked, it will not be followed — and it is costing you tokens to be ignored.

The part that compounds

This is the habit that separates a CLAUDE.md that decays from one that gets sharper. The docs name the exact trigger: add to CLAUDE.md when Claude makes the same mistake a second time, when a code review catches something Claude should have known about this codebase, or when you type the same correction you typed last session.

Not the first mistake — the second. The first might be a one-off. The second is a missing line in your file.

My rule of thumb: when I correct Claude twice on the same thing, I stop and ask which of three files it belongs in. A fact about the repo? CLAUDE.md. A procedure with steps? A skill — the body only loads when used, so it costs nothing until you need it. Something that must never happen? A deny rule. Getting this routing right is most of what people mean by "Claude Code just works for them."

Worth knowing: Claude also keeps its own notes now. Auto memory writes to ~/.claude/projects/<project>/memory/, and only the first 200 lines or 25KB of its MEMORY.md index loads each session. It is plain markdown — go read what it has been saving about your repo. Mine had learned things about my build I never wrote down.

Do this today

Open your most active repo and run /context. Look under Memory files and confirm your CLAUDE.md actually loaded — if it is not in that list, Claude has never seen it, and you have been debugging a file that was never read. Then count the lines. Over 200, cut it. Then take the one rule you have written in caps and move it to permissions.deny, where it will actually hold.

Sources