Engineering
A CLAUDE.md That Actually Helps

Part 2 of the thread Building with Claude and MCP
- CLAUDE.md is a plain Markdown file Claude Code reads at the start of every session. It's the house rules.
- It can live at the user, project or local level, and the docs suggest keeping each one under 200 lines.
- The test for every line: would Claude make a mistake without it? If not, cut it.
- Point to other files instead of pasting them in, and prune it like code.
The CLAUDE.md template in my vault is a monster. It has a tech stack section, coding standards, a layered architecture diagram, four FastAPI code patterns, a pull request checklist, a production deployment checklist and a version history. It looks thorough. It's also exactly what the current docs warn against.
Checked against the docs in September 2026.
What it is and where it goes
CLAUDE.md is a MarkdownA plain-text format where a # makes a heading and **stars** make bold. Easy to write, and easy to turn into a web page. file that Claude Code loads into context when a session starts. Think of it as the note you'd leave a new contractor on the kitchen counter: what this place is, where things are, and the three things that'll get you in trouble.
There's more than one, and they stack:
| File | Scope | Commit it? |
|---|---|---|
~/.claude/CLAUDE.md |
You, in every project | No, it's yours |
./CLAUDE.md or ./.claude/CLAUDE.md |
This project, everyone on it | Yes |
./CLAUDE.local.md |
This project, just you | No, add it to .gitignore |
| A CLAUDE.md in a subfolder | Loads when Claude reads files in that folder | Yes |
A few tools make it easier. /init writes a starter file from your repo, and if one already exists it suggests changes instead of overwriting. /memory opens the files so you can edit them. A line like @docs/setup.md imports another file, up to four hops deep. There's also a .claude/rules/ folder for rules that should only apply to certain paths.
Note
My notes mention a
#shortcut for adding a line to memory mid-session. It's gone from the current docs. Now you just tell Claude "add that to CLAUDE.md," or edit it through/memory.
The one this blog uses
The best example I've got is the file sitting in the repo for this site. Trimmed a little, it reads:
# Working on this site
This is Wes Ellis's personal blog (Eleventy 3, Nunjucks, Markdown, Sveltia CMS, deployed to DigitalOcean from `main`).
Before writing or editing any post, read `TEMPLATES.md`. The five post types (note, script, recipe, case study, photo story) are locked. Don't invent new layouts, front matter fields or page styles.
Must-follow rules:
- Voice: Wes's, human and conversational. Never generic or AI-sounding.
- Never put real credentials in anything.
- Never hard-wrap code.
- Don't invent personal experiences, numbers or results.
Before handing work back: `npm run build` then `npm run check`. Both must pass.
That's about it. What it does well is mostly what it leaves out. It doesn't restate the post templates, it points at the file that has them. It doesn't explain EleventyA static site generator. It takes Markdown files and templates and builds a folder of plain HTML pages. This site runs on it.More: Rebuilding This Notebook. It names the two commands that prove the work is done, and it lists the handful of mistakes that would actually hurt, like a real password in a post or a made-up anecdote with my name on it.
What earns a line
The docs have a good test: for each line, ask whether removing it would cause Claude to make mistakes. If not, cut it. They're blunt about why, too. A bloated file makes Claude more likely to ignore the instructions you care about, and the suggested ceiling is under 200 lines per file.
My template did get one thing right, the "be specific" section:
| Vague | Specific |
|---|---|
| Write good code | Run ruff check and pytest before calling anything done |
| Test everything | Every new function gets a test in tests/, mirroring src/ |
| Be careful with secrets | Config comes from environment variables. Never commit .env |
| Follow our patterns | Data access goes through repositories/. Routes never touch the database |
Things worth a line:
- Commands: how to build, test, lint and run it.
- Landmines: the thing that broke last month and why.
- Pointers: "read X before touching Y."
- Hard nos: no secrets, no force-pushes, don't edit generated files.
Things that don't earn one: anything a linterA tool that reads your code without running it and flags mistakes and sloppy habits, like an unused import or a variable that's never set.More: Scaffolding a Python Project So Future-You Doesn't Hate It already enforces, anything Claude can read straight from the code, long style guides, and anything secret. The file gets committed, and its contents go to the model, so treat it like any other text you'd paste into a prompt. I wrote more about that in keeping secrets out of prompts.
Keep it alive
The best habit from my old notes still holds: update it right after something goes wrong. If Claude trips on the same thing twice, that's a line. If a line hasn't mattered in months, it's clutter. The docs put it as treating CLAUDE.md like code, reviewed when things break and pruned regularly.
It also isn't the only place instructions can live. When I run three Claude Code agents at once, each one gets its own written brief for the batch, and CLAUDE.md stays the standing rules underneath all three. And for a prompt you keep typing by hand, a custom slash command is usually a better home than another paragraph here.