All posts
6 min read

How to Write a CLAUDE.md That Actually Changes What Claude Does

Most CLAUDE.md files are either empty or a wall of generic advice Claude would have followed anyway. What to put in one, what to leave out, how the files load, and how to tell whether yours is working.

Claude CodeAI agentscontextdeveloper experience

Every Claude Code session starts with an empty context window. Whatever it learned yesterday about your project — that tests need a running database, that utils/ is legacy and shouldn't be extended, that you deploy from release and never from main — is gone.

CLAUDE.md is how you give it back. It's a Markdown file Claude Code loads at the start of every session, and it's the cheapest, highest-leverage thing you can do to make an agent better at your codebase specifically.

It's also where a lot of people waste effort, writing instructions Claude would have followed anyway and omitting the ones it could never guess.

How the files load

Before deciding what to write, know where it goes. Per Anthropic's documentation:

File Scope Shared?
./CLAUDE.md (or ./.claude/CLAUDE.md) This project Yes — commit it
./CLAUDE.local.md This project, just you No — add to .gitignore
~/.claude/CLAUDE.md Every project on your machine Just you
subdir/CLAUDE.md That part of the codebase Yes

Files in the directory you launch from, and every directory above it, load at startup and are concatenated — they don't override each other. Files in subdirectories load on demand, when Claude reads files in that directory. That makes nested files a good home for instructions that only matter in one area: a CLAUDE.md in migrations/ that says "never edit a migration that has already been merged" costs nothing until Claude goes near a migration.

You can also pull other files in with @path/to/file imports, though imported content still loads at launch and still takes up context.

Run /init in a project to have Claude generate a starting file from what it can discover in the codebase. It's a reasonable first draft. The valuable part is what you add afterwards.

The test for every line

Ask one question of each instruction: would Claude get this wrong without being told?

"Write clean, readable code" fails the test. So does "use TypeScript" in a repository full of .ts files, or "follow existing conventions." Claude does those already. Those lines cost context and dilute the ones that matter.

What passes the test is knowledge that isn't in the code, or is in the code but is easy to misread:

  • Commands that aren't obvious. How to run a single test file. Which script seeds the database. That the dev server needs npm run dev:api and npm run dev:web.
  • Things that look usable but aren't. "lib/legacy-auth/ is being removed — do not import from it." Without this, Claude sees a working auth module and uses it.
  • Non-local consequences. "Changing anything in schema.prisma requires a migration; run npm run db:migrate and commit the generated file."
  • Environment facts. "Tests need Postgres running on port 5433, not 5432." "The API key in .env.example is fake; real keys are in the team vault."
  • Decisions already made. "We use Zod for validation, not Yup — don't add Yup even where it would be shorter." "Dates are stored as UTC and formatted only in the UI layer."
  • Workflow rules. "Never push to main. Open a pull request." "Run npm run lint before declaring a task done."

A good one is short

Anthropic's own guidance is to keep each file under roughly 200 lines, because longer files consume context and reduce how consistently instructions are followed. That matches experience: the most effective files are dense and specific, not comprehensive.

A good project CLAUDE.md often looks something like this:

# Project: billing-api

## Commands
- Install: `pnpm install`
- Dev: `pnpm dev` (needs Postgres — `docker compose up db`)
- Test one file: `pnpm vitest run path/to/file.test.ts`
- Before finishing any task: `pnpm lint && pnpm test`

## Architecture
- `src/routes/` is thin: validate with Zod, call a service, return.
- Business logic lives in `src/services/`. Services never import from `routes/`.
- `src/legacy/` is frozen. Read it, never extend it.

## Rules
- Money is integer cents everywhere. Never use floats for amounts.
- Every schema change needs a migration: `pnpm db:migrate`, commit the file.
- Never push to `main`; open a PR.

Twenty lines, and nearly every one of them prevents a specific, realistic mistake.

Write rules, not essays

Instructions work better as short, direct statements than as paragraphs of reasoning. "Money is integer cents" beats a paragraph about floating-point precision. If the reason matters — because it helps Claude handle cases the rule doesn't cover — add it in one clause: "Money is integer cents (floats caused rounding bugs in invoices)."

Be specific about scope. "Don't use any" is ambiguous in a codebase that already has fifty. "Don't add new any types; leave existing ones alone unless the task is about them" is not.

And watch for contradictions. If two files disagree, Claude may follow either. Nested files and a user-level file make this easy to do by accident.

What doesn't belong in CLAUDE.md

  • Secrets. It's committed and it's read into a model's context. Keys belong in environment variables.
  • Things that must never happen. CLAUDE.md is context, not enforcement — Claude treats it as guidance. If a command must never run, block it with a permission deny rule or a hook. We cover those in Running Claude Code Unattended.
  • Documentation for humans. Your README explains the project to people. CLAUDE.md should hold the operational knowledge an agent needs, and can import the README if it's genuinely useful.
  • Task-specific instructions. "Today we're refactoring the invoices module" belongs in the prompt, not the file every future session loads.

Maintaining it

Treat CLAUDE.md like code. The best trigger for an edit is a mistake: when Claude does something wrong that a sentence would have prevented, add the sentence. When a rule stops being true — the legacy module is finally deleted — remove it, because stale instructions actively mislead.

Review it in pull requests like anything else. It shapes every session anyone on the team runs.

The limit of what it can fix

A good CLAUDE.md solves session amnesia about knowledge: conventions, commands, decisions. It doesn't solve amnesia about state. If every session starts in a fresh environment, Claude still has to reinstall dependencies, restart the database, and reproduce the bug it had already narrowed down yesterday — no instruction file brings that back. We go into that distinction in Why Your AI Agent Keeps Forgetting.

The two fixes are complementary: write down what the agent should know, and give it an environment that keeps what it did.


EasySpawn gives Claude Code a persistent workspace per project — your CLAUDE.md, dependencies, database, and the agent's own notes all survive between sessions. See how it works or join the waitlist.

Related: Why Your AI Agent Keeps Forgetting · Running Claude Code Agents in Parallel With Git Worktrees

Keep reading