CLAUDE.md Guide
CLAUDE.md is the single most leverage point in your Claude Code setup. A well-written CLAUDE.md gives Claude the same onboarding information a senior engineer would need — project structure, key commands, invariants, and gotchas — so it starts every session with full context instead of reading code from scratch.
How CLAUDE.md Works
Claude Code reads CLAUDE.md automatically at the start of every session, before you type anything. It's injected as part of the system prompt. This means:
- Every new conversation starts with the same context — no re-explaining architecture
- Every team member's Claude sessions share the same conventions
- The context is stable across Claude model upgrades
Claude Code also looks for CLAUDE.md in parent directories (up to the git root) and in subdirectories relevant to the current task. In a monorepo, you can have one per package.
What to Include
| Section | What to write | Why |
|---|---|---|
| Project overview | 1–2 sentences: what it does, who uses it, scale | Orients Claude so it makes sensible defaults |
| Architecture | Tech stack, folder layout, module boundaries | Prevents Claude from suggesting wrong frameworks |
| Dev commands | Exact commands to run tests, linting, dev server | Claude will run these automatically without asking |
| Critical invariants | Rules that must never be violated (e.g., no DB calls in service layer) | Claude won't violate them even when it seems locally reasonable |
| Do Not list | Explicit prohibitions: never push --force, never mock DB in tests | Highest-priority instructions — Claude treats these as hard rules |
| Danger zones | Files/dirs that need extra caution (auth, migrations) | Claude will ask before touching these |
Minimal Solo Project Template
# my-saas-app SaaS app for tracking freelance invoices. ~200 users, solo dev. ## Stack - Next.js 14 (App Router), TypeScript, Tailwind - Prisma + PostgreSQL (dev: Docker on port 5432) - Auth: NextAuth.js v5 with GitHub OAuth - Payments: Stripe (test mode in dev) ## Commands - `npm run dev` — start dev server (port 3000) - `npm test` — vitest unit + integration tests - `npx prisma studio` — DB GUI (port 5555) - `npx prisma db push` — apply schema changes to dev DB - `npm run build` — production build + type check ## Conventions - All DB access goes through `src/lib/db/` repositories - API routes in `src/app/api/` — one file per resource - Never use `any` in TypeScript - Commit style: conventional commits (feat/fix/chore/docs) ## Do Not - Never commit `.env.local` - Never add `console.log` to files in `src/app/api/` - Never bypass NextAuth middleware in tests — use `getServerSession` with mocked session
Full Team Template
# acme-platform B2B SaaS platform for inventory management. 500 enterprise customers. Monorepo: Next.js frontend + FastAPI backend + shared TypeScript types. ## Architecture - `packages/web/` — Next.js 14 frontend (TypeScript, Tailwind) - `packages/api/` — FastAPI (Python 3.12), Alembic migrations - `packages/shared/` — shared Pydantic + Zod schemas (auto-generated) - DB: PostgreSQL 16 (dev: Docker), Redis for job queue - Auth: Auth0 (JWT, roles: admin/member/viewer) - Queue: Celery + Redis (workers in `packages/api/workers/`) - Infra: AWS ECS + RDS, managed by Terraform in `/infra` ## Services Map - `packages/api/src/routers/` — FastAPI route handlers - `packages/api/src/services/` — business logic (NO DB calls here) - `packages/api/src/repositories/` — all DB access goes through here - `packages/api/src/models/` — SQLAlchemy models - `packages/api/src/schemas/` — Pydantic schemas (source of truth for API contracts) ## Dev Commands ```bash make dev # Start all services via docker-compose make test # pytest (backend) + vitest (frontend) make migrate # Run pending Alembic migrations make lint # ruff + mypy + eslint + tsc make gen-types # Regenerate shared TypeScript types from Pydantic schemas ``` ## Critical Invariants - Service layer NEVER imports from routers layer (dependency direction is strict) - All DB access goes through repositories — never SQLAlchemy in routers/services directly - Celery tasks MUST be idempotent (they may execute more than once on retry) - Never store PII in Redis (only entity IDs, never names/emails/addresses) - All API responses must match a Pydantic schema in `src/schemas/` — no ad-hoc dicts ## Code Style - Python: ruff formatting, type hints on all public functions, no `*` imports - TypeScript: strict mode, no `any`, absolute imports via `@/` alias - Commits: conventional commits — feat/fix/chore/docs/refactor/test - Branch naming: `/ -short-description` - Test co-location: `src/routers/users_test.py` next to `users.py` ## Do Not - `git push --force` to main — never, without explicit approval - Mock the database in tests — we use TestContainers (real Postgres in CI) - Add `print()` or `console.log` to any non-test file - Touch `packages/api/src/auth/` without a security review comment in the PR - Modify Terraform files without asking — infra changes need team sign-off - Create DB migrations that are not backward-compatible with the previous release ## Danger Zones (always ask before modifying) - `packages/api/src/auth/` — Auth0 integration, token validation, RBAC - `infra/` — Terraform modules for production infrastructure - `packages/api/alembic/versions/` — database migrations (must be backward-compatible) - `packages/api/src/workers/billing_jobs.py` — Stripe billing worker (affects revenue)
Monorepo: Nested CLAUDE.md Pattern
For large monorepos, put a lean root CLAUDE.md with global context and detailed CLAUDE.md files in each package. Claude Code reads both.
my-monorepo/ ├── CLAUDE.md ← global: team conventions, shared commands, org-wide Do Not list ├── packages/ │ ├── api/ │ │ └── CLAUDE.md ← api-specific: DB schema, FastAPI patterns, migration rules │ ├── web/ │ │ └── CLAUDE.md ← web-specific: component library, state management, routing patterns │ └── shared/ │ └── CLAUDE.md ← shared: code-gen workflow, schema contract rules
Root CLAUDE.md stays under 100 lines — only things true for every package. Package CLAUDE.md goes into detail for that package's patterns and gotchas.
What NOT to Put in CLAUDE.md
- API keys, passwords, connection strings — these belong in
.env.local(gitignored) - Task-tracking notes — "TODO: fix the auth bug" → use GitHub Issues instead
- In-progress work — CLAUDE.md is stable context, not a scratchpad
- Documentation Claude can infer — if Claude can read it from the code, don't duplicate it
- Frequently-changing data — stale info in CLAUDE.md is actively harmful
- Long prose explanations — bullet lists and code blocks, not paragraphs
Keeping CLAUDE.md Current
A stale CLAUDE.md is worse than none — Claude will follow outdated instructions confidently. Treat it like a README:
- Add an update to the CLAUDE.md PR checklist when commands or architecture change
- Review it in onboarding sessions — if a new engineer finds it confusing, Claude will too
- When Claude gives a surprising response, check if CLAUDE.md has conflicting or outdated info
FAQ
What is CLAUDE.md in Claude Code?
CLAUDE.md is a special Markdown file that Claude Code reads automatically at the start of every session. It lets you encode persistent context about your project — architecture, dev commands, code conventions, and things Claude should never do — so you don't have to re-explain them every conversation.
How long can a CLAUDE.md file be?
Practically, keep CLAUDE.md under 500 lines (~4 KB). Claude Code reads it into the context window at session start, so every line costs tokens on every request. The most valuable sections are: project overview, architecture summary, critical dev commands, and a "Do Not" list.
Can I have multiple CLAUDE.md files in a monorepo?
Yes. Claude Code supports nested CLAUDE.md files. Place a root CLAUDE.md with global project context, then add package-level CLAUDE.md files in subdirectories. Claude Code reads both the root and the most relevant subdirectory file based on the active session context.
What should I NOT put in CLAUDE.md?
Never put secrets, API keys, passwords, or internal URLs. Also avoid: lengthy docs Claude can derive from reading the code, task-tracking notes, in-progress work, and frequently-changing information that will go stale.
Does CLAUDE.md work in Claude.ai web interface?
No. CLAUDE.md is specific to the Claude Code CLI. The Claude.ai web interface does not read CLAUDE.md files. For similar persistent context in the web interface, use Projects with a custom system prompt.