CLAUDE.md: The File That Saves You From Repeating Yourself
I rewrote my CLAUDE.md file about a dozen times before it started actually helping. The first few versions were either too vague to matter or so long that I was burning context on stuff Claude didn’t need.
Here’s what I eventually figured out.
What It’s For
CLAUDE.md is project memory. The things Claude needs to know before touching your code:
- How the project is structured
- Build and test commands
- Conventions you follow
- Gotchas that will waste time
It’s not documentation. It’s not a README. It’s a briefing.
What Actually Belongs In There
Architecture in one paragraph. Not a deep dive — just enough to orient. “This is a FastAPI service. Routes live in app/routes/. Database models are in app/models/.”
Commands that matter. Build, test, lint, deploy. The ones Claude will actually need to run.
## Commands
- `uv run pytest` — run tests
- `uv run ruff check .` — linting
- `uv run uvicorn app.main:app --reload` — dev server
Your conventions. If you have opinions about how code should look, state them. “We use Pydantic for all request/response models. No raw dicts in route handlers.”
The gotchas. The non-obvious stuff that trips Claude up. “The database session is injected via Depends(get_db) — don’t create sessions manually.”
What Doesn’t Belong
Stuff Claude can discover. Don’t list every file. Don’t explain what FastAPI is. Claude can read your code and figure out the obvious.
Anything that changes constantly. If you’re updating CLAUDE.md every day, that content probably belongs somewhere else — or should be injected via hooks.
Long explanations. If a section runs past a few sentences, you’re writing documentation, not a briefing. Link to docs instead.
Structure Tips
Keep it scannable. Headers matter. Claude (and you) should be able to skim it in seconds.
I like this order:
- One-line project description
- Key commands
- Architecture overview
- Conventions
- Gotchas
Front-load the stuff Claude needs most often.
Subdirectory CLAUDE.md Files
You can put CLAUDE.md files in subdirectories. Claude reads them when working in that part of the codebase.
This is useful for:
- Monorepos with different packages
- A
tests/folder with specific testing conventions - An
app/routes/folder with API patterns
Keep the root file general. Let subdirectory files handle the specifics.
The Length Tradeoff
Too short: Claude asks questions you could have preempted.
Too long: You’re burning context on stuff that doesn’t matter for most tasks.
My rule of thumb: if I wouldn’t say it out loud at the start of a pairing session, it probably doesn’t belong.
Aim for something you can read in 30 seconds. If you can’t, trim it.
A Before and After
Before (too vague):
# My Project
This is a web app. Please write good code and follow best practices.
This tells Claude nothing. “Best practices” according to who?
After (actually useful):
# Invoice API
FastAPI service for invoice management. PostgreSQL backend.
## Commands
- `uv run pytest` — run tests
- `uv run ruff check . --fix` — lint and fix
- `uv run alembic upgrade head` — run migrations
## Structure
- `app/routes/` — API endpoints
- `app/models/` — SQLAlchemy models
- `app/schemas/` — Pydantic request/response models
## Conventions
- All routes use dependency injection for DB sessions
- Pydantic models for all request/response bodies
- Use `HTTPException` for errors, not bare raises
## Watch Out For
- Always use `async def` for route handlers
- The `get_current_user` dependency handles auth — don't roll your own
- Alembic migrations must be created manually: `uv run alembic revision --autogenerate -m "description"`
The second version tells Claude exactly what it needs. No guessing.
Keep It Fresh
CLAUDE.md gets stale. When you change conventions or add new patterns, update it.
I review mine whenever I notice Claude making the same mistake twice. That’s usually a sign something’s missing from the briefing.
How This Relates to Hooks
In the last post, I covered injecting context dynamically with hooks. That’s for stuff that changes — git state, environment info, current focus.
CLAUDE.md is the constant. The foundation that’s always there.
Dynamic context on top of static context. That’s the full picture.
A good CLAUDE.md saves time on every session. Ten minutes spent writing it pays off for months.
Start small. Add things when you notice Claude asking or assuming wrong. Trim things that never seem to matter.