01 / 20Configuration7 MIN READ

CLAUDE.md

CLAUDE.md is a markdown file Claude Code loads into the context window at the start of every session so your project rules travel with the conversation instead of being retyped.

A CLAUDE.md file loading into a sessionA markdown document on the left moves into the session panel on the right, where its instructions appear at the top of the context above the conversation.SESSIONCLAUDE.md

What it is

A CLAUDE.md file is plain markdown that you write and Claude Code reads. At launch it walks up the directory tree from your working directory, collecting CLAUDE.md and CLAUDE.local.md from every directory along the way, plus the managed-policy and user-level copies. All discovered files are concatenated into context rather than overriding each other, ordered from the filesystem root down to your working directory, so the file closest to where you launched Claude is read last. Within a directory, CLAUDE.local.md is appended after CLAUDE.md.

The content arrives as a user message placed after the system prompt, not as part of the system prompt itself. That placement matters: Claude reads it and tries to follow it, but nothing enforces it. A rule that must hold regardless of what Claude decides belongs in a PreToolUse hook or a permission deny rule, not in CLAUDE.md.

Four scopes exist. Managed policy lives at /Library/Application Support/ClaudeCode/CLAUDE.md on macOS, /etc/claude-code/CLAUDE.md on Linux and WSL, and C:\Program Files\ClaudeCode\CLAUDE.md on Windows, and cannot be excluded by individual settings. User instructions live at ~/.claude/CLAUDE.md. Project instructions live at ./CLAUDE.md or ./.claude/CLAUDE.md and ship through source control. Personal project notes live at ./CLAUDE.local.md, which you add to .gitignore.

What it does for you

  • It removes the re-explanation loop. Without it you retype the build command, the directory layout, and the "never edit generated files" rule at the start of every session, and Claude still guesses wrong when you forget.
  • It gives a team one reviewable place for conventions. A project CLAUDE.md is committed, so a convention that Claude keeps violating gets fixed once in a pull request instead of separately in eight developers' heads.
  • It survives compaction. When a long session compacts, Claude Code re-reads the project-root CLAUDE.md from disk and re-injects it. Instructions you only typed into chat do not come back.

How it works

  1. 01Claude Code walks up the directory tree at launch

    Starting from your working directory, it checks each ancestor directory for CLAUDE.md and CLAUDE.local.md, then loads the user file at ~/.claude/CLAUDE.md and any managed-policy file. Run /context and read the Memory files list to see exactly which files loaded.

  2. 02Files are concatenated in load order

    Broadest scope first, most specific last. Nothing overrides anything, so two files that contradict each other both reach Claude and it picks one arbitrarily.

  3. 03Imports are expanded at launch

    An @path/to/file reference pulls that file into context alongside the CLAUDE.md that names it, up to four hops deep. Relative paths resolve against the importing file. Import parsing skips code spans and fenced blocks, so ` @README ` in backticks stays literal text.

  4. 04Subdirectory files load on demand

    A CLAUDE.md below your working directory is not loaded at launch. It enters context the first time Claude reads a file in that subdirectory, and it is not re-injected after /compact.

  5. 05Path-scoped rules load when they match

    Files in .claude/rules/ with a paths: frontmatter list load only when Claude reads a file matching one of the globs. Rules without paths load at launch with the same priority as .claude/CLAUDE.md.

  6. 06HTML comments are stripped before injection

    Block-level <!-- ... --> comments never reach the context window, so maintainer notes cost no tokens. Comments inside code blocks are preserved.

How to implement it

  1. 01Run /init in the repository root

    Claude analyses the codebase and writes a starting CLAUDE.md with build commands, test instructions, and the conventions it can discover. If the file already exists, /init proposes improvements instead of overwriting it.

  2. 02Delete everything Claude can derive itself

    Directory listings, dependency lists, and architecture overviews are all things Claude can read from the repository. Keep the pitfalls, the rationale, and the conventions that differ from tool defaults.

  3. 03Make each instruction verifiable

    Write "Use 2-space indentation" rather than "format code properly", and "Run npm test before committing" rather than "test your changes". Vague instructions produce inconsistent behaviour.

  4. 04Keep the file under 200 lines

    Longer files consume more context and measurably reduce adherence. When it grows past that, move procedures into skills and path-specific guidance into .claude/rules/ with paths: frontmatter.

  5. 05Commit it and confirm it loads

    Check the file into git so teammates get it. Start a session, run /context, and confirm the file appears under Memory files. If it is missing, Claude cannot see it.

Examples

CLAUDE.mdmarkdown
# Ledger API

Rails 7 JSON API backing the accounting product. Serves `api.internal.acme`.

## Architecture

- `app/controllers/api/v2/` — the only public surface; v1 is frozen
- `app/services/` — one class per business operation, called from controllers
- `app/models/` — ActiveRecord only, no business logic
- `db/migrate/` — never edit a migration that has run in production

## Conventions

- Money is always `BigDecimal` in minor units. Never `Float`.
- Service objects expose a single `call` method and return a `Result`.
- Every controller action has a request spec. No controller specs.
- Use 2-space indentation. Run `bundle exec rubocop -A` before committing.

