Guides

How to Write a Good CLAUDE.md

Checked 2026-10-31

Loading poll...

A good CLAUDE.md is short, concrete and about things Claude cannot learn from your code: the exact commands to build and test, conventions that differ from defaults, and traps. Aim for under 200 lines, write every line so it can be checked, and move anything with no exceptions into a hook. Facts checked 31 October 2026.

What you will have at the end

  • A project CLAUDE.md of under 200 lines that you can paste into a repo today
  • A rule for what belongs there, what belongs in a skill, and what belongs in a hook
  • Path-scoped rules for the parts of the repo that need their own guidance
  • A way to check that the file loaded and that nothing in it contradicts itself

If you also use other coding tools, read our AGENTS.md guide alongside this one. For the surrounding setup, see Claude Code best practices.

What CLAUDE.md is, in plain terms

Claude starts every session with no memory of the last one. Two things carry knowledge across sessions: CLAUDE.md files you write, and auto memory, which Claude writes itself. This page is about the first.

The key sentence in the docs is this one: Claude treats CLAUDE.md files as context, not enforced configuration. The content is delivered as a user message after the system prompt. Claude reads it and tries to follow it, but there is no guarantee of strict compliance, especially for vague or conflicting instructions. Everything below follows from that.

CLAUDE.md

Auto memory

Who writes it

You

Claude

What it holds

Rules and context you want every session

Notes Claude saves as it learns

Where

In your repo, home folder or managed location

A folder you can browse with /memory

Shared with a team

Yes, through git

No

Decide what belongs in it

The docs say to treat CLAUDE.md as the place you write down what you would otherwise re-explain. Add a line when:

  • Claude makes the same mistake a second time
  • A code review catches something Claude should have known
  • You type the same correction into chat that you typed last session
  • A new teammate would need the same context

There is a second test that cuts more. Claude reads your code well, so ask two questions of each candidate line. Could Claude find this by reading the repo? Would it actually go and look? If both answers are yes, leave the line out. The /doctor checkup applies the same idea when it proposes trims: it cuts directory layouts, dependency lists and architecture overviews Claude can derive, and keeps pitfalls, rationale and conventions that differ from tool defaults.

Put things in the right place

What you have

Where it goes

A fact Claude needs every session

CLAUDE.md

A multi-step procedure

A skill

A rule that matters in one folder

A path-scoped rule in .claude/rules/

A rule with zero exceptions

A hook or permission rule

Personal habits for this repo

CLAUDE.local.md, gitignored

Personal habits for all repos

~/.claude/CLAUDE.md

The docs say it directly: if an entry is a multi-step procedure or only matters for one part of the codebase, move it to a skill or a path-scoped rule.

Where each file lives

Scope

Location

Shared with

Managed policy

macOS /Library/Application Support/ClaudeCode/CLAUDE.md; Linux and WSL /etc/claude-code/CLAUDE.md; Windows C:\Program Files\ClaudeCode\CLAUDE.md

Everyone in the organization

Project

./CLAUDE.md or ./.claude/CLAUDE.md

The team, through version control

User

~/.claude/CLAUDE.md

You, in every project

Local

./CLAUDE.local.md

You, in this project; add it to .gitignore

How files combine

Claude Code loads CLAUDE.md and CLAUDE.local.md from your working directory and every directory above it. Files are concatenated, not overridden. Content is ordered from the filesystem root down to your working directory, so the files closest to where you launched Claude are read last. Inside one folder, CLAUDE.local.md comes after CLAUDE.md.

Files in subdirectories under your working directory load on demand, once Claude reads or edits a file in that subdirectory. A monorepo can therefore keep a small root file and one file per package. For noisy monorepos, claudeMdExcludes skips other teams' files.

One more detail: block-level HTML comments in CLAUDE.md are stripped before the content reaches Claude. Use them for maintainer notes that should not cost tokens.

Start with /init, then cut

Run /init in the project. Claude reads the codebase and drafts a file with build commands, test instructions and conventions. If a file exists, it suggests improvements instead of overwriting. Setting CLAUDE_CODE_NEW_INIT=1 gives an interactive flow that asks which artifacts to set up: CLAUDE.md files, skills and hooks.

