For the first few weeks I used Claude Code, I kept correcting the same things. “We use pnpm, not npm.” “Tests go next to the file, not in a __tests__ folder.” “Don’t add comments explaining what the code does.” Every session. Same corrections. Like onboarding a new hire who forgets everything overnight.

Then I actually read the docs and set up a CLAUDE.md properly. Most of that repetition disappeared in a day. It’s the single highest-leverage thing I’ve done with the tool, and it took twenty minutes.

Here’s what I put in mine, what I deliberately leave out, and the mistakes I made getting there.


What CLAUDE.md actually is

It’s a file Claude Code reads automatically at the start of every session. Whatever’s in it becomes standing context. So instead of explaining your project every time, you explain it once, in a file, and it’s just always there.

That’s the whole idea. It’s not magic. It’s a cheat sheet you write for a coworker who’s brilliant but has amnesia.

The trap is treating it like documentation. It’s not documentation. It’s instructions. Big difference, and it’s the difference between a file that helps and a file that gets ignored.


Start with how to run things

The first section of mine is the boring operational stuff, because that’s what Claude gets wrong most often when it’s guessing.

## Commands
- Install: `pnpm install`
- Dev server: `pnpm dev` (runs on :3000)
- Test: `pnpm test` (vitest, watch mode off in CI)
- Test one file: `pnpm test path/to/file.test.ts`
- Lint: `pnpm lint` (biome, not eslint)
- Build: `pnpm build`

Before this, Claude would confidently run npm test and get an error, then try yarn, then ask me. Now it just knows. The “test one file” line alone saves me constant back-and-forth, because otherwise it runs the entire suite to check one function.

Put this first. It’s the section that pays for itself on day one.


Then the conventions that aren’t obvious from the code

Claude reads your code and copies the patterns it sees. That works until your codebase is inconsistent, which every real codebase is. So I spell out the version I actually want.

## Conventions
- TypeScript strict mode. No `any`. Use `unknown` and narrow.
- Tests live next to source: `foo.ts` and `foo.test.ts`
- No barrel files (`index.ts` re-exports). Import direct paths.
- Errors: throw typed error classes from `lib/errors.ts`, never bare strings
- Data fetching goes in `services/`, never in components

The key is these are the rules that you can’t infer by reading one file, because half the codebase breaks them. If your code already perfectly follows a rule everywhere, you don’t need to write it down. Claude will copy it. Only write down the things where the code would mislead it.


Tell it what NOT to do

This section did more for me than any of the positive rules. Claude Code, left alone, has habits I don’t want. So I name them and ban them.

## Don't
- Don't add comments that restate the code. Only comment the "why"
- Don't write a README or docs unless I ask
- Don't add error handling "just in case" on happy paths
- Don't install a package to solve something the stdlib handles
- Don't refactor code I didn't ask you to touch

That last one is my favorite. Without it, I’d ask for a one-line fix and get a “while I was in here I cleaned up…” with forty lines changed. Now it stays in its lane. The “don’t add comments that restate the code” line changed the character of every file it writes.

Negative instructions are underrated. Telling a capable tool what to skip is often more useful than telling it what to do.


The mistake I made: writing a novel

My first CLAUDE.md was three pages. I explained the architecture, the history of the project, why we chose the database, the whole story. It felt thorough.

It was worse than useless. A long file buries the instructions that matter under context that doesn’t. And every token in it is a token loaded into every session, so a bloated file is a slower, more expensive session for no benefit.

I cut it down to about a screen and a half. If a line isn’t changing what Claude does, it’s gone. The test I use now: would a new senior dev actually need this to not screw up? If it’s just nice-to-know background, it goes in the real docs, not here.


Use nested files for big repos

One thing that clicked late: you can have more than one CLAUDE.md. A root one for the whole repo, and more specific ones deeper in the tree. Claude reads the closest ones for wherever it’s working.

So in a monorepo I keep a lean root file with the global rules, and a small apps/api/CLAUDE.md that says “this service talks to Stripe, webhooks are in webhooks/, never log the raw payload.” Local rules live next to the local code. The root file stays short.

This stopped me from cramming every service’s quirks into one giant file that’s mostly irrelevant to whatever I’m doing right now.


Let it write its own

Here’s the shortcut I wish I’d known first. You don’t have to write CLAUDE.md by hand. Claude Code has an /init command that reads your project and drafts one for you.

I run that, then edit hard. The generated version is a solid skeleton, but it tends toward the “documentation” style, listing what things are instead of instructing what to do. So I keep the structure it finds and rewrite the content into actual rules. Getting a first draft in ten seconds and editing beats staring at a blank file.


The thing that finally made Claude Code feel like it knew my project wasn’t a better prompt or a fancier model. It was twenty minutes writing down the handful of things I was tired of repeating. Keep it short, make it instructions and not documentation, and lean hard on the “don’t” list. If you catch yourself correcting the same thing twice in one week, that correction belongs in CLAUDE.md. That’s the whole system.