Skip to content

How to Write a CLAUDE.md File That Actually Gets Followed

Most CLAUDE.md files are written once, bloat to 400 lines, and quietly stop working. The load order, the four scopes, and the categorical mistake underneath it: CLAUDE.md is context, not enforcement.

August 1, 202611 min readShift The Culture

A CLAUDE.md is the file Claude Code reads at the start of every session. Most of them are written once, grow to 400 lines of things the model could have worked out on its own, and then quietly stop being followed. This is how the loading actually works, what belongs in the file versus the three other places instructions can live, and the failure that catches almost everyone: CLAUDE.md is context, not enforcement.

What the file actually is

Every Claude Code session starts with an empty context window. CLAUDE.md is the plain-markdown file you write to carry knowledge across that gap — build commands, conventions, architecture, the rules you would otherwise retype every session. Claude Code reads it automatically at session start. There is no schema, no frontmatter requirement, no special syntax to learn. It is a markdown file in a known location.

The single most important thing to understand about it is documented plainly and ignored universally: the file's contents are delivered as a user message after the system prompt, not as part of the system prompt. Claude reads it and tries to follow it. There is no guarantee of strict compliance, and vague or conflicting instructions get followed least reliably of all.

CLAUDE.md shapes behaviour. It does not enforce it. Anything that genuinely must happen belongs in a hook, not in a paragraph asking nicely.

Where the file goes (and the load order)

There are four scopes, and they stack rather than override. Claude Code loads them from broadest to most specific, so more specific instructions land later in context:

  • Managed policy — organisation-wide, deployed by IT. On macOS /Library/Application Support/ClaudeCode/CLAUDE.md; on Linux and WSL /etc/claude-code/CLAUDE.md; on Windows C:\Program Files\ClaudeCode\CLAUDE.md. This one cannot be excluded by individual settings.
  • User~/.claude/CLAUDE.md. Your personal preferences across every project on the machine.
  • Project./CLAUDE.md or ./.claude/CLAUDE.md. Committed to source control, shared with the team.
  • Local./CLAUDE.local.md. Your personal project-specific notes. Add it to .gitignore.

Beyond the scopes, Claude Code walks up the directory tree from wherever you launched it, picking up a CLAUDE.md and CLAUDE.local.md in each directory along the way. Everything found is concatenated, ordered from the filesystem root down toward your working directory — so the file closest to where you started is read last. Within a single directory, CLAUDE.local.md is appended after CLAUDE.md.

Files in subdirectories below your working directory behave differently: they are not loaded at launch. They come in on demand, when Claude reads a file in that subdirectory. That is a useful property in a monorepo and a confusing one if you do not know about it, because a rule can appear to be ignored simply because nothing has pulled it into context yet.

What belongs in it — and what does not

The useful test is not “is this true about the project?” It is “would Claude get this wrong without being told?” Anything derivable from the codebase in a few tool calls is costing you context every session to restate.

Earns its place

  • Commands that are not guessable: the actual test invocation, the build with its flags, how to run one test file.
  • Conventions that differ from the tool's default — the package manager you use, the formatter settings, the commit format.
  • Pitfalls: the thing that looks safe and is not, the generated file nobody should hand-edit, the migration that must run first.
  • Rationale for decisions that look wrong from the outside, so they do not get “fixed.”
  • Hard prohibitions: what must never be touched, deleted, or committed.

Does not

  • Directory listings and file trees. Claude can list a directory.
  • Dependency inventories. That is what the lockfile is.
  • General programming advice — “write clean code,” “handle errors properly.” It scores as noise and dilutes the rules that matter.
  • Multi-step procedures used occasionally. Those belong in a skill, which loads on demand instead of every session.
  • Instructions that only matter for one part of the tree. Those belong in a path-scoped rule.

The documented size target is under 200 lines. That is not a hard limit — the file loads in full at any length — but longer files consume more context and reduce adherence. Recent versions ship a /doctor checkup that proposes trims for a checked-in CLAUDE.md, cutting the derivable content and keeping pitfalls, rationale and conventions.

Write rules a machine can check

The difference between an instruction that holds and one that evaporates is whether it is verifiable. Compare:

Vague vs verifiable
WEAK                                  STRONG
"Format code properly"          ->    "Use 2-space indentation"
"Test your changes"             ->    "Run `npm test` before committing"
"Keep files organized"          ->    "API handlers live in src/api/handlers/"
"Be careful with the database"  ->    "Never edit files in db/migrations/ that
                                       are already applied — add a new one"