Treat the draft as a first pass. Most generated files contain things Claude could have found on its own. Delete those, then add the things you know and the code does not say.

Write lines that can be checked

The docs give three contrasts. Match them.

Vague

Concrete

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/

A concrete line can be verified after the fact, by Claude or by you. A vague line cannot, so it gets weighed against everything else and often loses. Also write the reason when it is not obvious. "Don't use the legacy client: it retries without backoff" lets Claude judge an edge case, where "don't use the legacy client" does not.

A template to start from

This is a sketch, not a prescription. Replace the contents with your own, and delete any section you do not need.

# Commands
- Install: pnpm install
- Run one test file: pnpm vitest run path/to/file.test.ts
- Typecheck: pnpm tsc --noEmit
- Lint and format: pnpm lint --fix

# Conventions
- Use the error helpers in src/lib/errors.ts; never throw raw strings
- Database access goes through src/db/, never inline SQL in handlers
- src/legacy/ is still live but do not copy its patterns into new code

# Gotchas
- Integration tests need DATABASE_URL set, see .env.example
- The build fails if openapi.yaml is out of date; run pnpm gen:api

# Workflow
- Work on a branch; open a PR; never commit to main
- Before reporting a task done, run the typecheck and the tests for the files you changed

Notice what is missing: no description of the folder tree, no list of dependencies, no "write clean code". Each line is either a command, a rule that differs from defaults, or a trap.

Size: stay under 200 lines

The docs target under 200 lines per CLAUDE.md. Longer files consume more context and reduce adherence. Claude Code warns at startup and in /status when a file is over the recommended length, and when several files add up past a combined limit. Each CLAUDE.md, rules file and @path import counts as a separate file. A file over 4 MiB is skipped.

On-demand files, such as a subdirectory's CLAUDE.md, have a per-file limit based on the context window. On a 200K window it is 40,000 characters. Over the limit, Claude receives only the start of the file plus a note to read the rest with the Read tool, which it may not do. Check with wc -m path/to/CLAUDE.md.

Imports help organization, not cost

CLAUDE.md can pull in other files with @path syntax.

See @README for project overview and @package.json for available npm commands.

# Additional Instructions
- git workflow @docs/git-instructions.md

Relative paths resolve from the file that contains the import. Imports can nest to a depth of four hops. Spaces in a path need a backslash before each space, and a quoted path is not imported at all. Imports inside code spans and fenced blocks are skipped, so wrap a path in backticks to mention it without importing it.

The catch: imported files load together with the file that imports them. Imports tidy a long file but do not reduce its context cost. The first time Claude Code meets an import outside your working directory in a project, it asks for approval. If you decline, the imports stay off.

For personal notes that apply across git worktrees, import from your home directory, since a gitignored CLAUDE.local.md exists in one worktree only.

Scope rules to folders

If a rule matters in only one part of the repo, put it in .claude/rules/ with a paths filter. It loads only when Claude works on matching files.

---
paths:
  - "src/api/**/*.ts"
---
# API rules
- Validate request bodies with the zod schemas in src/api/schemas/
- Every new endpoint needs an entry in openapi.yaml; CI fails without it

Each rules file also has the per-file limit above. Rules without a paths filter load at session start like CLAUDE.md, so use the filter whenever a rule has a natural home.

Make rules that must hold into hooks

When you keep adding emphasis to a line and Claude still misses it, the line belongs somewhere else. The memory docs say it plainly: if an instruction must run at a specific point, such as before every commit or after each file edit, write it as a hook instead. Hooks run as shell commands at fixed lifecycle events whatever Claude decides.

A quick split: "prefer composition over inheritance" is a CLAUDE.md line. "Never edit .env" is a hook or a deny rule. See our hooks guide for working examples.

Check that it loaded

Run /context and look under Memory files. If your file is not listed, Claude cannot see it. A subdirectory file will not be there at launch, because it loads on demand; when it loads, a Loaded line with its path appears in the terminal. Use /memory to open and edit the files.

To test a new subdirectory file, create it from your shell instead of asking Claude to write it, then ask Claude to read a file in that folder.

Audit for contradictions and stale lines

