📄 Configuration

The CLAUDE.md File Guide

What CLAUDE.md is, what to put in it, where to put it, and how to write one for your project type — with copy-paste examples.

What Is CLAUDE.md?

CLAUDE.md is a Markdown file that Claude Code reads at the start of every session. Its contents are injected directly into the model's context as project instructions — no commands needed, no special syntax beyond Markdown. Claude uses it to understand your project's conventions, commands, and constraints before touching any code.

Place it at the repo root alongside your package.json, Makefile, or go.mod. Claude Code loads it automatically every time you run claude in that directory.

Why it matters: Without a CLAUDE.md, Claude has to ask about your test runner, guess your code style, and risk modifying generated files. A good CLAUDE.md eliminates those friction points before the first message.

What to Put in CLAUDE.md

The rule: include only what Claude cannot derive by reading the code. Self-evident things (variable names, function signatures, directory structure) belong in the code itself, not CLAUDE.md.

1. Build, Test, and Lint Commands

## Commands

- Install deps: `npm ci`
- Run tests: `npm test` (requires Postgres running — see docker compose)
- Lint: `npm run lint`
- Type-check: `npm run typecheck`
- Build for prod: `npm run build`

2. Architecture Overview

## Architecture

Monorepo managed by Turborepo.
- `apps/api` — Express REST API (Node 20)
- `apps/web` — Next.js 14 frontend (App Router)
- `packages/db` — Prisma schema + generated client
- `packages/shared` — shared TypeScript types

