Every Claude Code session starts with an empty context window. CLAUDE.md is the file the agent reads at the start of each one, so whatever sits in it gets paid for on every task, whether it helps or not. The usual failure is a long file that describes a codebase the agent could read for itself, plus a changelog nobody asked for.
I keep the CLAUDE.md of this site at 45 lines. Below is what is in it, why each line earns its place, and what I moved elsewhere or deleted.
What does Claude Code actually do with CLAUDE.md?
Claude Code loads CLAUDE.md files into context when a session starts. The official memory documentation lists four scopes: a managed policy file for the whole organization, a user file at ~/.claude/CLAUDE.md for all your projects, a project file at ./CLAUDE.md shared through git, and a CLAUDE.local.md for personal notes you keep out of version control. Files found above the working directory load at launch; files in subdirectories load once Claude touches a file in that folder. All of them are concatenated, so nothing overrides anything: they stack.
Two sentences from the same page shape how I write the file. First, Claude "treats them as context, not enforced configuration", and if something must be blocked no matter what, the docs point you to a PreToolUse hook. Second, "the more specific and concise your instructions, the more consistently Claude follows them." The docs also suggest a target of under 200 lines per file, because longer files consume more context and reduce adherence.
Which instructions belong in a CLAUDE.md?
A line belongs in CLAUDE.md when the agent cannot infer it from the code and getting it wrong costs something. Build commands, package manager, the one test command that matters, delivery rules, conventions that contradict the framework default. The docs phrase it as "facts Claude should hold in every session" and suggest refining the /init output "with instructions Claude wouldn't discover on its own."
This is the core of the project CLAUDE.md on this site, trimmed of a couple of rows:
# CLAUDE.md
Bilingual (en/it) portfolio: Next.js 16 App Router, React 19, Tailwind v4,
deployed on Vercel from `main`. `AGENTS.md` points here.
## Rules
- **TDD, non-negotiable.** Failing test first, then the code. Skills `tdd` + `testing`.
- **Code** follows CODING_STANDARDS.md; `/ship` reviews every diff against it.
- **Docs = current state only.** When behavior changes, update or delete the
old text in the same diff. No history (git has it).
- **Map is part of the diff**: update affected cards in the same session (map/CLAUDE.md).
- **Never open PRs**: `/ship` merges into `main` and pushes.
- **pnpm only**: never npm/yarn.
- **Type errors don't fail the build** (`ignoreBuildErrors`): run `pnpm typecheck`.
- **New translatable string**: add the key to both `en.json` and `it.json`.
## Where to find things
| You need... | Open |
| --------------------------- | --------------------------- |
| why a choice was made | docs/adr/ |
| how code must be written | CODING_STANDARDS.md |
| what a change hits | map/CLAUDE.md |
| tests: layer, how to run | `testing` skill |
| shipping config | .agents/ship.md |Read the rules one at a time and ask whether the agent could work them out alone. "pnpm only" is guessable from the lockfile, but an agent that reaches for npm install out of habit creates a second lockfile, so the line stays. "Type errors don't fail the build" is the opposite of what anyone expects from a Next.js project, because next.config sets ignoreBuildErrors; without the line, a green build looks like proof the types are fine. "Never open PRs" encodes a delivery decision that lives in my head and in a ship config, not in the source. None of these would come out of reading the code.
The style is imperative and short. Each rule is one bullet, the reason is a clause at most, and the bold lead word is what the agent needs to remember. Long explanations go where the rule points.
Why should CLAUDE.md link out instead of inlining everything?
The bottom half of the file is a table called "Where to find things". It maps a need (why a choice was made, how code must be written, what a change hits) to a file: architecture decision records, CODING_STANDARDS.md, the system map, a skill. The agent pays a single line of context for each pointer and only reads the target when the task needs it.
CODING_STANDARDS.md is 48 lines of rules such as no comments in source files and no secrets in logs or tracebacks, each with a short "Why". It does not sit in CLAUDE.md because only code-writing tasks need it, and because the review step checks every diff against it anyway. The system map has its own map/CLAUDE.md, 25 lines, which Claude Code loads on demand when the agent works inside map/. AGENTS.md at the repo root is one sentence: all guidance lives in CLAUDE.md, do not duplicate rules here. Other coding agents that read AGENTS.md get sent to the same source.
The way the pointer is worded decides when the agent follows it. "Map is part of the diff: update affected cards in the same session" gets followed far more reliably than a bare "see map/", because it names the trigger (any change) and the action (update the cards).
How do project, global and skill instructions divide the work?
I use three layers, and the test for each is who needs the instruction and how often.
The global file in ~/.claude/CLAUDE.md holds how I work on every repo. Mine is short and almost entirely about mistakes I watched an agent make more than once. One rule says to open a git worktree before editing a repository and to return it when finished, because parallel agents writing to the same checkout overwrite each other. Another one covers a wait loop that never terminates:
# Global
## Isolated / parallel work
If you need to edit files in a repo, open a git worktree first and work only there.
Never leave worktrees behind: return them when done.
## Local tools
My CLI tools are listed in a separate file. Read it before reinventing one.
## Waiting on processes
Never wait with `until ! pgrep -f "X"` inside a Bash command: the pattern matches
the shell running the loop, and it never ends. Run the job in the background and
wait for the notification, or use `wait <pid>`.That rule describes the failure precisely: pgrep -f matches its own shell, so the loop never exits. A vague "be careful when waiting on processes" would change nothing. The global file also points to a separate list of my local CLI tools instead of describing them.
The project CLAUDE.md holds what is true for this repository and anyone working in it. Skills hold procedures. This repo has project skills in .claude/skills/ for TDD, testing, shipping, triage and writing blog posts. Claude Code loads a skill's body only when the skill is invoked or judged relevant, so a 120-line procedure for writing a post costs nothing while I fix a CSS bug. The docs say the same thing: multi-step procedures and instructions that only matter for part of the codebase belong in a skill or a path-scoped rule in .claude/rules/.
| Instruction | Where it goes | Why |
|---|---|---|
| pnpm only, never npm | Project CLAUDE.md | Short, every task, costly if missed |
| Type errors don't fail the build | Project CLAUDE.md | Not inferable, contradicts the default |
| Open a worktree before editing | Global CLAUDE.md | True on every repo I touch |
| Full coding standards with reasons | CODING_STANDARDS.md, linked | Needed only when writing code |
| How to write and publish a blog post | Skill | Multi-step, needed a few times a month |
| Rules for one folder | Nested CLAUDE.md or .claude/rules/ | Loads only when that folder is touched |
| What the code already says (folder tree, list of components) | Nowhere | The agent can read it, and it goes stale |
| History of past decisions and old behavior | Nowhere (git, ADRs) | Describes code that no longer exists |
What does "docs = current state only" mean for an agent?
One of the rules in this repo's CLAUDE.md reads: docs, PRDs, plans and map describe what the code does now; when behavior changes, update or delete the old text in the same diff; no history, git has it. The rule matters more with agents than with people. A developer reads "we used to do X, now we do Y" and skips the first half. An agent may treat both halves as instructions, or follow the old one because it appears first.
So the CLAUDE.md never says "previously" or "since the migration". When a rule changes, the old line goes away in the same commit as the code change. The map has the same discipline, written in map/CLAUDE.md as an update rule: changes are proportional, and prose is rewritten only when behavior changes. The official docs flag the same risk from another angle: if two instructions contradict each other, Claude may pick one arbitrarily.
What should you leave out of CLAUDE.md?
Everything the agent can derive by reading the repo: directory trees, lists of components, the framework's standard conventions, a summary of package.json. It costs tokens on every session and turns into a lie the first time someone renames a folder. History goes too, along with changelogs, "we tried X and it didn't work" stories without a rule attached, and generic advice such as "write clean code" or "follow best practices". The docs give a good test case: "API handlers live in src/api/handlers/" instead of "Keep files organized".
Personal preferences stay out of the shared file. Your editor habits, your sandbox URLs and your test accounts belong in CLAUDE.local.md or the global file, not in a document every teammate's agent reads.
What are the common mistakes with CLAUDE.md?
Running /init and committing the output as is. /init produces a reasonable first draft by scanning the codebase, which means it is full of things the codebase already says. Keep the commands and delete the description.
Using CLAUDE.md as enforcement. If the agent must never push to main or touch a secrets file, a sentence in a context file is a request. Permissions and hooks are the mechanism that actually blocks.
Writing rules without the failure they prevent. "Be careful with processes" gives the agent nothing to act on. "pgrep -f matches its own shell, use wait <pid>" does.
Duplicating rules across CLAUDE.md, AGENTS.md, a README and a wiki page. They drift apart, and then the agent has two versions to choose from. Keep one source and make the others point to it.
Never pruning. A rule written for a bug that was fixed six months ago keeps costing context on every run. When you review the file, delete as readily as you add.
Want your agents to follow the rules that matter?
I set up Claude Code and agent workflows on real codebases: CLAUDE.md, skills, review gates and tests. Tell me how your team works today.
Let's talkIf you are building agents rather than configuring a coding assistant, the same principles apply to system prompts and tool descriptions. That is the work behind my AI agent development service.