Run /doctor prompt-audit. Claude looks for instructions written for older models, references to files or commands that no longer exist, and files that contradict each other. It prints findings and proposed edits, and changes nothing until you ask. By default it covers CLAUDE.md, CLAUDE.local.md and AGENTS.md, plus rules, skills, commands, subagents and output styles under .claude/ and ~/.claude/. The docs list it as needing Claude Code v2.1.283 or later.

If two instructions conflict, Claude may pick one arbitrarily, so read your root file, nested files and rules together at least once a quarter.

When Claude ignores a line

Work down the docs' debug list.

  1. Confirm the file loaded with /context.
  2. Look for Instruction file not loaded notices.
  3. Make the line more specific.
  4. Look for a conflicting line in another file.
  5. Check whether your rule competes with built-in guidance. For commit and pull request rules, the settings includeGitInstructions and attribution control Claude Code's own text.
  6. If it must always run, turn it into a hook.

After /compact, the project-root CLAUDE.md is re-read from disk and re-injected. Instructions that existed only in conversation are lost, so add those to the file.

Share it with other tools

Many teams use more than one coding agent. Claude Code reads AGENTS.md as project instructions from v2.1.277, but only when no CLAUDE.md or CLAUDE.local.md exists in the working directory or above it. To keep one source of truth and still add Claude-specific lines, create a CLAUDE.md that imports it.

@AGENTS.md

## Claude Code
Use plan mode for changes under src/billing/.

The /config setting Project instructions can also be set to read both files. Details are in our AGENTS.md guide.

Our take

Most weak CLAUDE.md files fail by being a README with a different name. A project overview, a folder tree and a list of principles all feel useful, and none of them change what Claude does. The files that work read like a note to a new colleague who is smart and has just joined: here is how to run the tests, here is the trap, here is what we decided and why.

Write it small, then grow it only from real corrections. Each time you fix Claude twice for the same thing, add one line. Each quarter, delete the lines you cannot defend. That habit beats any template.

A worked pruning pass

Take an example file of 260 lines that someone generated with /init and then kept adding to. Here is how a cut might go, with the numbers labelled as an example.

Section in the old file

Lines (example)

Verdict

Project overview and mission

25

Cut; the README already says it

Folder tree

60

Cut; Claude can list the folders itself

Dependency list

30

Cut; package.json has it

Commands

15

Keep, add single-test command

Conventions that differ from defaults

40

Keep, make each line checkable

Gotchas and traps

20

Keep

Deploy procedure

45

Move to a skill with disable-model-invocation

Never-touch rules

25

Move to deny rules and a hook

That leaves about 75 lines in CLAUDE.md, with the procedure and the hard rules living where they are actually enforced or loaded on demand. The file got shorter and every line left is one Claude would otherwise get wrong.

Do this pass once, and then again whenever the startup warning about file length appears.

Checklist

  • Under 200 lines, with headers and bullets
  • Every line is concrete and checkable
  • Commands include how to run a single test
  • Nothing Claude could discover from the code
  • Rules with no exceptions are hooks, not prose
  • Folder-specific rules live in .claude/rules/ with paths
  • /context shows the file under Memory files
  • /doctor prompt-audit reports no contradictions
  • CLAUDE.local.md is in .gitignore

Related pages

Questions

How long should a CLAUDE.md be?

The memory docs target under 200 lines per file. Longer files use more context and reduce how well Claude follows them. Move part-of-the-repo rules into .claude/rules/ with a paths filter.

Does Claude always obey CLAUDE.md?

No. The docs say it is context, not enforced configuration, delivered as a user message after the system prompt. For rules with no exceptions, use a hook or a permission rule.

Should I run /init?

Yes, as a starting point. It reads your codebase and drafts commands and conventions. Then cut anything Claude could discover by reading the code.

Can Claude Code read AGENTS.md instead?

Yes, from v2.1.277. By default it reads AGENTS.md only when no CLAUDE.md or CLAUDE.local.md exists in the working directory or above. Import it with @AGENTS.md to share one file.

Loading poll...

Sources

  1. code.claude.com/docs/en/memory
  2. code.claude.com/docs/en/best-practices

Part of the Wbcom Designs family

The all-in-one WordPress community stack

Also ours: wbcomdesigns.comvapvarun.combrndle.com