Why Claude Code Ignores Your CLAUDE.md, and How to Fix It

Either the file never loaded, or it loaded and lost out to something else. How to tell which in one command, then a fix for each cause: location, start folder, imports, path rules, memory, compaction, and the rules that need a hook instead.

7 min read

When Claude Code ignores your CLAUDE.md, one of two things has happened: the file never loaded, or it loaded and something else won. Run /context and look under Memory files. If your file is missing, the cause is where it is, where you started the session, or an import that did not resolve. If it is there, the cause is how the instruction is written, a conflicting file or memory note, or a long session that compacted it away. And if the rule is one that must never be broken, CLAUDE.md was the wrong tool: Anthropic’s memory documentation (opens in a new tab) says the file is delivered as a message after the system prompt, and Claude tries to follow it without any guarantee. That needs a hook or a permission rule.

First: did it load?

/context shows what is occupying the context window right now, by category, including each memory file that loaded. /memory lists the locations Claude Code looks in and opens any of them for editing. According to the configuration debugging guide (opens in a new tab), if /context confirms the file loaded but Claude still does not follow a rule, the problem is how the rule is written, not whether it arrived. Everything below is sorted by which of those two answers you got.

For files that load part-way through a session, an InstructionsLoaded hook fires each time a CLAUDE.md or rules file is loaded, and can log which one, when and why. It is the quickest way to see whether a subfolder’s file or a path rule ever arrived.

Not loaded: the file is in the wrong place

  • The locations are fixed: ~/.claude/CLAUDE.md for you, ./CLAUDE.md or ./.claude/CLAUDE.md for the project, ./CLAUDE.local.md for your private project notes, and a managed file your organisation may deploy. Use those names exactly as written.
  • ~/.claude.json is not a settings or instructions file. It holds app state; your user instructions go in ~/.claude/CLAUDE.md.
  • A file over 4 MiB is skipped outright. Long before that it stops working well, as below.
  • A setting can leave it out: a claudeMdExcludes glob in any settings layer, or Project instructions set to claude-md or managed-only in /config. Check both if one project behaves differently from the rest.

Not loaded: you started in the wrong folder

At launch, Claude Code reads CLAUDE.md files in the folder you started in and every folder above it. Files in folders below load only when Claude reads a file there with the Read tool; not at launch, and not when it writes or creates a file in that folder. So a session started one level above the project begins without the project’s rules. Start in the project. How the layers stack across several repositories, and what --add-dir does and does not bring, is covered in managing multiple projects with CLAUDE.md.

  • Subagents: the built-in Explore and Plan agents skip CLAUDE.md. A custom subagent loads it unless its definition sets omitClaudeMd; for anything critical, put the rule in the agent file itself.
  • AGENTS.md: by default Claude Code reads it only when there is no CLAUDE.md or CLAUDE.local.md in the folder or above. Adding a private CLAUDE.local.md to such a repository quietly stops your AGENTS.md loading. Import it with @AGENTS.md, or set Project instructions to claude-md-and-agents-md.

Imports that do not resolve

An @path line pulls another file in at launch. When the imported text is missing from the session, check these in order:

  1. Relative paths resolve from the file that contains the import, not from the folder you started in. @docs/rules.md in .claude/CLAUDE.md looks for .claude/docs/rules.md.
  2. An @path inside backticks or a code block is left as text on purpose. Take it out of the code span.
  3. Imports nest at most four hops deep.
  4. A project file importing something outside the working folder, such as @~/.claude/my-rules.md, triggers a one-time approval dialog. Decline it and those imports stay disabled, and the dialog does not come back.

An import that does work saves no context: the file is loaded in full, exactly as if it were pasted in. Splitting a long CLAUDE.md into imports tidies it without making it any lighter.

Loaded but ignored: how the rules are written

  • Too long. The documentation targets under 200 lines per file, and warns at startup and in /status when a file, or the files together, run over. The more there is, the less attention each line gets. /doctor proposes cuts: directory layouts, dependency lists and anything else Claude can read from the code.
  • Too vague. “Test your changes” cannot be checked; “run pnpm test before committing” can. Rewrite every rule until you could tell whether it was followed.
  • Contradictory. Files are joined together, not merged, and nothing overrides anything. If your user file says npm and the project says pnpm, Claude may follow either. On recent versions, /doctor prompt-audit reads all your instruction files and reports conflicts and references to files that no longer exist.
  • Buried. A critical rule on line 140, under a heading about something else, is the easiest one to miss. Move it up, and use emphasis such as IMPORTANT for one rule, not twenty.
  • Competing with built-in guidance. If your file sets commit or pull request rules, Claude Code’s own git instructions may pull the other way; the includeGitInstructions and attribution settings turn those off or change them.

What a file looks like once those are fixed, line by line, is in CLAUDE.md examples.