The web app calls /api/* on the same domain in prod (rewrites in vercel.json).
In dev, NEXT_PUBLIC_API_URL=http://localhost:4000.

3. Code Conventions

## Code conventions

- Named exports only — never default exports
- All async functions must be typed with explicit return Promise<T>
- Database access goes through the repository layer (src/repositories/), never direct Prisma calls in route handlers
- No `console.log` in committed code — use the `logger` util (src/lib/logger.ts)
- Tests use vitest; place test files co-located as `*.test.ts`

4. Files and Directories to Leave Alone

## Do not modify

- `src/generated/` — auto-generated by `npm run generate`; run the command and commit output instead
- `migrations/` — create new migration with `npx prisma migrate dev --name <name>`, never edit existing files
- `public/icons/` — managed by the design team; file a Figma export request instead

5. Known Gotchas

## Gotchas

- The test suite hits a real Postgres: `docker compose up -d` before `npm test`
- Environment variables must be in `.env.local` (not .env) — dotenv is configured this way
- Import paths use `~` alias for `src/` — configure in tsconfig.json paths, not package.json
- The `user.createdAt` field is stored as UTC but displayed in the user's timezone — never compare raw timestamps to Date.now()

Complete Example CLAUDE.md Files

Python / FastAPI Project

# CLAUDE.md — Python API

## Commands
- Install: `pip install -e ".[dev]"`
- Test: `pytest -x` (stop on first failure)
- Lint: `ruff check . && ruff format --check .`
- Type-check: `mypy src/`
- Run dev server: `uvicorn app.main:app --reload`

## Architecture
- `src/app/` — FastAPI application, routers split by domain
- `src/app/models/` — SQLAlchemy ORM models
- `src/app/schemas/` — Pydantic request/response schemas (separate from ORM models)
- `src/app/services/` — business logic layer, called by routers
- Tests in `tests/` use pytest-asyncio with an in-memory SQLite test DB

## Conventions
- All endpoints return Pydantic response schemas, not raw ORM objects
- Use `Annotated` dependency injection for DB session: `db: Annotated[Session, Depends(get_db)]`
- Background tasks go in `src/app/tasks/` and are registered via Celery

## Do not modify
- `src/app/migrations/` — use `alembic revision --autogenerate` to create new migrations

Go Service

# CLAUDE.md — Go Service

## Commands
- Build: `go build ./cmd/server`
- Test: `go test ./... -race`
- Lint: `golangci-lint run`
- Generate mocks: `go generate ./...`

## Architecture
- Entry point: `cmd/server/main.go`
- HTTP layer: `internal/handler/` (chi router)
- Business logic: `internal/service/`
- Data layer: `internal/repository/` with interfaces for testability
- Generated code: `internal/mocks/` (do not edit, run go generate)

## Conventions
- Return errors, don't panic — only panic in init() for fatal misconfigs
- All repository methods take a `context.Context` as the first argument
- Structured logging with `slog` (Go 1.21+), key-value pairs only
- Package names match directory names — never alias imports

## Gotchas
- Integration tests require a real Postgres; set TEST_DATABASE_URL before running
- The Makefile `make test-unit` runs only unit tests (no DB dependency)

Monorepo with Sub-Package CLAUDE.md

Root CLAUDE.md:

# CLAUDE.md — Monorepo Root

## Layout
This is a pnpm workspace monorepo.
- `apps/` — deployable applications
- `packages/` — shared internal libraries
- `infra/` — Terraform and Kubernetes configs (do not touch without asking)

## Commands
- Install all: `pnpm install` (from root only)
- Run a package's tests: `pnpm --filter @acme/api test`
- Build all: `pnpm run build`

## Conventions
- Internal packages use `@acme/` scope
- Changesets manages versioning: `pnpm changeset` before merging a feature

Then apps/api/CLAUDE.md for API-specific notes, packages/ui/CLAUDE.md for component library notes, etc. Claude discovers them contextually.

CLAUDE.md Sections at a Glance

SectionInclude?Why
Test / lint / build commands✅ AlwaysClaude cannot guess your exact runner
Architecture overview✅ For non-trivial reposPrevents navigating wrong directories
Code style / conventions✅ Non-obvious ones onlyAvoids repeated corrections
Do-not-touch directories✅ AlwaysPrevents corrupting generated code
Known environment gotchas✅ Where relevantPrevents failed test runs
Variable / function names❌ SkipAlready in the code
Full feature descriptions❌ SkipClaude reads the code itself
Git history or PRs❌ SkipUse git log instead
Team org chart or roles❌ SkipIrrelevant to code tasks

Tips for Maintaining CLAUDE.md

Cost note: CLAUDE.md tokens are input tokens billed on every turn, but Claude Code's prompt caching means after the first request the file is cached at a 90% discount. A 1,000-token CLAUDE.md costs roughly $0.001 per message uncached, $0.0001 cached. See prompt-pricing.vercel.app for current token costs.

Frequently Asked Questions

What is CLAUDE.md in Claude Code?
CLAUDE.md is a Markdown file that Claude Code reads automatically at the start of every session. It injects project-specific instructions into the model's context — telling it which commands to run for tests, which code conventions to follow, which directories to avoid, and any gotchas specific to your codebase. Think of it as a persistent system prompt that travels with your repo.
Where should I put CLAUDE.md?
The primary location is the project root (wherever you run the claude command). Claude Code also reads a global ~/.claude/CLAUDE.md for user-level preferences, and nested CLAUDE.md files in subdirectories for component-specific notes. All discovered files are concatenated and injected at session start.
Does CLAUDE.md replace a system prompt?
It is the system prompt for project context. Claude Code composes its internal system prompt from several sources: its own built-in instructions, your CLAUDE.md content, and any memory files. For Claude SDK / API usage outside Claude Code, you manage the system prompt yourself — CLAUDE.md is a Claude Code CLI convention, not an API concept.
Can I have multiple CLAUDE.md files in one repo?
Yes. Place a root CLAUDE.md for the overall repo, and subdirectory CLAUDE.md files for packages or services. Claude Code discovers nested files contextually when it reads files in that directory. This is the recommended pattern for monorepos: root covers overall layout and tooling; each package covers its own test commands and conventions.
How long should CLAUDE.md be?
Under 500 lines is a good target. Every line consumes context tokens. Include only what Claude cannot derive by reading the code — non-obvious commands, historical decisions, external constraints. Anything evident from reading a file or running a command does not belong in CLAUDE.md.
Does Claude.md affect token cost?
Yes, but minimally due to prompt caching. A 1,000-token CLAUDE.md costs roughly $0.0001 per cached message at Claude Sonnet rates. Claude Code caches the system prompt aggressively — after the first request, subsequent requests pay 90% less for that content. Keep CLAUDE.md lean not just for cost but because shorter context means Claude attends more carefully to each instruction.

Explore More Claude Code Skills

⚡ Using Claude Code? 30 power prompts that 2× your output · £5 £3 first 10Get PDF £3 →