Українська версія

Author: abavyka

It came up in every post: rules that survive compact, stack versions against hallucinations, check commands.

What it is

CLAUDE.md is plain markdown with instructions that you, or the team, write yourselves. Claude Code reads it at the start of every session. Unlike auto memory, where Claude keeps the notes itself, here it’s all by hand: build commands, conventions, “always do X”.

It’s context, not config. The contents come in as a message after the system prompt, and Claude tries to follow them, but there’s no guarantee. If something has to be blocked for real — that’s hooks or permissions, not CLAUDE.md.

Where it lives

  • Managed policy — for the whole org, IT drops it in (on macOS /Library/Application Support/ClaudeCode/CLAUDE.md)
  • ~/.claude/CLAUDE.md — global, for all projects
  • ./CLAUDE.md or ./.claude/CLAUDE.md — the project one, committed and shared with the team
  • ./CLAUDE.local.md — your personal one for this project, goes into .gitignore

They don’t override each other, they get glued together. The order goes from the filesystem root down to the folder where you launched Claude, and in each folder CLAUDE.local.md comes after CLAUDE.md. So the file from the folder where you launched Claude lands in context last, after all the files from the folders above. CLAUDE.md files in subfolders don’t load at startup, but when Claude first pokes into files in that subfolder.

To check what actually loaded: /context, the Memory files list.

What to write and what not

The docs say to add to CLAUDE.md when:

  • Claude makes the same mistake a second time
  • in review you catch something it should have known about this code
  • you type into the chat the same correction as last session
  • a new dev on the team would need the same context

Write it concrete, so it can be checked: “run npm test before committing” instead of “test your changes”. Group it under headings and lists.

Size — under 200 lines per file. A longer file eats more context and gets followed worse.

What not to write: stuff Claude already sees from the code — the folder tree, the dependency list, an architecture overview. /doctor suggests cutting exactly that, and keeping the gotchas, the “why” explanations and the conventions that differ from the defaults.

Multi-step procedures — into a skill. Rules only for part of the code — into path-scoped rules (more on them below).

And it needs refactoring now and then: clearing out the stale and the contradictory. If two rules contradict each other, Claude may pick either one. /doctor prompt-audit will find stale instructions, links to files that don’t exist and contradictions on its own, and applies fixes only when you ask.

How it turned out for me (on a pet project): CLAUDE.md at 14 lines, and inside it @RULES.md at 292 lines, with the src/ and server/src/ tree inside. So, everything the docs talk you out of.

I ran /doctor prompt-audit on it. The main stuff:

  • In RULES.md the numbers and line numbers are already stale: “24 of 60 handlers” — and there are already 62 handlers, database.ts:60 moved to :68, and the folder the rule describes as empty doesn’t exist at all
  • A rule points to one migration 001_schema.sql, and there are already eight
  • The aside “take the list from the filesystem, not from memory” — a patch after a mistake in one session, the list right next to it is correct. Advice: delete it
  • Five skills sat as flat files in .claude/skills/ instead of <name>/SKILL.md, so not one of them loaded

Every finding comes with a confidence level and a ready diff, but nothing gets applied until you say so. Specific numbers and line numbers in CLAUDE.md go stale with every commit, better to write the rule and the command that checks it.

What else gets plugged in

Imports: @path/to/file anywhere in CLAUDE.md pulls the file into context. The path is resolved from the file with the import, not from the working folder. Nesting up to four levels. If you just need to mention a path without importing it — backticks: `@README`.

Rules: files in .claude/rules/, one topic per file (testing.md, api-design.md). A regular rules file loads at startup together with CLAUDE.md and hangs around in context the whole session. But at the top of the file you can put paths: with a pattern, for example server/**/*.ts. Then the rules get pulled in only when Claude opens or changes a file that matches that pattern. Didn’t touch the backend — no backend rules in context. Now this actually saves context. Personal rules for all projects — in ~/.claude/rules/.

AGENTS.md — if the team uses different agents. Claude Code reads it on its own, but by default only when there’s no CLAUDE.md or CLAUDE.local.md next to it. Want both — either @AGENTS.md as the first line in CLAUDE.md, or in /config set Project instructions = claude-md-and-agents-md.

Small thing, but handy: HTML comments <!-- ... --> get stripped before going into context. Notes for humans don’t eat tokens.

Personal stuff that shouldn’t end up in the repo

  • ~/.claude/CLAUDE.md and ~/.claude/rules/ — for everything about you, not the project
  • CLAUDE.local.md + .gitignore — personal stuff for one project
  • If you work in several git worktrees, CLAUDE.local.md will only be in the one where you created it. Then an import from your home folder is better: @~/.claude/my-project-instructions.md. The first time, Claude Code shows an approval dialog for such external imports
  • .git/info/exclude — like .gitignore, only local: not committed and invisible to everyone. Handy when you don’t even want to touch .gitignore. It just doesn’t work on files git already tracks

How it is for me: in another repo there’s my CLAUDE.md at 4 lines — three @ imports of my tools, and all of it is in .git/info/exclude. Next to it there’s an AGENTS.md I once dropped in while testing other agents. The kicker is that CLAUDE.md doesn’t import it, so by default Claude simply doesn’t see that AGENTS.md.

Gotchas

  • An import doesn’t save context. It helps organize the file, but the imported stuff loads at startup in full. Only rules with paths: save it
  • Edits to CLAUDE.md mid-session don’t apply. Claude works with the old version until /clear, /compact or a restart
  • CLAUDE.md is advice, not a guarantee. Whatever is critical — hooks
  • CLAUDE.local.md in a project with AGENTS.md turns off reading AGENTS.md. Fixed by the same Project instructions setting

How to start from scratch

  • /init — Claude goes through the codebase and generates a CLAUDE.md with build and test commands and conventions. If the file already exists, it suggests improvements instead of overwriting it
  • With CLAUDE_CODE_NEW_INIT=1 /init is interactive: it asks what to set up (CLAUDE.md, skills, hooks), asks follow-ups and shows a proposal before writing
  • Then you add what Claude won’t find on its own. And clean out what it would find anyway
  • /memory — the list of all instruction files, open and edit

TS example

A made-up project: frontend in web/, backend in server/.

CLAUDE.md:

@AGENTS.md
 
## Commands
- `npm run typecheck && npm test` after every change
- `npm run dev` starts web and server together
 
## Conventions
- Strict TypeScript, no `any`; types from `const` arrays, not manual unions
- No hardcoded UI strings, only `t('key')`
- Never edit generated files in `src/gen/`
 
## Gotchas
- Server tests need a local Postgres: `docker compose up db`

.claude/rules/api.md — loads only when Claude touches the backend:

---
paths:
  - "server/**/*.ts"
---
# API rules
- Validate every request body at the route
- Throw typed errors, never a raw `Error`
- Route handlers stay thin: parse, call one service, respond

I’ll tell you about my tools separately — rtk and a local code graph MCP.

Read more