Keep CLAUDE.md under 200 lines: what to write, what to cut, where the rest goes
TL;DR
Put in CLAUDE.md only what Claude can't learn from the code: verification commands, misleading spots, off-repo decisions. Stay under 200 lines; move scoped rules to .claude/rules, procedures to skills and hard rules to hooks.
Many teams treat CLAUDE.md like a wiki: every convention, every process, every lesson learned, then wonder why Claude increasingly "ignores" instructions. The reason is mechanical: CLAUDE.md is loaded into every session, so every line takes a bit of Claude's attention on every task, relevant or not. The Claude Code docs recommend keeping each file under 200 lines; longer files both cost context and reduce adherence. This post covers how to write a lean CLAUDE.md and where to put everything else.
The test before adding a line
- Could Claude find this out by reading the code?
- Would it actually go looking?
If both answers are "yes", drop the line. Today's models read code very well: folder structure, test framework, naming conventions… they see it themselves. What they can't see is what never lived in the repo: decisions made in a meeting, a deploy process that exists in one person's head, environment variables the integration tests need.
What should CLAUDE.md contain?
- How to verify: exact test, typecheck and lint commands; how to run a single test file.
- Misleading code: old patterns that are everywhere but new code shouldn't copy; folders that look abandoned but are still in use.
- Decisions not in the repo: the chosen error-handling helper, how to deploy, which migrations need review.
- Things you've had to correct Claude on twice.
# Commands
- Install: pnpm install
- Run one test file: pnpm vitest run path/to/file.test.ts
- Typecheck: pnpm tsc --noEmit
# Conventions
- Use the error helpers in src/lib/errors.ts, never throw raw strings
- src/legacy/ is still live but don't copy its patterns into new code
# Gotchas
- Integration tests need DATABASE_URL set, see .env.example
Where does everything else go?
| Content type | Put it in | When it loads |
|---|---|---|
| Rules for one part of the codebase | .claude/rules/*.md with paths: frontmatter | Only when Claude works on matching files |
| Team processes (release, runbooks) | .claude/skills/<name>/SKILL.md | Only name + description always visible; content read when needed |
| Personal preferences in the project | CLAUDE.local.md (add to .gitignore) | Every session, only on your machine |
| Instructions for one subfolder | subfolder/CLAUDE.md | When Claude reads/edits files in that folder |
| Rules with no exceptions | Hooks, deny rules | Always enforced by the harness, independent of the model |
An example path-scoped rule:
---
paths:
- "src/api/**/*.ts"
---
- Validate request bodies with the zod schemas in src/api/schemas/
- Every new endpoint needs an entry in openapi.yaml, CI fails without it
A long release process inside a skill won't weigh down unrelated bug fixes the way it does inside CLAUDE.md. For skills with side effects (actually cutting a release), add disable-model-invocation: true so they only run when you type /release yourself.
Loading mechanics worth knowing
- CLAUDE.md files in the working directory and every parent directory are loaded at startup, concatenated rather than overriding each other. If two instructions conflict, Claude may pick either.
- Import other files with
@path/to/file, up to 4 levels deep. Imports don't save tokens: imported files still go into context. - Auto memory (notes Claude writes itself) lives in
~/.claude/projects/<project>/memory/; each session loads only the first 200 lines or 25KB of the index file.
Cleanup tools
/init: generates a first version from the codebase. The next job is mostly deleting./doctor: suggests cutting what Claude can infer from the code./doctor prompt-audit: finds instructions written for older models, references to files that no longer exist, or contradictions./context: confirms the file is loaded;/memory: view and edit it.
How to apply it
- Dev: Put personal preferences (reply tone, sandbox URLs) in
CLAUDE.local.md, not in the shared file. - Tech Lead: Review CLAUDE.md quarterly like tech debt: delete stale lines, move processes into skills, local rules into
.claude/rules/, mandatory rules into hooks. - PM: Product decisions that affect code (for example "don't use library X because of its licence") are exactly the kind of information worth having in CLAUDE.md.
Sources & references
- Best practices for Claude Code — Claude Code Docs
- How Claude remembers your project — Claude Code Docs