Rules files that never fire

A Markdown file in .claude/rules/ with no frontmatter loads at launch like CLAUDE.md. Give it a paths list and it loads only when Claude reads a file matching one of the globs, which is exactly why it can seem to be ignored:

.claude/rules/api.md
---
paths:
  - "src/api/**/*.ts"
---
- Every handler validates its input with the schema in src/api/schemas/.
- Errors use the ApiError shape. Never return a bare string.
  • It triggers on reading a matching file. A session that only creates a new handler, without reading an existing one, may never load it.
  • paths is the only field a rule reads. Any other field is ignored silently.
  • If the YAML does not parse, the frontmatter is ignored and the rule loads for everything, as if it had no paths. claude --debug shows the parse error.
  • A glob with a stray [ is invalid and matches nothing. Escape a literal bracket as \[.

Memory saying something different

Auto memory loads every session too: the first 200 lines or 25KB of MEMORY.md in ~/.claude/projects/<project>/memory/. Claude skips saving what your CLAUDE.md already says, but a note written before you added the rule, or from a correction you gave months ago, can still contradict it, and Claude treats both as context. Open the folder from /memory and delete or fix the stale note. Also check where your corrections are going: “remember to use pnpm” is saved to auto memory, while “add this to CLAUDE.md” edits the file. What auto memory keeps and how to prune it is in Claude Code memory.

It worked, then stopped: compaction

Long sessions are summarised to free space. The context window guide (opens in a new tab) lists what survives: the project-root CLAUDE.md, rules without paths and auto memory are re-read from disk; nested CLAUDE.md files and path-scoped rules come back only when Claude next reads a matching file; anything you said only in chat is summarised with everything else. So a rule that holds for an hour and then fades is usually one of the latter kinds. Move it to the root file or an unscoped rule, or use a SessionStart hook matched on compact to put it back after every compaction. Context engineering for Claude Code covers the rest of what compaction keeps.

When a rule must never be skipped

Some rules are not guidance: never edit .env, never use npm in a pnpm repository, never push. No wording makes CLAUDE.md enforce them. Permission deny rules and hooks do, because they run whatever Claude decides. The hooks guide (opens in a new tab) shows the pattern: a PreToolUse hook that exits with code 2 blocks the tool call and hands its message back to Claude, which then adjusts.

.claude/settings.json
{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Bash",
        "hooks": [
          { "type": "command", "command": "\"$CLAUDE_PROJECT_DIR\"/.claude/hooks/no-npm.sh" }
        ]
      }
    ]
  }
}
.claude/hooks/no-npm.sh
#!/bin/bash
CMD=$(jq -r '.tool_input.command // empty')
RE='(^|[;&|[:space:]])npm([[:space:]]|$)'
if [[ "$CMD" =~ $RE ]]; then
  echo "Blocked: this repository uses pnpm. Run the pnpm equivalent." >&2
  exit 2
fi
exit 0

Keep the CLAUDE.md line as well, so Claude gets it right first time and the hook is only the backstop. Make the script executable on macOS and Linux (it needs jq), and check it is registered with /hooks. The regular expression catches npm at the start of a command or after && or ;, but not pnpm or npx.

The line people most often want enforced

A common skipped instruction is some form of “update the board before you stop”. It is exactly the kind of rule that drifts after compaction and gets missed at the end of a long task. With fenbs connected over MCP, keep the instruction short in CLAUDE.md and add a Stop hook that reminds Claude when there is unrecorded work, as in Claude Code hooks that update a board. The board then shows whether it happened: every change an assistant makes is recorded in the history under its name, so a missing update is visible the same day rather than discovered later.

Related

Where each file belongs in a repository: Claude Code project structure. Custom commands for procedures that do not belong in CLAUDE.md at all: Claude Code custom commands. Connect the board: Claude Code integration.

Questions people ask.

How do I know if Claude Code loaded my CLAUDE.md?

Run /context in the session and look under Memory files. If the file is not listed, Claude cannot see it. /memory shows the locations Claude Code checks and opens each file for editing.

Why does Claude follow CLAUDE.md at first and then stop?

Usually compaction. The project-root CLAUDE.md is re-read after a long session is summarised, but nested CLAUDE.md files and path-scoped rules return only when Claude next reads a matching file, and instructions given only in chat are summarised away.

Why is my subfolder CLAUDE.md ignored?

Files in folders below where you started load only when Claude reads a file in that folder with the Read tool, not at launch and not when it creates a file there. Start the session in that folder, or move the rule up.

Can I make a CLAUDE.md rule mandatory?

No. CLAUDE.md is context that Claude tries to follow. For a rule that must always hold, add a permission deny rule or a PreToolUse hook, which runs every time and can block the action.

Start with one thing.

There is nothing to set up first. Write one line and you’ve started.