Last updated: May 2026 · Covers Claude Code v2.1.x
CLAUDE.md is the configuration file Claude Code reads at the start of every session. It loads into the system prompt before your first message, giving Claude persistent knowledge about your project — build commands, coding standards, architectural constraints, forbidden patterns — without you having to re-explain anything each time.
This guide covers how the scoping system works, what belongs in the file, what to leave out, and ready-to-copy templates for common project types.
Claude Code sessions are stateless by design. Each new conversation starts with a blank context window. CLAUDE.md bridges sessions: whatever you put in it, Claude has from message one.
This is the same problem that Cursor Rules, Windsurf Rules, and Cline Rules solve for their respective tools. The implementation differs — CLAUDE.md has a layered scoping system that none of the others have — but the intent is identical: stop repeating yourself every session.
Unlike .cursorrules or .clinerules, CLAUDE.md is not simply concatenated into the prompt and ignored. Claude Code has a layered discovery system with multiple scopes that load in order. Understanding this system is what separates a working configuration from one that gets silently ignored.
Claude Code loads CLAUDE.md files from five locations, in this order:
1. Global — ~/.claude/CLAUDE.md
Your personal defaults that apply across every project on your machine. Put your general coding preferences, preferred output style, and personal workflow rules here. This is never committed to any repository.
2. Organization (Enterprise only) — managed settings pushed via claude_desktop_config.json
Enforced rules that cannot be overridden by project or local files. Useful for team-wide security policies, data handling rules, or approved tool lists.
3. Project root — CLAUDE.md in the root of your repository
The primary project configuration. Committed to the repo and shared with anyone who uses Claude Code on the project. This is the file most developers mean when they say "CLAUDE.md."
4. Local — CLAUDE.local.md in the project root
Personal overrides on top of the project configuration. Always in .gitignore — never committed. Use this for your own preferences that differ from the team (verbose output, specific shortcuts, personal API keys for tools).
5. Subdirectory — CLAUDE.md in any subdirectory
When Claude is working in a subdirectory, it also reads any CLAUDE.md in that directory. Useful for monorepos where different packages have different conventions.
All applicable files are loaded and merged. Project settings override global, local settings override project, and so on.
Claude Code has two configuration mechanisms and they serve different purposes.
CLAUDE.md provides advisory instructions. Claude reads them and tries to follow them, using judgment about when and how to apply them. Flexible and context-aware.
Hooks (.claude/settings.json) provide deterministic shell commands that run at specific events — PostToolUse, PreToolUse, Notification, Stop, and others. Guaranteed execution regardless of what Claude decides.
The practical rule: use CLAUDE.md for anything that requires judgment. Use hooks for anything that must happen every time without exception.
If a lint check is already in a PostToolUse hook, do not also put "run ESLint after edits" in CLAUDE.md. You will get conflicting signals: the hook runs automatically, and Claude also tries to run it manually. Pick one mechanism per behavior.
A brief, factual description of what the codebase is. Not marketing copy — just enough for Claude to understand the domain and the tech stack without reading the entire repository.
## Project
This is a multi-tenant SaaS billing platform built with Next.js 15 (App Router),
TypeScript, Prisma (PostgreSQL), and Stripe. The frontend is in /app, the API
routes are in /app/api, and background jobs run via BullMQ in /workers.
The single most important section. Claude cannot run tests if it does not know the command. Specify exactly how to build, test, and check the project.
## Commands
- Build: `npm run build`
- Test: `npm test` (all tests) or `npm test -- --testPathPattern=auth` (specific)
- Type check: `npm run typecheck`
- Lint: `npm run lint`
- Dev server: `npm run dev`
All tests must pass before marking any task complete. TypeScript errors are
blocking — do not leave any.
Specific, enforceable rules. Not vague principles ("write clean code") but concrete decisions ("use async/await, never .then() chains").
## Code standards
- TypeScript strict mode is enabled — never use `any`
- Use `async/await`, not `.then()` chains
- All new functions must have JSDoc comments
- Error handling: always catch and handle, never swallow errors silently
- Imports: absolute paths using `@/` alias, not relative paths from deep directories
- No console.log in committed code — use the `logger` utility from `src/lib/logger`
What Claude should know about how the codebase is structured to avoid making changes in the wrong layer.
## Architecture
- API routes handle request validation and call service functions — no business
logic in route handlers
- Database access only through Prisma client in /lib/db — never raw SQL
- Authentication is handled by NextAuth — do not write custom auth logic
- All external API calls go through /lib/clients — never fetch() directly in
components or routes
Explicit prohibitions are more reliable than hoping Claude infers them from the rest of the file.
## Never do
- Do not use `@ts-ignore` or `@ts-expect-error`
- Do not modify the Prisma schema without explicit instruction — schema changes
require a migration
- Do not use `eval()` or `Function()` constructor
- Do not commit `.env` values or API keys
- Do not install new dependencies without asking first
Tell Claude what "finished" means so it knows when to stop.
## Done means
- Code builds without errors
- All existing tests pass (`npm test`)
- TypeScript reports no errors (`npm run typecheck`)
- Lint passes with no warnings (`npm run lint`)
- If adding a new function with external dependencies, a test exists for it
Anything Claude already does correctly. If Claude consistently follows a behavior without being told, adding an instruction for it wastes token budget and buries the rules that actually matter.
Redundant explanations. Do not explain why a rule exists unless the reason changes what Claude should do in edge cases. "Do not use any" is enough — "Do not use any because our team values type safety" adds nothing.
Vague principles. "Write maintainable code" gives Claude nothing to act on. "Functions should be under 40 lines; extract helpers if longer" is actionable.
Long context that belongs in code comments. If a function has unusual behavior that needs explanation, put it in a code comment — not in CLAUDE.md. CLAUDE.md is for project-wide rules, not specific implementation notes.
The official Claude Code docs make this point directly: if your CLAUDE.md is too long, Claude ignores half of it because important rules get buried in noise. Ruthlessly prune. Target under 500 words for a focused, effective file.
Over-specifying. A 2,000-word CLAUDE.md is almost always worse than a 400-word one. Long files cause critical rules to be treated with the same weight as trivial preferences.
Duplicating hooks. If a behavior is enforced by a hook, remove it from CLAUDE.md. Dual enforcement creates conflicts and confusing agent behavior.
No stop condition. If you do not tell Claude what "done" means, it decides for itself — often stopping too early or running in circles fixing one issue that reveals another. Explicit pass/fail criteria are the single biggest reliability improvement most CLAUDE.md files are missing.
Committing CLAUDE.local.md. Personal preferences in .gitignore stay off the repository. If your local file has API keys, debug settings, or personal shortcuts, it must never be committed.
Generic project overview. "This is a web app" is not useful context. "This is a Next.js 15 App Router project with Prisma and a PostgreSQL database hosted on Supabase" is.
## Project
Next.js 15 App Router, TypeScript strict, Prisma + PostgreSQL, Tailwind CSS.
## Commands
- Build: `npm run build`
- Test: `npm test`
- Typecheck: `npm run typecheck`
- Lint: `npm run lint`
- Dev: `npm run dev`
## Standards
- No `any` types
- async/await only, no .then()
- Absolute imports via @/ alias
- No console.log — use logger from @/lib/logger
## Architecture
- Business logic in /lib/services — not in route handlers or components
- DB access only via Prisma client in @/lib/db
## Never
- Modify schema.prisma without explicit instruction
- Install new packages without asking
- Use @ts-ignore
## Done
Build passes, tests pass, no TypeScript errors, lint clean.
## Project
FastAPI REST API, Python 3.12, SQLAlchemy + PostgreSQL, pytest, ruff for linting.
## Commands
- Test: `pytest`
- Lint: `ruff check .`
- Format: `ruff format .`
- Type check: `mypy .`
- Dev: `uvicorn main:app --reload`
## Standards
- Type hints on all function signatures
- Pydantic models for all request/response schemas
- No mutable default arguments
- Dependency injection via FastAPI Depends()
## Architecture
- Routes in /api/routes — thin, call service functions only
- Business logic in /services
- DB models in /models, schemas in /schemas
## Never
- Direct DB queries in route handlers
- Bare `except:` without specifying exception type
## Done
pytest passes, ruff reports no errors, mypy reports no errors.
In a monorepo, put a lean global CLAUDE.md at the root with shared conventions, and a package-specific CLAUDE.md in each subdirectory:
Root CLAUDE.md:
## Repository structure
Monorepo using Turborepo. Packages in /packages, apps in /apps.
Shared config in /config.
## Global rules
- All packages use TypeScript strict
- Run `turbo build` to build all packages
- Run `turbo test` to test all packages
- Never cross-import between app packages — use shared packages in /packages
/apps/api/CLAUDE.md:
## This package
Express API, connects to the shared @repo/database package.
Test command: `npm test` (from this directory)
Do not import from @repo/web — only from @repo/database and @repo/utils.
When Claude Code uses subagents — spawning parallel workers for different parts of a task — each subagent inherits the project CLAUDE.md. You can also pass additional instructions to specific subagents at invocation time.
For multi-agent workflows, add a brief section to CLAUDE.md describing how agents should coordinate:
## Agent coordination
When using subagents, assign one agent per logical module — do not split work
within the same file across multiple agents. Each agent should run its own
test pass before reporting done. Main agent merges results only after all
subagents confirm passing tests.
After writing or updating CLAUDE.md, run a short verification session:
If Claude cannot answer questions 1 or 2 accurately from a cold start, your CLAUDE.md is either missing those sections or too long to be parsed effectively.
copilot-instructions.md reference.aider.conf.yml and conventions filesconfig.json and prompt customizationAGENTS.md, which Claude Code also reads