Skip to content

CLAUDE.md Guide: Coding Project Rules into its Memory

📚 Series Navigation: The previous article 17 Images and Multimodal taught you how to feed screenshots and error images directly to Claude. This article shifts direction—coding the project's "rules" into its memory all at once, so it automatically follows them every time it starts working, without you having to repeat yourself daily.

Everyone says the more detailed CLAUDE.md is, the better. But truth be told, the most useless CLAUDE.md is exactly the one with three hundred lines that Claude ignores completely.

Imagine a CLAUDE.md left by a predecessor in a project you just took over, sprawling with: company background, product vision, team introductions, the ins and outs of technology choices... You scroll to the second screen before seeing a useful "use pnpm, not npm". The result? Claude still frequently does npm install on you.

The problem is not that it's disobedient, but that the rule is buried in two hundred lines of nonsense, and its attention has long been diluted.

CLAUDE.md (Claude's project memory file) is an artifact if written well, but a burden if written poorly—it occupies your context window every session. The more bloated it is, the less space there is for actual work. Today we will break this down: how many layers it has, what should be written, what shouldn't be written, how to reference other files, and how to keep it concise.

After reading this article, you will get:

  • What each of the three CLAUDE.md layers (user level / project level / subdirectory level) manages, and how their loading order is arranged
  • A "should write vs. shouldn't write" checklist, avoiding 90% of the pitfalls beginners face by stuffing nonsense into it
  • The correct posture for using the @ syntax to reference other files, and its true cost to the context
  • The official way to temporarily add a memory rule during a session, plus a "good vs. bad" comparison table to use as a template

ℹ️ This article focuses only on how to write and maintain the single CLAUDE.md file well. The /init one-click generation gameplay was covered in 12 "Project Initialization", and the broader auto-memory mechanism is saved for a dedicated discussion in 25 "Memory System".


01 Understand First: What Exactly is CLAUDE.md

Conclusion first: CLAUDE.md is a "persistent instruction" you write to Claude, which it reads first every time a session opens, treating it as project background loaded into its brain.

Why do we need it? Because every Claude Code session starts from a blank slate—the painstaking instructions from last time ("use pnpm, don't touch the legacy directory, run tests this way") are completely forgotten this time. Without CLAUDE.md, you have to explain it again every time. Isn't that annoying?

Analogy: An onboarding manual for a new employee. On a newcomer's first day, you won't stand next to them orally dictating rules all day. You give them a manual: what the project does, how code is committed, which minefields to avoid. They read it once and get to work. CLAUDE.md is Claude's onboarding manual—and the kind it rereads every day before starting work.

But there is a key understanding here, which the official documentation states very straightforwardly:

CLAUDE.md contents are passed as user messages after the system prompt, rather than being part of the system prompt itself. Claude reads it and attempts to follow it, but there is no strict guarantee of compliance.

Translated to human language: CLAUDE.md is a "strong recommendation", not an "iron law". It shapes Claude's behavior, but it's not a hard enforcement layer. So the more specific and concise you write it, the more stably it follows it. Expecting it to 100% block a dangerous operation? That's a job for Hooks, not a job for CLAUDE.md—the division of labor between these two will be discussed in later chapters.

When should you add content to it? The official guide gives several very practical signals:

  • Claude makes the same mistake a second time — this indicates the rule should be written down and solidified
  • You type the exact same correction you typed in a previous session again in this session
  • During code review, you find that it should have already known a certain convention of this codebase
  • New teammates need the same background to quickly get up to speed

💡 One-sentence summary: CLAUDE.md is the onboarding manual Claude must read every time it starts working, "strong recommendation" level rather than "iron law" level; the more specific it is written, the more effective it is.


02 Three Layers: Who Manages the Global Scope, Who Manages the Single Project

There is more than one CLAUDE.md; it can be placed in several locations, with its scope ranging from large to small. Beginners are most likely to get confused here, let's clear it up once and for all.

According to the official documentation, the commonly used ones are these three layers (plus one local variant):

LayerWhere to place itScope ManagedEnters git?
User level~/.claude/CLAUDE.mdAll projects on this machine of yoursNo, purely personal preference
Project level./CLAUDE.md or ./.claude/CLAUDE.mdThis current project✅ Yes, team shared
Subdirectory levelAny Subdirectory/CLAUDE.mdLoaded only when Claude reads files in that directory✅ Yes, suitable for multi-module repositories
Local level (Variant)./CLAUDE.local.mdCurrent project, only for yourself❌ Add to .gitignore

There is also a "managed policy layer", deployed by IT administrators to system directories (/Library/Application Support/ClaudeCode/CLAUDE.md on macOS), which is loaded before the user level and cannot be excluded by individuals. Individual users usually don't encounter this; refer to official docs for enterprise scenarios, this article omits it.

How to divide the labor? Remember one sentence: Put personal habits in the user level, team rules in the project level.

  • User level (~/.claude/CLAUDE.md): Put cross-project general personal preferences. For example, "Reply in Chinese", "Explain your thought process before modifying code, don't just jump in", "Use English for commit messages". These have nothing to do with specific projects, they are "your" habits as a person, so they apply to all projects and do not enter any project's git.
  • Project level (./CLAUDE.md): Put rules exclusive to this project, and which the whole team should follow. Tech stack, build commands, directory conventions, do-not-modify lists. It goes into version control with the code, so when new colleagues clone it, it comes with this set of specifications.
  • Subdirectory level: Only useful for large repositories. For example, a frontend directory has a frontend-exclusive one, a backend directory has a backend-exclusive one. It is normally not loaded; only when Claude actually goes to read files in that directory, does it conveniently bring that CLAUDE.md along—saving context.

The analogy is still the onboarding manual: User level = your personal work habit notebook (you take it with you when you change companies); Project level = the employee manual issued by this company (you return it when you leave); Subdirectory level = additional details within a certain department (only issued to you if you transfer to that department).

Take a common user-level configuration: in ~/.claude/CLAUDE.md, put a sentence "When encountering multiple implementation options, list the options for me to choose, rather than silently deciding for me". This holds true for every project of yours, so putting it in the user level is the easiest—once configured, you never have to repeat this sentence in a new project.

💡 One-sentence summary: Write personal habits in the user level (~/.claude/CLAUDE.md), team rules in the project level (./CLAUDE.md goes into git), and use the subdirectory level to split by modules for large repositories.


03 Loading Order: Why the Project Level "Speaks Last and Has More Authority"

The previous section listed three layers, so when they exist at the same time, who has the final say? This is another frequent misunderstanding that must be clarified.

The official rule: Loaded sequentially from the broadest scope to the most specific scope; the closer an instruction is to your launch directory, the later it is read.

How exactly is it ordered? Claude Code goes all the way up from your current directory, collecting CLAUDE.md at each layer along the way, and finally splices it into one complete context. The order is roughly:

text
User level ~/.claude/CLAUDE.md
        ↓ (Read first)
(Higher up in the directory tree) Parent directory CLAUDE.md

Project root ./CLAUDE.md
        ↓ (Read later, closest to you)
Subdirectory CLAUDE.md (Only added when Claude reads files in that directory)

Note two key points, both from the official documentation:

First, all found files are "spliced", not "overwritten". They all enter the context, it's not that the later ones replace the earlier ones. So the user level and project level take effect simultaneously; there is no such thing as "if project level is set, user level becomes invalid".

Second, instructions closer to the working directory are "read last". When two rules conflict—for example, user level says "use single quotes for strings", project level says "use double quotes"—the closer project level usually prevails because it speaks later. To put it plainly, project rules can override your personal habits, which is exactly the effect desired for team collaboration.

CLAUDE.md Three Layers Loading: Splicing Not Overwriting

This image stacks the three layers from top to bottom: User level (manages all projects, read first), Project level (current project, enters git), Subdirectory level (closest to code, prevails in conflicts); the arrow on the right indicates the "top-down" loading order, and the iron rule at the bottom points out—the three layers are spliced, not overwritten; the closer to the code, the later it is read and has the final say.

Here we must also correct a common erroneous statement. Many tutorials online write the priority as "Project Local → Project Root → Subdirectory → Global", which is the opposite of the loading direction described by the official documentation. It's easy to be led astray by this kind of statement, but flipping through the official docs makes it clear: the official explicitly says it is loaded "from the broadest scope to the most specific scope", with project instructions appearing after user instructions. Follow the official word, don't remember it backwards.

There is also a considerate detail: The CLAUDE.md in the project root will be automatically re-read from disk after /compact (compact conversation), it won't be lost. But those nested CLAUDE.md in subdirectories won't be automatically re-injected; you have to wait for Claude to read files in that directory next time for them to come back. So try to put important rules in the project root, don't bury them too deep.

💡 One-sentence summary: Multi-layer CLAUDE.md is spliced, not overwritten; the closer to the working directory, the later it is read, and the more it prevails in conflicts, so project rules can override personal habits—don't remember the official loading direction backwards.


04 What Should Be Written vs. What Shouldn't Be Written

This section is the lifeline of the whole article. If CLAUDE.md is not written well, nine times out of ten it falls into the trap of "what should be written isn't clear, what shouldn't be written is stuffed in a bunch".

First, let's talk about what should be written—the official word points it out clearly: write "facts that Claude should maintain in every session". Translated into a checklist, it's these five categories:

CategoryWhat exactly to writeExample
Project OverviewSummarize what this project is in one sentence"FastAPI-based order management backend"
Tech StackLanguage, framework, database, key tools"Python 3.11 / PostgreSQL / pytest"
Common CommandsHow to run tests, build, and checksuv run pytest, uv run ruff check .
Coding ConventionsStyle, naming, syntax that must be followed"Functions must have type annotations", "Use double quotes for strings"
Explicit "Do Not"sMinefields, do-not-modify files, operations that must ask first"Modifying existing files in migrations/ is prohibited"

Among them, common commands are the most frequently referenced—Claude will come here to look up commands before running tests or building, saving it from blind guessing or using the wrong ones. The prohibition list is the guardrail preventing it from being "smart but causing trouble": which directories are legacy code and strictly read-only, which file must it tell you before modifying, which secret files are forbidden from outputting content.

Next, let's talk about what shouldn't be written, which is the real disaster area for beginners:

  • Lengthy backgrounds: Company introduction, product vision, historical origins of tech choices—Claude can't use them to write code, it just takes up context.
  • Outdated information: Switched package managers but didn't update CLAUDE.md, it still says npm inside, misleading it as a result.
  • Things obvious from reading the code: Don't repeat what each file in the directory structure does, don't re-copy the code style already defined by ESLint config. Claude will read the code itself; repeating it is a waste of space.

The official attitude on this matter is very clear, specifically giving size red lines:

Each CLAUDE.md file targets under 200 lines. Longer files consume more context and reduce adherence.

Why is 200 lines so critical? Because CLAUDE.md fights for the same context window with your conversation. If you stuff three hundred lines of nonsense in it, it's equivalent to taking up a large chunk of the workbench right at the start, and the space left for actual tasks shrinks—moreover, important rules get drowned in the nonsense, attention is diluted, and adherence drops instead of rising. This is the root cause of the "three hundred lines nobody listens to" mentioned at the beginning.

There's a handy, simple method: Before writing every rule, ask yourself "Can Claude figure this out on its own by looking at the code? If yes, delete it". Just relying on this single slash can cut a CLAUDE.md in a taken-over project from over three hundred lines down to eighty, leaving only the hard constraints it can't figure out—after cutting, the number of times it uses the wrong package manager visibly decreases.

💡 One-sentence summary: Write "facts that should be remembered in every session" (overview / tech stack / commands / conventions / restricted areas), delete everything Claude can figure out on its own by looking at the code, and keep the full text under 200 lines.


05 Referencing Other Files: The @ Syntax and Its Cost

Sometimes you already have existing specification documents in your project—an API design guide, a database convention. There is no need to copy the content into CLAUDE.md; just use the @ syntax to reference it.

The syntax is very simple, write @ plus the path anywhere in CLAUDE.md:

text
For the project overview, please refer to @README; available commands can be found in @package.json.

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

When Claude reads CLAUDE.md, it will expand the contents of these referenced files and load them into the context together. A few details clarified by the official docs; keep them in mind to avoid pitfalls:

  • Relative paths are resolved relative to the "file containing the reference", not relative to your working directory. This is easy to get wrong.
  • Absolute paths work too; referenced files can also reference other files, recursively up to four hops.
  • The first time it encounters a reference outside the project, Claude Code will pop up an approval dialog listing these files for you to confirm; if you reject it, this reference will be permanently disabled, and the dialog won't pop up again.

But here is the most crucial understanding, repeatedly emphasized officially, and also the easiest pitfall to step into:

Imported files are expanded and loaded into context on startup. Splitting into @path imports helps with organization, but does not reduce context because imported files are loaded on startup.

To put it plainly: @ references are for "organization", not "saving money". Many people think that by splitting content into external files, the CLAUDE.md body becomes shorter, and context is saved—wrong. The referenced files are still fully loaded into the window at the start, and the context consumed is not reduced one bit. Imagine splitting a five-hundred-line specification out using @ references, thinking it slimmed down, but checking with /context (viewing context usage), every token that should have been consumed is still consumed.

So the principle is: @ references are used to make the structure cleaner and easier for humans to maintain, but to save context, you have to rely on "streamlining content" or "path scope rules", not splitting files. And the single file referenced shouldn't be too large either; if it's too large, it will still drag you down.

Incidentally, mentioning a related point: If you have some purely personal project preferences that you don't want to go into git (like your local sandbox URL, favorite test data), don't write them into ./CLAUDE.md, write them into ./CLAUDE.local.md, and then add it to .gitignore. It is loaded together with CLAUDE.md and processed in exactly the same way, except it won't be committed and won't affect teammates.

💡 One-sentence summary: Bringing in external documents via @path is for a "clean structure", but the referenced content is still fully loaded into context and doesn't save tokens; if you want to save, you must actually delete content; put private preferences in CLAUDE.local.md and gitignore it.


06 Maintenance: Casually Add in Session, Trim Regularly

CLAUDE.md is not something you write once and enshrine; it has to grow with the project. This section discusses two maintenance actions: how to casually add a rule, and how to slim down regularly.

What to Do When You Think of Adding a Rule Temporarily During a Session

It often happens like this: while chatting, you correct Claude on a point and think "this rule should be followed every time from now on, it needs to be written down". The most convenient official method—just tell it directly in the conversation:

text
Add the rule "Database operations must go through the Service layer, don't write SQL directly in routes" to CLAUDE.md

Claude will help you write this rule into the CLAUDE.md file. You can also type the /memory command at any time; it will list all CLAUDE.md, CLAUDE.local.md, and rule files loaded in the current session, click one and it will open in the editor, manually editing works too. If you want Claude to decide how to phrase it itself, use the first method; if you want precise control over the phrasing, use /memory to edit it yourself.

ℹ️ A version difference reminder: In early Claude Code, typing a sentence starting with # in the input box could quickly append memory. In new versions, this interaction has changed—follow the current official method: either tell Claude directly to "add to CLAUDE.md", or use /memory to edit it yourself. If you just type "remember xxx", Claude will likely save it by default to its own auto-memory (that's a topic for 25 "Memory System"); if you explicitly want it in CLAUDE.md, say the full phrase "add to CLAUDE.md".

Trim Regularly, Delete Outdated and Conflicting Rules

A hidden danger called out officially: When two rules conflict, Claude might just pick one at random to follow. So you must regularly look back and clear out outdated and conflicting ones. The timing to trigger trimming:

  • Changed package manager / build tool (old commands must be deleted, keeping them is misleading)
  • Added or removed important dependencies
  • Set new coding conventions (conveniently check if they conflict with old rules)
  • Discovered CLAUDE.md has quietly grown past 200 lines again

To judge whether a rule is good or bad, just see if it looks like a "rule" rather than "prose". The official comparison is particularly practical, I've compiled it into a table:

❌ Vague Prose (Useless)✅ Specific Rule (Effective)
Code should be relatively cleanFunctions cannot exceed 50 lines; if they do, they must be split
Try to write testsEvery newly added function must have a corresponding unit test
Pay attention to securityUser input must pass through sanitize() before entering database queries
The legacy directory is not very importantModifying any file in the legacy/ directory is prohibited
Using pnpm is betterDependency management only uses pnpm; npm and yarn are disabled

The kind on the left is as good as unsaid—"clean", "try to", "pay attention" are all subjective words; Claude has no way to verify them, and naturally has no way to execute them stably. Every rule on the right is specific enough to be verified: 50 lines, must have tests, must pass a certain function. The official exact wording is "write instructions specific enough to be verifiable".

When writing CLAUDE.md, you might as well develop a hard habit: After writing each rule, act as a referee yourself and judge "can this rule be determined at a glance whether it's violated or not". If it can't be judged, it's written too vaguely; go back and make it specific.

💡 One-sentence summary: To casually add a rule, just tell Claude to "add to CLAUDE.md" or edit with /memory; regularly delete outdated and conflicting rules; good rules look like "verifiable at a glance rules", not prose like "clean, try to".


07 Hands-on: Equip a Toy Project with a Qualified CLAUDE.md

Talking without practicing is useless. Below, let's use a minimal project and walk through the complete process of "create file → write rules → verify loading". Follow along and type, it takes five minutes.

Step 1: Create a toy project and initialize git (Mac / Linux)

bash
mkdir claude-md-demo
cd claude-md-demo
git init
echo 'def add(a, b):
    return a + b' > main.py

Expectation: The claude-md-demo directory has a main.py and a .git directory. Git initialization is to allow this CLAUDE.md to enter version control (the prerequisite for team sharing).

Step 2: Hand-write a concise project-level CLAUDE.md

Use your preferred editor to create a new CLAUDE.md in the project root directory, and paste in this copy (note it only has a few lines in total—this is what a good CLAUDE.md should look like):

markdown
# add-demo — A minimal Python project for demonstration

Only has one `add` function, used to demonstrate how to write CLAUDE.md.

## Common Commands
- `python -m pytest` —— Run tests

## Coding Conventions
- All functions must have type annotations
- Strings must always use double quotes

## Notes
- Do not modify the function signature of `add` in `main.py`, you can only add logic inside

Expectation: CLAUDE.md appears under the project root directory, its content being just the sections above. The full text is less than 15 lines—remember this sense of length, don't let it spiral out of control in real projects.

Step 3: Launch Claude, verify it actually read it

Launch in the project directory:

bash
claude

After launching, type this command to confirm the loading status:

text
/memory

Expectation: You can see the ./CLAUDE.md you just wrote in the list. As long as it's in the list, it means Claude did load it into the context for this session. This step is the officially recommended troubleshooting method—if a certain rule is not followed, the first thing to do is use /memory to see if the file was actually loaded.

Step 4: Have it do a task that "steps on conventions", to see if it follows the rules

Exit /memory back to the input box, type:

text
Add type annotations to the add function

Expectation: In the diff provided by Claude, type annotations use the project's agreed-upon syntax, and it won't touch parts outside the function signature that it's forbidden to modify. If it obediently modifies according to the "functions must have type annotations" in your CLAUDE.md—congratulations, this onboarding manual took effect.

⚠️ In case you find it didn't follow CLAUDE.md: First, use /memory to confirm the file is loaded; then check if that rule is written too vaguely (like "clean"); finally, see if there are two rules fighting each other. These three steps are the standard troubleshooting sequence given officially; following them basically pinpoints the issue.

💡 One-sentence summary: Walk through the process of "create file → write concise rules under 15 lines → /memory to confirm loading → have it work to verify rule adherence", if it doesn't take effect, troubleshoot according to the official sequence: /memory → check for vagueness → check for conflict.


08 Summary

In this article, you have thoroughly figured out CLAUDE.md, this "Claude's project memory", from start to finish:

DimensionKey Conclusion
What is itThe onboarding manual read in every session, "strong recommendation" level, not iron law
How many layersUser level (personal) / Project level (team in git) / Subdirectory level (on demand)
Loading orderSplicing not overwriting, closer means read later, prevails in conflicts
What to writeOverview / tech stack / commands / conventions / restricted areas, delete anything code can self-prove
@ ReferenceUsed for structuring, doesn't save context (still fully loaded)
MaintenanceLet Claude "add to CLAUDE.md" or edit with /memory; regularly delete outdated and conflicting ones; should be like rules, not prose

You should now be able to: Judge whether a piece of information should go into CLAUDE.md, and in which layer; write rules specific enough to verify instead of empty talk; use @ to reference external documents while clearly knowing its context cost; know how to casually add and regularly trim when the project runs for a long time. In a word—you can write a CLAUDE.md that Claude is actually willing to listen to, instead of one with three hundred lines that nobody ignores.


Next up is 19 "Context Management"—this article repeatedly mentioned that "CLAUDE.md takes up the context window" and "@ references are still fully loaded", so what exactly is this context window, what happens when it's full, and how to use /context and /compact? The next article will thoroughly explain this workbench piece. Leaving a small thought exercise: Which do you think consumes more, the tokens taken up by a CLAUDE.md, or an entire conversation of yours?