How to Write a CLAUDE.md That Actually Works
By Tyler Cyert
The difference between a productive Claude Code session and a frustrating one is almost always the CLAUDE.md. A well-written instruction file gives Claude everything it needs to work autonomously. A bad one forces you to re-explain context, correct mistakes, and fight against the agent instead of working with it.
This guide goes beyond the basics covered in our CLAUDE.md overview and focuses on the practical craft of writing instructions that actually work.
Start with the Five Essentials
Every CLAUDE.md needs these five sections. Skip any of them and you will spend time answering questions that should have been pre-answered:
1. Project Description (2-3 sentences)
What the project does, who it serves, and its current state. This prevents the agent from making wrong assumptions about purpose and scope.
Not this: "A web application." But this: "E-commerce admin dashboard for managing product catalog, orders, and customer accounts. Currently in production with 200 daily active users. Built for internal operations team."
2. Stack (bulleted list)
Every technology the project uses. Be specific about versions when they matter.
- Runtime: Node.js 22, TypeScript 5.7 (strict mode)
- Framework: Next.js 15 (App Router)
- Database: PostgreSQL 16 via Drizzle ORM
- Styling: Tailwind CSS v4
- Testing: Vitest + Playwright
- Package manager: pnpm
3. Build Commands
How to run every common operation. Do not assume the agent knows your tooling.
pnpm dev— start dev server on port 3000pnpm build— production buildpnpm test— run unit testspnpm test:e2e— run end-to-end testspnpm lint— check lintingpnpm db:push— push schema changes
4. Architecture (directory map)
Key directories and what they contain. Not every folder — just the ones the agent needs to navigate.
src/app/— Next.js App Router pages, layouts, and API routessrc/components/— React components organized by featuresrc/lib/— Shared utilities, database client, business logicsrc/db/— Drizzle schema, migrations, and seed scriptstests/— Playwright e2e tests
5. Code Style (3-7 rules)
The conventions that differ from standard defaults. Do not list things the agent already knows — focus on your project-specific choices.
- Use
@/import alias for all src/ imports - Named exports only — no default exports except page components
- Prefer server components — only add
use clientfor interactivity - File names in kebab-case, component names in PascalCase
- Never commit .env files — use .env.example for documentation
Writing Rules That Work
Be Imperative, Not Descriptive
Not this: "The project uses Tailwind for styling." But this: "Use Tailwind utility classes for all styling. Do not create CSS files."
The first is informational. The second is an instruction the agent can follow.
Include the Why
Not this: "Never modify files in drizzle/." But this: "Never modify files in drizzle/ — these are generated migration files. Editing them after they have been applied causes schema drift."
The "why" helps the agent make judgment calls in edge cases.
State the Negative
Not this: "Use the database client." But this: "All database queries must go through src/lib/db.ts. Never write raw SQL. Never import the postgres driver directly."
Telling the agent what not to do is as important as telling it what to do. Agents will take creative approaches unless you close off the wrong paths.
Staying Under 200 Lines
The 200-line rule is practical, not arbitrary. Past 200 lines, your CLAUDE.md competes with itself for the agent's attention. Here is how to stay lean:
Extract to Rules
File-specific conventions should be rules, not CLAUDE.md sections. If an instruction only matters when working with React components, move it to a rule with the glob src/components/**/*.tsx.
Extract to Skills
Procedures that you invoke explicitly should be skills. "How to deploy" does not need to load every session — make it a /deploy skill.
Remove the Obvious
If it is a default behavior for your stack, do not repeat it. You do not need to tell Claude to use semicolons in TypeScript if your ESLint config already enforces it.
Merge Similar Rules
Five rules about error handling can usually be one rule: "All errors use the AppError class from src/lib/errors.ts. API routes return { error, code } format. Log server errors with request context. Never expose stack traces to clients."
Testing Your CLAUDE.md
The New Session Test
Start a fresh Claude Code session and give it a task without any additional context. Does it:
- Know what the project does?
- Use the right build commands?
- Follow your naming conventions?
- Put files in the right directories?
If it asks questions your CLAUDE.md should have answered, update the file.
The New Developer Test
Have someone unfamiliar with the project read your CLAUDE.md. Can they understand:
- What the project does?
- How to run it?
- Where to find things?
- What conventions to follow?
A good CLAUDE.md doubles as a quick-start guide for humans too.
CLAUDE.md as a Living Document
Your CLAUDE.md should evolve with your project:
- After a new convention — add it
- After repeated corrections — formalize the rule
- After a refactor — update the architecture section
- After growing past 200 lines — extract into rules and skills
Version control it. Review changes in PRs. It is as important as your codebase because it shapes how AI writes your code.
Generating CLAUDE.md with DotBox
Starting a CLAUDE.md from scratch is straightforward for simple projects. But coordinating it with settings.json, rules, skills, and agent definitions takes effort — especially ensuring they reference each other correctly. DotBox has your agent write them together. Draw your agents and skills, copy the setup prompt, and Claude Code writes a CLAUDE.md that lists every agent, the flow between them and the skills, alongside the files it points to — one coordinated directory structure.