Writing Effective CLAUDE.md Files
When you open a project in Claude Code, it automatically reads any CLAUDE.md file it finds — in the current directory, parent directories, and sub-directories. This file is your opportunity to give Claude persistent, project-specific context that would otherwise require re-explaining in every session.
A well-written CLAUDE.md makes Claude Code dramatically more useful. A poorly written one — too long, too obvious, or outdated — wastes tokens and can actually degrade responses by adding noise to context.
What CLAUDE.md Files Are
CLAUDE.md is a plain Markdown file that Claude Code reads automatically at the start of every session. It functions as persistent system context: everything in it is available to Claude before you type a single message.
Claude Code looks for these files in a specific order:
~/.claude/CLAUDE.md— User-level global instructions{project-root}/CLAUDE.md— Project-level instructions (checked into the repo)- Sub-directory
CLAUDE.mdfiles when working in specific subdirectories
In a monorepo, you might have a root CLAUDE.md for shared conventions plus individual CLAUDE.md files in each app directory for app-specific details. Claude reads all of them and merges the context.
What to Include
The goal is to give Claude information it cannot easily discover itself, or that would take several tool calls to infer. Good candidates:
Build and dev commands — The exact commands to run the project, lint, test, and build. Claude should never have to guess whether it's npm test, yarn test, pnpm test, or vitest run.
## Commands
- Dev: `npm run dev` (localhost:3000)
- Test: `npm test` (Jest with ts-jest)
- Lint: `npm run lint` (ESLint + Prettier check)
- Build: `npm run build`
- Single test file: `npm test -- auth.test.ts`
Project-specific conventions — Naming patterns, import alias configuration, folder structure, and where to find things. If your project uses @/* as a path alias for ./src/*, say so. If feature code goes in src/features/ not src/components/, say so.
Testing patterns — Where tests live, what framework and matchers are in use, whether tests require a running database, and any setup/teardown to be aware of.
Known gotchas — Things that aren't obvious from reading the code. A static export limitation that breaks if you use cookies(). A custom ESLint rule that requires a specific import order. A CI skip flag needed for certain commits.
Tech stack specifics — Framework version, major libraries, and any non-standard choices that affect how code should be written. "We use Tailwind v4 with @theme directive, not v3 configuration" is useful. "We use React" is not.
What NOT to Include
Obvious things Claude already knows — Don't explain TypeScript syntax, React hooks basics, or how git works. Every token spent on basics is a token not available for actual project context.
Entire codebases — Don't paste full files into CLAUDE.md. Claude Code can read files directly with its tools. Use CLAUDE.md to point Claude at files, not to inline them.
Frequently changing details — If a piece of information changes weekly (current sprint goals, temporary workarounds, in-progress migrations), it doesn't belong in a committed file. It becomes stale and misleading.
Sensitive information — Never put API keys, credentials, or production database URLs in CLAUDE.md. It's committed to the repo.
Things that are self-evident from the codebase — If your folder structure makes the architecture obvious, don't re-describe it. If you have extensive JSDoc comments, don't duplicate them in CLAUDE.md.
Monorepo Patterns
For monorepos, the recommended structure is a two-level approach:
Root CLAUDE.md — Cross-app conventions:
- How the monorepo is structured (workspace layout)
- Root-level scripts (
turbo build,turbo dev --filter=@app/name) - Shared tooling (TypeScript config, ESLint base config, Prettier)
- Port assignments if multiple apps run concurrently
- Conventions that apply everywhere (commit message format, PR process)
App-level CLAUDE.md — App-specific details:
- App's specific tech stack and major dependencies
- Database schema and migration process
- App-specific build commands and environment variables
- File conventions unique to that app
This separation keeps root-level context concise and prevents app-specific details from polluting the context when working in other apps.
Real Examples of Effective CLAUDE.md Sections
Here is a CLAUDE.md template with annotated sections demonstrating what to include and why each section earns its place:
Exercise: Write a CLAUDE.md for a Hypothetical Project
Key Takeaways
- CLAUDE.md is automatically read by Claude Code at session start — it provides persistent project context without requiring any prompt setup
- The highest-value sections are: exact dev/test/build commands, non-obvious conventions, and important constraints or gotchas
- Avoid padding with obvious information, large code pastes, or frequently changing details — every token should earn its place
- In monorepos, use a two-level structure: root CLAUDE.md for cross-app conventions, app-level CLAUDE.md files for app-specific details
- A good CLAUDE.md lets Claude operate as if it has worked in the codebase before — it knows where things are, how to run them, and what to avoid
Discussion
Sign in to join the discussion.

