![]()
Every Claude Code session starts the same way. Before you type a single prompt, before Claude reads a single file, it loads your CLAUDE.md. This file shapes every decision Claude makes — what conventions it follows, what commands it runs, how it structures code. A well-written CLAUDE.md turns Claude into a team member who already knows your project. A poorly written one wastes tokens and gets ignored.
This guide covers everything: what CLAUDE.md is, where to put it, what to include, what to leave out, and how to maintain it as your project evolves.
CLAUDE.md is a markdown file that gives Claude Code persistent context about your project. Think of it as a briefing document — it tells Claude the things it can't infer from code alone. Your tech stack, build commands, naming conventions, architectural decisions, testing patterns, and workflow rules.
Claude reads CLAUDE.md at the start of every session. Unlike your conversation history (which resets between sessions) or your codebase (which Claude explores on demand), CLAUDE.md is always present. It's the one file guaranteed to be in Claude's context window every time you work together.
This makes it both powerful and expensive. Every token in your CLAUDE.md is a token Claude reads before you've typed a word. A 5,000-token CLAUDE.md costs 5,000 tokens on every single session. That's why the best CLAUDE.md files are concise, high-signal, and ruthlessly pruned.
Claude Code doesn't just read one CLAUDE.md. It loads multiple files from different locations, following a specific hierarchy. Understanding this hierarchy is key to organizing your configuration effectively.
| Location | Scope | Shared via Git? |
|---|---|---|
~/.claude/CLAUDE.md | Global (all projects) | No |
./CLAUDE.md | Project root | Yes |
./CLAUDE.local.md | Personal project notes | No (gitignore it) |
./packages/web/CLAUDE.md | Subdirectory | Yes |
| Parent directories up to git root | Monorepo root | Depends |
When you start Claude Code, it walks up the directory tree from your current working directory to the nearest git root, loading every CLAUDE.md it finds along the way. It also loads your global ~/.claude/CLAUDE.md.
Subdirectory CLAUDE.md files work differently. They don't load at startup. Instead, Claude picks them up on demand — when it reads or edits files in that subdirectory. This is important for monorepos where each package might have its own conventions.
When the same instruction appears in multiple files, specificity wins:
Personal > Project > Global
Your CLAUDE.local.md overrides CLAUDE.md, which overrides ~/.claude/CLAUDE.md. This lets your team share project-level rules while each developer keeps personal preferences separate.
The best CLAUDE.md files answer one question: what would Claude get wrong without this instruction? If Claude already does something correctly on its own, the instruction is noise.
Claude can't infer business logic or product intent from code alone. A brief summary at the top sets the right mental model.
# Project
SupaLaunch is a Next.js 14 starter kit for building SaaS applications.
Uses App Router, TypeScript, Tailwind CSS, Supabase (auth + database),
and Stripe for payments.
Two to three sentences is enough. Claude doesn't need your full product spec.
These are the highest-value instructions you can add. Claude uses them constantly, and getting them wrong wastes entire tool calls.
# Commands
- `npm run dev` — start dev server on port 3000
- `npm run build` — production build (runs type checking)
- `npm run test` — run Vitest test suite
- `npm run test:e2e` — run Playwright end-to-end tests
- `npm run lint` — ESLint check
- `npm run db:migrate` — run Supabase migrations
Only include conventions that Claude wouldn't follow by default. Don't tell Claude to "write clean code" or "use meaningful variable names" — it already does that.
# Conventions
- Use named exports, not default exports
- Components go in `src/components/{feature}/ComponentName.tsx`
- Server actions go in `src/app/{route}/actions.ts`
- Use Zod for all form validation
- Prefer server components; only add 'use client' when needed
- Use `cn()` utility for conditional Tailwind classes
Document the decisions that would take ten minutes to explain verbally. These prevent Claude from making reasonable-but-wrong choices.
# Architecture
- All database access goes through Supabase client, never raw SQL
- Auth uses Supabase SSR package (@supabase/ssr), not the older @supabase/auth-helpers
- Middleware handles auth token refresh (see src/middleware.ts)
- Row Level Security is enabled on all tables — never bypass it
- Environment variables: NEXT_PUBLIC_ prefix for client, plain for server
# Git
- Branch naming: `feature/description`, `fix/description`
- Commit messages: imperative mood, under 72 characters
- Always run `npm run lint && npm run test` before committing
- Never commit directly to main
This is the single highest-impact instruction you can add to any CLAUDE.md. Tell Claude how to check its own work.
# Verification
After making code changes, always run:
1. `npm run lint` to catch style issues
2. `npm run test` to verify nothing is broken
3. `npm run build` to check for type errors
When Claude knows how to verify its work, it catches its own mistakes and fixes them before you ever see the output. This one pattern measurably improves output quality across every task.
Knowing what to leave out is just as important as knowing what to put in. Overloaded CLAUDE.md files degrade Claude's performance — important rules get lost in the noise.
Don't tell Claude how to write TypeScript, Python, or JavaScript. It already knows. Instructions like "use const instead of let when the variable doesn't change" or "prefer async/await over .then()" are noise.
Never send an LLM to do a linter's job. If you want consistent formatting, use Prettier through a hook. If you want style enforcement, use ESLint. These tools are faster, cheaper, and more reliable than asking Claude to remember formatting rules.
{
"hooks": {
"PostToolUse": [
{
"matcher": "Edit|Write",
"command": "npx prettier --write \"$TOOL_INPUT_FILE_PATH\""
}
]
}
}
Hooks are deterministic. CLAUDE.md instructions are probabilistic. Use the right tool for the job.
Never put credentials in CLAUDE.md. Use environment variables and reference them by name if Claude needs to know they exist.
CLAUDE.md is not a wiki. If Claude needs to understand a complex system, link to the documentation or use an @import to pull in a separate file only when needed.
If something changes every week, it doesn't belong in a persistent config file. Use session-specific context or conversation prompts for volatile information.
There's roughly a 150-200 effective instruction budget before Claude's compliance drops off. The system prompt already uses about 50 of those. That leaves you around 100-150 instructions before things start getting ignored.
In practice, this means:
Every line should pass this test: would Claude make a mistake without it? If the answer is no, delete it.
You don't have to write your CLAUDE.md from scratch. The /init command scans your project and generates a starter file automatically.
cd your-project
claude
> /init
Claude examines your package files, configuration, directory structure, and source code, then produces a CLAUDE.md tailored to your project. The generated file typically includes:
Think of /init as a starting point. The generated file captures obvious patterns but misses nuances specific to your workflow. Review what Claude produces, delete what's redundant, and add what's missing.
A practical approach: run /init, then use Claude Code for a few sessions. Every time Claude does something wrong — uses the wrong command, puts a file in the wrong place, follows the wrong convention — add the correction to your CLAUDE.md. Over a few days, you'll have a config file that perfectly matches your workflow.
Monorepos benefit the most from CLAUDE.md's hierarchical loading. You can set global rules at the root and package-specific rules in subdirectories.
my-monorepo/
├── CLAUDE.md # Shared rules (linting, git, CI)
├── packages/
│ ├── web/
│ │ ├── CLAUDE.md # Next.js-specific conventions
│ │ └── src/
│ ├── api/
│ │ ├── CLAUDE.md # Express/Fastify-specific conventions
│ │ └── src/
│ └── shared/
│ ├── CLAUDE.md # Shared library conventions
│ └── src/
# Monorepo
pnpm workspaces monorepo. Packages in `packages/`.
# Commands
- `pnpm install` — install all dependencies
- `pnpm -r build` — build all packages
- `pnpm -r test` — test all packages
# Rules
- Changes to `packages/shared` require running tests in all consuming packages
- Use workspace protocol for internal dependencies: `"@company/shared": "workspace:*"`
- Never install dependencies at the root unless they're dev tools
# packages/web
Next.js 14 App Router frontend.
# Commands
- `pnpm dev` — start dev server (port 3000)
- `pnpm build` — production build
- `pnpm test` — run Vitest
# Conventions
- Pages go in `src/app/{route}/page.tsx`
- Components go in `src/components/{feature}/`
- All API calls go through `src/lib/api-client.ts`
When Claude works on a file in packages/web/, it loads both the root CLAUDE.md and the package-level one. Root rules apply everywhere; package rules apply only when Claude is working in that context.
CLAUDE.md supports an import syntax that lets you pull in content from other files. Instead of cramming everything into one file, you can modularize your instructions.
# Project
See @README.md for project overview.
# Conventions
Follow the rules in @docs/coding-standards.md.
Follow the git workflow in @docs/git-workflow.md.
Imports resolve relative to the file containing them, not your working directory. They're recursive up to five levels deep, so imported files can import other files.
This is useful for keeping your CLAUDE.md short while giving Claude access to detailed documentation on demand. It's also the bridge to multi-tool setups — if your team maintains an AGENTS.md for cross-tool compatibility, your CLAUDE.md can import it:
@AGENTS.md
# Claude-Specific
Use plan mode for changes under `src/billing/`.
One caveat: imported files are silently truncated at 2,000 lines. Keep imported content focused.
For larger projects, individual instructions in CLAUDE.md can be broken out into separate files in the .claude/rules/ directory. Every .md file in this directory is automatically loaded.
.claude/
├── rules/
│ ├── testing.md
│ ├── api-conventions.md
│ └── frontend/
│ └── react-patterns.md
The real power is path-scoped rules. Add YAML frontmatter to limit when a rule loads:
---
paths:
- "src/api/**/*.ts"
- "src/middleware/**/*.ts"
---
# API Rules
- All endpoints must validate input with Zod
- Always return proper HTTP status codes
- Include rate limiting on public endpoints
This rule only loads when Claude reads files matching the glob patterns. It keeps API-specific rules out of the global context when Claude is working on the frontend, saving tokens and reducing noise.
Every developer has preferences that shouldn't be in the shared config. Maybe you use vim keybindings, prefer verbose test output, or work on a specific part of the codebase. That's what CLAUDE.local.md is for.
Create it in your project root alongside CLAUDE.md:
# Personal
- I primarily work on the payments module (src/lib/payments/)
- When suggesting commands, use verbose flags (-v) so I can see details
- I prefer explicit types over inferred types
- My local Supabase runs on port 54321
Add CLAUDE.local.md to your .gitignore so it never gets committed. Claude loads it alongside the main CLAUDE.md, and its instructions take precedence over project-level ones.
If your team uses multiple AI coding tools, you'll encounter different configuration file formats.
| File | Tool | Hierarchy | Shared via Git |
|---|---|---|---|
CLAUDE.md | Claude Code | Multi-level (global, project, subdirectory, personal) | Project-level yes |
.cursorrules | Cursor | Single file per project | Yes |
.github/copilot-instructions.md | GitHub Copilot | Project + scoped instructions | Yes |
AGENTS.md | Cross-tool (emerging standard) | Varies by tool | Yes |
CLAUDE.md has the most sophisticated hierarchy of any AI config file. The multi-level loading, subdirectory support, and personal overrides make it well-suited for complex projects and monorepos.
If your team uses multiple AI tools, consider maintaining a shared AGENTS.md as your single source of truth, then having tool-specific files reference the shared rules. This avoids duplicating instructions across CLAUDE.md, .cursorrules, and copilot-instructions.md.
When your context window fills up, Claude Code runs auto-compaction to summarize the conversation and free tokens. Your CLAUDE.md survives compaction — it reloads fresh every time. But the context around it doesn't.
You can customize compaction behavior directly in your CLAUDE.md:
# Compaction
When compacting, always preserve:
- The full list of modified files
- Any test commands that were run and their results
- Architecture decisions made during this session
This ensures critical context survives summarization even when older conversation history gets compressed.
A CLAUDE.md that never changes becomes stale. Instructions accumulate, some become redundant, others start conflicting with how the project actually works.
Every few weeks, ask Claude to review your CLAUDE.md:
Review my CLAUDE.md file. Identify any instructions that are redundant,
conflicting, or that you would follow correctly without being told.
Suggest what to remove.
Claude will flag instructions it already follows by default, rules that contradict each other, and sections that have grown too verbose. This is one of the most effective maintenance practices for keeping your config lean.
The best CLAUDE.md files evolve through use. Here's the practical workflow:
For shared projects, treat CLAUDE.md like any other code file. Changes go through pull requests. Team members can propose new rules, and the team decides what belongs in the shared config versus personal CLAUDE.local.md files.
If you use the Claude Code GitHub Action, you can update CLAUDE.md directly from PR comments:
@claude add to CLAUDE.md: always use string literal unions instead of enums
Claude updates the file and commits the change as part of the PR.
Here's a complete template you can adapt for your project. It stays under 80 lines and covers the essentials.
# Project
[One-sentence description of what this project does]
Tech stack: [framework], [language], [database], [key libraries]
# Commands
- `[dev command]` — start dev server
- `[build command]` — production build
- `[test command]` — run test suite
- `[lint command]` — lint check
# Structure
- `src/app/` — pages and routes
- `src/components/` — React components
- `src/lib/` — utilities and helpers
- `src/types/` — TypeScript type definitions
# Conventions
- [Convention Claude wouldn't follow by default]
- [Convention Claude wouldn't follow by default]
- [Convention Claude wouldn't follow by default]
# Architecture
- [Key decision that prevents wrong assumptions]
- [Key decision that prevents wrong assumptions]
# Git
- Branch naming: [pattern]
- Commit messages: [style]
- Run tests before committing
# Verification
After changes, run:
1. `[lint command]`
2. `[test command]`
3. `[build command]`
Notice what's missing: no code style rules (use a linter), no basic language conventions (Claude knows them), no long explanations (link to docs instead). Every line earns its place by preventing a specific mistake.
~/.claude/CLAUDE.md for global rules, and CLAUDE.local.md for personal overrides. Subdirectory files load on demand for monorepos./init to generate a starter file, then refine through use. Add corrections when Claude gets something wrong, and prune monthly to remove rules Claude follows without being told.Production-ready CLAUDE.md templates, MCP server configs, custom hooks, and battle-tested workflows. Stop configuring, start building.