"Write good commit messages"    ->    "Commits: <type>: <description>, types are
                                       feat|fix|refactor|docs|test|chore"

The second column survives a long session; the first does not. Use markdown headers and bullets to group them — structure is scanned the same way a human scans it, and organised sections beat dense paragraphs.

Generating the first draft

Do not start from a blank file. Run /init — Claude analyses the codebase and writes a starting CLAUDE.md with the build commands, test instructions and conventions it can discover. If a CLAUDE.md already exists, /init suggests improvements instead of overwriting it. Setting CLAUDE_CODE_NEW_INIT=1 switches on an interactive multi-phase flow that asks which artefacts to set up, explores with a subagent, asks follow-up questions, and shows you a reviewable proposal before writing anything.

Then do the part /init cannot: add what is not inferable. The generated file is a good description of your repository. It contains none of the things that live in your head — the pitfalls, the reasons, the prohibitions. That gap is the whole value of the file.

There is also a maintenance habit worth building. Add to CLAUDE.md when Claude makes the same mistake twice, when a review catches something it should have known, when you type the same correction you typed last session, or when a new teammate would need the same context. That trigger list keeps the file growing from real friction rather than from imagination.

Imports, and the thing people get wrong about them

CLAUDE.md supports @path/to/file imports. Relative paths resolve against the file containing the import, not your working directory. Imported files can import further files, to a maximum depth of four hops. Import parsing skips code spans and fenced blocks, so wrapping a path in backticks mentions it literally instead of importing it.

CLAUDE.md — imports
See @README for the project overview and @package.json for available commands.

# Additional Instructions
- git workflow @docs/git-instructions.md
- personal preferences @~/.claude/my-project-instructions.md

The misconception worth killing: imports do not save context. Imported files are expanded and loaded at launch alongside the file that references them. Splitting a 600-line CLAUDE.md into six imported files is an organisational improvement and a context no-op. If you want instructions that load only sometimes, you need path-scoped rules or skills, covered below.

One safety note: when a project-level import resolves outside your working directory, Claude Code shows a one-time approval dialog listing the files. That exists because a shared repository can commit an import pointing anywhere. Imports in your own user-scope files load without the dialog.

When to use `.claude/rules/` instead

For anything larger than a small project, the better structure is a short CLAUDE.md plus a .claude/rules/ directory of topic files. Markdown files there are discovered recursively, and rules without a paths field load at launch with the same priority as .claude/CLAUDE.md.

The payoff is path scoping. Add a paths field in YAML frontmatter and the rule only enters context when Claude touches matching files:

.claude/rules/api.md
---
paths:
  - "src/api/**/*.ts"
  - "src/**/*.{ts,tsx}"
---

# API rules

- Every endpoint validates input at the boundary
- Use the standard error envelope, never a bare throw
- Update the OpenAPI comment block in the same commit

User-level rules in ~/.claude/rules/ apply to every project and load before project rules, so project rules win on specificity. The directory supports symlinks, which is the clean way to share one maintained rule set across several repositories.

And the tier below that: if an instruction is a procedure you invoke occasionally rather than a fact that must always be true, it belongs in a skill, which loads only when relevant. Three tiers, three costs — always-on, path-triggered, on-demand. Most bloated CLAUDE.md files are simply the wrong tier.

AGENTS.md and CLAUDE.md together

Claude Code reads CLAUDE.md, not AGENTS.md. If your repository already maintains an AGENTS.md for other coding agents, the documented fix is a CLAUDE.md that imports it, so both tools read one source and you can append Claude-specific instructions underneath:

CLAUDE.md
@AGENTS.md

## Claude Code

Use plan mode for changes under src/billing/.

A symlink (ln -s AGENTS.md CLAUDE.md) also works if you have nothing Claude-specific to add — though on Windows that needs Administrator rights or Developer Mode, so prefer the import there. Either way, confirm it with /context afterwards.

The lesson that costs people the most

Sooner or later you will write a rule in CLAUDE.md, watch it get violated, and add capital letters. That never fixes it, because the problem is categorical: CLAUDE.md is context, and context influences a decision it does not control.