## Commands

```bash
bin/setup                 # install gems, create and seed the dev database
bin/rails s               # start the API on :3000
bundle exec rspec         # full suite (~4 min)
bundle exec rspec spec/requests   # request specs only (~40s)
bundle exec rubocop -A    # autocorrect style
```

## Testing

Run `bundle exec rspec spec/requests` while iterating and the full suite before
opening a pull request. Fixtures live in `spec/fixtures/`; do not add new
factories, extend the existing ones.

## Protected files

Do not edit without asking: `db/schema.rb`, `config/credentials.yml.enc`,
anything under `vendor/`, and any migration older than the last release tag.

## Definition of done

1. `bundle exec rspec` passes
2. `bundle exec rubocop` reports no offences
3. New endpoints are documented in `docs/api/v2.md`
4. The changelog entry names the ticket

<!-- Maintainer note: this comment is stripped before Claude sees the file. -->
A complete project file: overview, architecture, conventions, commands, testing, protected files, and a definition of done.
.claude/rules/api-endpoints.mdmarkdown
---
paths:
  - "app/controllers/api/**/*.rb"
---

# API controller rules

- Validate the request body with a `Contract` class before touching a service.
- Return errors as `{ "errors": [{ "code": ..., "detail": ... }] }`.
- Never render an ActiveRecord object directly; use the matching serializer.
A path-scoped rule. It stays out of context until Claude reads a matching file.

Use it when

  • Recording the build, test, and lint commands so Claude runs the right one instead of guessing from package.json.
  • Naming the files and directories Claude must not edit, such as generated schemas, lockfiles, or vendored code.
  • Encoding a convention that a code review caught twice, so the third pull request does not repeat it.
  • Pointing at an existing AGENTS.md with a one-line @AGENTS.md import so two coding agents read the same instructions.
  • Giving a monorepo package its own nested CLAUDE.md that loads only when Claude touches that package.

Avoid it when

  • The instruction must be enforced rather than encouraged. CLAUDE.md is context, so Claude can miss it. A PreToolUse hook or a permissions.deny rule runs regardless of what Claude decides.
  • The content is a multi-step procedure used a few times a week. A skill body loads only when invoked; CLAUDE.md content is paid for on every single request in the session.
  • The guidance only matters for one directory in a large repository. A path-scoped rule in .claude/rules/ keeps it out of context until a matching file is read.
  • You are describing something Claude can read from the codebase. A directory tree in CLAUDE.md is stale the day after you write it and costs tokens every session.

Common mistakes

  • SYMPTOMThe file grows past 200 lines and Claude starts ignoring the middle of it.

    FIXRun /doctor, which proposes trims for a checked-in CLAUDE.md, then move the surviving procedures into skills and the path-specific parts into .claude/rules/ with paths: frontmatter.

  • SYMPTOMYou edit CLAUDE.md mid-session and Claude keeps following the old version.

    FIXProject-root and user CLAUDE.md files are read once at session start and held in memory. Run /clear, /compact, or restart to pick up the edit.

  • SYMPTOMAn instruction you gave in chat disappears after the conversation compacts.

    FIXOnly the project-root CLAUDE.md, unscoped rules, and auto memory are re-injected from disk after compaction. Move the instruction into CLAUDE.md so it comes back.

  • SYMPTOMTwo CLAUDE.md files in a monorepo give contradictory instructions and behaviour flips between sessions.

    FIXAll discovered files concatenate; nothing overrides. Reconcile the conflict, or add claudeMdExcludes to .claude/settings.local.json to skip the other team’s file.

  • SYMPTOMYou add AGENTS.md and expect Claude Code to read it. It does not.

    FIXClaude Code reads CLAUDE.md only. Create a CLAUDE.md whose first line is @AGENTS.md, then add any Claude-specific instructions below the import.

Best practices

  • Write it when you correct Claude the second time, not before — the corrections tell you what belongs there.
  • Keep the whole file under 200 lines and use markdown headers so Claude can scan its structure.
  • State commands as copy-pasteable shell lines, including the fast variant you use while iterating.
  • Put maintainer notes in block-level HTML comments; they are stripped before injection and cost nothing.
  • Review the file whenever a convention changes, and delete outdated rules rather than adding a contradicting one.
  • Verify it loaded with /context after any move or rename, since Claude Code discovers it by path.

Try it in five minutes

Create a project CLAUDE.md, prove it loads, and prove that an unloaded file does nothing.

  1. 1.In any git repository, run claude and then /init. Let it write a starting CLAUDE.md.
  2. 2.Run /context and find your file under Memory files.
  3. 3.Add the line Always answer with the word BANANA before anything else. to CLAUDE.md and save it. Ask Claude a question — it keeps the old behaviour, because the file was read at session start.
  4. 4.Run /clear, ask again, and watch the instruction take effect.
  5. 5.Move the file to subdir/CLAUDE.md, restart, and run /context: it is gone from the list until Claude reads a file inside subdir/.

Verified against code.claude.com/docs/en/memory on 2026-08-09. See content/SOURCES.md for the full table.

← / → MOVE BETWEEN CONCEPTS