ES · Leer en español Explore for free

Recipe · Basic · 15 min

How to write a CLAUDE.md that Claude Code actually follows

What to put in CLAUDE.md and what to leave out, where each file goes, @path imports, /init and /memory, plus a tested template for a web project.

Tested with Claude Code 2.1.316 · reviewed

The problem

You write a huge CLAUDE.md with everything you know about the project and Claude Code skips half of it. Or the opposite: you have none, and every session you explain again how to run the tests. Both have the same fix: a short file holding only what Claude can't work out from the code, in the right place, with the rules that allow no exceptions moved out of it.

The solution

1. Generate a draft with /init and start deleting

Open Claude Code inside your project and type:

/init

Claude analyzes the code and creates a CLAUDE.md with the build commands, test instructions and conventions it discovers. If you already have one, it suggests improvements instead of overwriting it. From there the work is mostly removing lines: the official docs recommend staying under 200 lines per file, because longer files use more context and are followed less reliably.

2. Keep only what Claude can't see in the code

Include:

Leave out:

3. Put each thing at its level

Claude Code concatenates (doesn't override) all of these files, from broadest to most specific:

LevelPathForShared with
OrganizationLinux/WSL: /etc/claude-code/CLAUDE.md · macOS: /Library/Application Support/ClaudeCode/CLAUDE.mdCompany standardsThe whole organization
User~/.claude/CLAUDE.mdYour preferences across all projectsOnly you
Project./CLAUDE.md or ./.claude/CLAUDE.mdTeam commands and conventionsThe team, via git
Local./CLAUDE.local.mdYour sandbox URLs, sample dataOnly you (add it to .gitignore)
Subfoldersrc/payments/CLAUDE.mdRules for that part of the codeThe team

Files in the directory where you launch Claude and the ones above it load at startup; the closest one is read last. Subfolder CLAUDE.md files load on demand, when Claude reads or edits a file in that folder. To keep CLAUDE.local.md out of the repo:

echo "CLAUDE.local.md" >> .gitignore

If a rule only matters for certain files, a better option than a subfolder is a rule with paths in .claude/rules/, which only enters the context when Claude touches matching files:

---
paths:
  - "src/api/**/*.ts"
---
- Validate request bodies with the schemas in src/api/schemas/

4. Split into files with @path imports

Write @path/to/file anywhere in CLAUDE.md and that file loads along with it. Relative paths resolve from the importing file (not from the folder where you launch Claude), and nested imports go up to four hops deep. Importing organizes, but it doesn't save context: the imported file loads in full next to the CLAUDE.md. To mention a path without importing it, wrap it in backticks. The first time a project CLAUDE.md imports something from outside the project (for example @~/.claude/my-notes.md), Claude Code asks you to approve it.

5. Move procedures to skills

A multi-step workflow (cutting a release, preparing a migration) weighs on every session if it lives in CLAUDE.md. In a skill (.claude/skills/<name>/SKILL.md) Claude only sees the name and description until the task needs it. If the workflow has side effects (deploying, publishing), add disable-model-invocation: true to its frontmatter so it only runs when you type /<name>.

6. Move mandatory rules to hooks and permissions

CLAUDE.md is context, not enforced configuration: Claude follows it almost every time, but it may decide an instruction doesn't apply. If something must always or never happen, have Claude Code enforce it. For example, "never read .env" as a permission rule in .claude/settings.json:

{
  "permissions": {
    "deny": ["Read(./.env)", "Read(./.env.local)", "Read(./secrets/**)"]
  }
}

deny rules hold in every permission mode and also block cat .env. For "run the formatter after every edit" or "don't touch migrations/" use a PostToolUse or PreToolUse hook (see the official hooks guide). If you catch yourself adding "IMPORTANT" to a line Claude keeps ignoring, that line is a hook.

7. Copy this template for a web project

Save it as CLAUDE.md at the root and swap the commands for yours:

# Project: web-shop (Vite + React + TypeScript)

## Commands
- Install: `npm ci`
- Dev server: `npm run dev` (http://localhost:5173)
- One test: `npx vitest run src/path/file.test.ts`
- All tests: `npm test`
- Types: `npx tsc --noEmit`
- Lint: `npm run lint`

## When something counts as done
- `npx tsc --noEmit` and the tests for the file you touched pass.
- UI changes: check them in the browser, not only with tests.

## Conventions (what the code doesn't show)
- Style: @docs/style.md
- API calls only from `src/api/client.ts`; never a bare `fetch` in components.
- `src/legacy/` is still in production, but don't copy its patterns into new code.

## Known gotchas
- Integration tests need `VITE_API_URL`; copy `.env.example` to `.env.local`.
- `npm run build` fails if there are circular imports in `src/store/`.

## Git
- Branches `feat/…` or `fix/…`; commit messages in the imperative.

And the imported file, docs/style.md:

# Code style
- 2-space indentation, single quotes, no semicolons.
- Components in PascalCase, one component per file, named exports (no `export default`).
- User-facing text in plain, neutral English.

Check it

Inside a session, /context shows the Memory files list with the CLAUDE.md files that loaded, and /memory lists them all (including ones that don't exist yet) so you can open and edit them. From the terminal you can ask directly:

claude -p "What style rules does this project have? Answer in one line"

Real output with the template above and Claude Code 2.1.316 (our ~/.claude/CLAUDE.md asks for replies in Spanish, so it answered in Spanish; translated here, which also shows the user and project levels being combined):

According to `docs/style.md`: 2-space indentation, single quotes, no semicolons, components in PascalCase with one component per file and named exports (no `export default`), and user-facing text in plain, neutral English.

The style rules live only in docs/style.md, and --output-format stream-json --verbose shows Claude used no tool to read it: it arrived through the @docs/style.md import.

Why it works

Claude Code reads the CLAUDE.md files at the start of every session and delivers them as a message after the system prompt, so they compete for attention with everything else: the shorter and more concrete, the better they're followed. Imports are expanded before reaching the model, paths rules and subfolder CLAUDE.md files only enter when needed, and hooks and permissions are run by Claude Code, not the model, so they don't depend on it "remembering". Sources: Claude Code memory and best practices.

Common mistakes

FAQ

Where does the CLAUDE.md file go?

At the project root (./CLAUDE.md or ./.claude/CLAUDE.md) for the team, and in ~/.claude/CLAUDE.md for your preferences across all projects. Both load together.

How many lines should a CLAUDE.md have?

The official docs recommend under 200 per file. Splitting it with imports doesn't reduce the cost, because imported files load anyway.

What's the difference between CLAUDE.md and CLAUDE.local.md?

CLAUDE.md goes into git and is shared by the team; CLAUDE.local.md is yours only, is read after the CLAUDE.md in the same folder, and belongs in .gitignore.

Does my AGENTS.md work?

Yes: Claude Code reads AGENTS.md when there's no CLAUDE.md or CLAUDE.local.md in your folder or above it. If you have both, put @AGENTS.md inside your CLAUDE.md.

Does writing "IMPORTANT" or "ALWAYS" help?

Not much. If a line keeps being ignored, either the file is too long or the rule allows no exceptions and should be a hook or a permission rule.

All recipes