Three layers, in ascending order of hardness:

  1. CLAUDE.md and rules — behavioural guidance. Best for conventions, preferences, architecture, and the things you want considered.
  2. Hooks — shell commands that run at fixed lifecycle events and apply regardless of what Claude decides. A PreToolUse hook can block an action outright. If it must run before every commit or after every edit, this is the layer.
  3. Settings — technical enforcement by the client: permission denies for specific tools, commands or paths, sandbox isolation, environment configuration. Not negotiable by the model at all.

We learned this the expensive way running an agent fleet: rules that lived only in prose drifted within weeks, and the fix was moving hard facts into a single machine-readable file that other documents are required to defer to, plus hooks that inject it automatically. The prose then does what prose is good at — explaining why — and stops pretending to be a control system.

Auto memory is a separate system

Claude Code also keeps notes it writes itself: build commands it worked out, debugging insights, preferences it picked up from your corrections. That is auto memory, and it is distinct from CLAUDE.md — you write one, Claude writes the other. It lives at ~/.claude/projects/<project>/memory/, with a MEMORY.md index whose first 200 lines (or 25KB, whichever comes first) load into every session, plus topic files that are read on demand.

It is on by default, machine-local, and plain markdown you can read, edit or delete. Toggle it from /memory, or disable it per project with { "autoMemoryEnabled": false }in that project's settings. Worth auditing occasionally: a wrong fact Claude saved about your project will quietly influence every session until you delete it.

A starting template

Short, specific, and structured to be deleted from rather than added to. Adapt the sections; keep the discipline.

CLAUDE.md
# <Project name>

## What this is
One or two sentences. What the thing does and who it is for.

## Commands
- Install: pnpm install
- Dev: pnpm dev
- Test: pnpm test          (single file: pnpm test path/to/file)
- Lint + types: pnpm lint && pnpm typecheck
- Build: pnpm build        (must pass before any deploy)

## Conventions
- Package manager is pnpm. Never npm or yarn — the lockfile is authoritative.
- 2-space indentation, no semicolon changes; the formatter decides, do not argue with it.
- Commits: <type>: <description>. Types: feat|fix|refactor|docs|test|chore
- New route -> add it to the sitemap and to the nav, same commit.

## Layout that is not obvious
- src/lib/  shared logic, no framework imports
- src/app/  routes only; anything reusable moves to components/

## Do not
- Do not edit anything under generated/ — it is rebuilt by the codegen step.
- Do not add a dependency for something the standard library does.
- Do not commit to main. Branch first.

## Pitfalls
- The dev server caches the content registry; restart after adding an entry.
- Two config files look interchangeable and are not: X is build-time, Y is runtime.

<!-- Maintainer note: keep this under 200 lines. Procedures go in skills,
     path-specific rules go in .claude/rules/. -->

Those HTML comments are worth knowing about: block-level comments are stripped before the content reaches Claude's context, so you can leave notes for human maintainers without spending tokens on them.

When it is not being followed

  1. Run /context and check Memory files. Not listed means not loaded — a path problem, not a wording problem.
  2. Look for a contradiction across scopes. User, project, local and nested files all stack; two of them disagreeing produces arbitrary behaviour.
  3. Make the rule verifiable. If you could not write a test for it, the model cannot reliably comply with it.
  4. Cut the file down. Adherence falls as length rises; deleting three paragraphs of general advice often fixes a rule fifty lines away.
  5. If it must happen, stop writing prose. Convert it to a hook or a permission deny.

The short version

  • Generate the first draft with /init, then add only what is not inferable from the code.
  • Keep it under 200 lines. Verify what loaded with /context, not with hope.
  • Every rule should be checkable. Delete anything you could not write a test for.
  • Imports organise; they do not reduce context. Path-scoped rules and skills do.
  • Already have AGENTS.md? Import it from CLAUDE.md rather than maintaining two files.
  • Anything that must happen is a hook or a setting. CLAUDE.md is the layer that persuades.

If you are coming at this from the operations side rather than the engineering side, the non-developer's guide to Claude Code covers the setup and the safety rules without assuming a terminal background, and the MCP server rundown covers the other half of configuration — giving the model access to the systems your instructions are talking about.

SharePost on X
Free · 13 pages · no upsell inside

Get the Operator Field Kit — free

Six production prompts, the five-step operator setup, and nine rules from our own failure log.

  • 6 complete prompts — printed in full, not previews
  • The five-step setup, each step with a pass/fail test
  • 9 rules from the failure log that produced them

The kit, then the occasional operator note. One click unsubscribes and we never sell the address.

Keep reading