CLAUDE.md Structure Guide: What Actually Works After 1000+ Sessions
The “What Do I Put in This File?” Moment
I created my first CLAUDE.md file and stared at the blank page. I knew this file was supposed to help Claude understand my project. But what exactly should go in it?
I started adding everything I could think of. Project description, coding standards, architectural decisions, TODO lists, API documentation. The file grew to 200 lines.
Then I watched Claude struggle. Long responses. Missed context. Repeated questions about things I’d documented.
Clearly, more was not better.
A Reddit comment from a power user caught my attention: “After 1000+ sessions the one thing that scales is the CLAUDE.md file - not hooks or plugins, but structured context the model reads at session start.”
Structure matters more than size. Here’s what I learned.
The Three Levels of Context
Claude Code reads CLAUDE.md files from multiple locations. Understanding the hierarchy prevents duplication:
~/.claude/CLAUDE.md <- Global (user-wide preferences)./CLAUDE.md <- Project (team-shared, git-tracked)./.claude.local.md <- Local (personal overrides, gitignored)Each level has a purpose:
| Level | File | What Goes Here |
|---|---|---|
| Global | ~/.claude/CLAUDE.md | Working relationship preferences, universal tool choices |
| Project | ./CLAUDE.md | Build commands, architecture, team conventions |
| Local | ./.claude.local.md | Personal API keys, experimental settings |
The mistake I made: putting global preferences in project files. Every project had the same “be concise” instruction. Wasted context.
The Six Sections That Actually Matter
After experimenting with various structures, I found six sections that consistently provide value:
1. Commands (Claude Can’t Guess Your Build System)
This is the most critical section. Without it, Claude tries common commands, fails, and wastes context on trial and error.
## Commands
| Command | Description ||---------|-------------|| `npm run dev` | Start development server on port 3000 || `npm run build` | Production build (runs typecheck first) || `npm test` | Run test suite with Jest || `npm run lint` | ESLint with auto-fix |I learned this the hard way. Claude kept running npm start when my project used npm run dev. Each failed attempt cost tokens and time.
2. Architecture (Where Does This File Go?)
Claude needs to know where to create files. A simple tree structure works:
## Architecture
```textsrc/ components/ # React components (functional, use hooks) services/ # API calls and business logic utils/ # Pure utility functions types/ # TypeScript type definitionstests/ unit/ # Jest unit tests (co-located with source) e2e/ # Playwright end-to-end testsEarly on, I listed every directory. That was verbose. Now I show structure and include one-line notes only for directories with non-obvious purposes.
### 3. Key Files (Entry Points Save Context)
Claude reads many files. Knowing which are critical prevents wasted exploration:
```markdown title="Key Files section"## Key Files
- `src/index.tsx` - Application entry point- `src/App.tsx` - Root component, defines routing- `vite.config.ts` - Build configuration- `.env.example` - Required environment variables templateThis section grew from frustration. I’d ask Claude to modify routing, and it would read five files before finding App.tsx. Now it knows immediately.
4. Code Style (Project-Specific Only)
Here’s where I made my biggest mistake. I included generic style rules:
- "Use meaningful variable names"- "Write DRY code"- "Follow SOLID principles"Claude already knows these. They waste space. What actually helps:
## Code Style
- Use functional components with hooks (no class components)- Prefer `const` with arrow functions for React components- Tests: describe/it pattern, aim for 80% coverage- Imports: group by external, internal, relative (separate groups)These are project-specific conventions that differ from defaults. That’s what belongs here.
5. Gotchas (Hard-Won Knowledge)
This section prevents repeated debugging:
## Gotchas
- Tests must run sequentially (`--runInBand`) due to shared DB state- `NEXT_PUBLIC_*` vars must be set at build time, not runtime- Redis connection requires `?family=0` suffix for IPv6 networks- Never delete `migrations/` files - use new migrations to undoEvery line in this section came from a debugging session. I got tired of explaining the same issues repeatedly.
6. Environment (Prerequisites for Running)
Claude can’t run your project without this:
## Environment
Required:- `DATABASE_URL` - PostgreSQL connection string- `REDIS_URL` - Redis connection with IPv6 suffix if needed- `JWT_SECRET` - Minimum 32 characters
Setup:1. Copy `.env.example` to `.env`2. Run `npm run db:migrate` before first startWhat I Stopped Including
Through trial and error, I identified patterns that don’t help:
Obvious code info. “The UserService class handles user operations” - the class name already tells us this.
Generic best practices. “Always write tests for new features” - universal advice, not project-specific.
One-off fixes. “We fixed a bug in commit abc123” - won’t recur, clutters the file.
Verbose explanations:
# BAD: The authentication system uses JWT tokens. JWT (JSON Web Tokens) are# an open standard (RFC 7519) that defines a compact and self-contained...
# GOOD: Auth: JWT with HS256, tokens in `Authorization: Bearer <token>` header.The Quality Checklist
I use this scoring rubric to evaluate my CLAUDE.md:
| Criterion | Check | Points |
|---|---|---|
| Commands | Can Claude run the project without asking? | /20 |
| Architecture | Can Claude find the right files? | /20 |
| Gotchas | Are non-obvious patterns documented? | /15 |
| Conciseness | No filler or obvious info? | /15 |
| Currency | Do commands actually work? | /15 |
| Actionability | Is everything copy-paste ready? | /15 |
A passing score is 70+. Below that, I’m probably answering the same questions repeatedly.
Scaling for Long Projects
The Reddit insight that stuck with me: “The point where minimal setups start to lose is longer projects spanning many sessions, when rebuilding context becomes the biggest time sink.”
For long-running projects, I add:
## Project State
- Current focus: Migrating from REST to GraphQL- Blocked: Waiting on API team for schema finalization- Recent decisions: Chose React Query over Apollo Client (see ADR-007)I only add this when I feel the pain of re-explaining context. Not before.
A Minimal Example
Here’s a complete minimal CLAUDE.md that works for most projects:
# My Project
React + TypeScript frontend with Node.js backend.
## Commands
| Command | Description ||---------|-------------|| `npm run dev` | Start both frontend and backend || `npm run build` | Production build || `npm test` | Run all tests |
## Architecture
```textsrc/ frontend/ # React app (Vite) backend/ # Express API shared/ # Shared types and utilitiesGotchas
- Run
npm run db:seedafter migrations in development - Frontend hot-reload sometimes misses CSS changes
That's it. 20 lines. Covers the essentials.
## When to Expand
I expand my CLAUDE.md when I notice these patterns:
1. **Claude asks the same question across sessions** - add to gotchas or architecture2. **Commands fail because Claude guessed wrong** - expand commands section3. **I explain project context to new team members** - that explanation belongs in CLAUDE.md4. **A debugging session revealed non-obvious behavior** - add to gotchas
The principle: add when you feel friction, not preemptively.
## Global vs Project Split
My global `~/.claude/CLAUDE.md` contains:
```markdown title="Global CLAUDE.md example"# Working Relationship
- Be concise. Avoid long-winded explanations.- Challenge my assumptions when I'm wrong.- Do things the right way, not the easy way.
# Tooling
- Prefer Edit tool over sed for file changes- Prefer Search tool over grep for finding code- Use Mermaid diagrams for complex systemsProject-level files contain only project-specific content. No overlap, no duplication.
The One Thing That Scales
After all the experimentation, the Reddit insight holds: “After 1000+ sessions the one thing that scales is the CLAUDE.md file.”
Hooks and plugins are powerful. But structured context that the model reads at session start is the foundation. Get that right first.
Start minimal. Add as you feel friction. Keep everything project-specific. That’s what works.
Final Words + More Resources
My intention with this article was to help others share my knowledge and experience. If you want to contact me, you can contact by email: Email me
Here are also the most important links from this article along with some further resources that will help you in this scope:
Oh, and if you found these resources useful, don’t forget to support me by starring the repo on GitHub!
Comments