Skip to content

Chapter 4 of 205 min readBy Deepak GuptaPublished

The CLAUDE.md Masterclass

CLAUDE.md is the only project knowledge Claude Code carries into every session. Teams that treat it as production code, with review and history, get consistent output. Teams that let it rot get a different engineer every morning.

How CLAUDE.md files load

Claude Code reads several memory files and merges them.

File Loaded Typical content
~/.claude/CLAUDE.md Every session, every project Your personal style and preferences
./CLAUDE.md (repo root) Every session in this repo Team conventions and commands
./CLAUDE.local.md Every session, not committed Your local paths, sandbox URLs
packages/x/CLAUDE.md When Claude works in that directory Rules specific to that package

You can also import other files from a CLAUDE.md with an @ reference, for example @docs/architecture.md. That keeps the root file short while still pointing at deeper material.

Use /memory to open and edit these files from inside a session.

The eight sections of a strong CLAUDE.md

  1. Purpose. Two sentences on what the codebase does and who uses it.
  2. Stack. Languages, frameworks, and versions, including the non-obvious ones. "TypeScript" is not enough. "TypeScript 5.x, strict mode, Node 22, ESM only" is.
  3. Commands. Exact commands for install, dev server, test (all and single file), lint, typecheck, and build.
  4. Code conventions. Only the rules that differ from community defaults: named exports only, error handling style, logging library, naming patterns.
  5. Architecture. Where business logic, API handlers, data access, and shared types live. What may import what.
  6. Do not touch. Traps and tripwires: generated files, the legacy module mid-migration, the config that breaks production if reordered.
  7. Workflow. How to verify a change, when to commit, branch naming, commit message format, PR expectations.
  8. Security rules. Non-negotiables for secrets, input handling, logging, and auth. Chapter 10 expands this section.

A worked example

# Billing Service

Handles subscriptions, invoices, and usage metering for the SaaS app.
Consumed by the web app and the admin console.

## Stack
- TypeScript 5, strict, Node 22, ESM
- Fastify 5, Prisma 6 with PostgreSQL 16
- Vitest for tests, Biome for lint and format

## Commands
- Install: `pnpm install`
- Test all: `pnpm test` / one file: `pnpm vitest run path/to/file.test.ts`
- Typecheck: `pnpm typecheck`
- Lint and format: `pnpm check --write`

## Conventions
- Named exports only. No default exports.
- Return `Result<T, AppError>` from services; never throw across module boundaries.
- Money is integer cents (`amountCents`). Never floats.

## Architecture
- `src/routes/` HTTP only: validate input, call a service, map the result.
- `src/services/` business logic. No Fastify imports here.
- `src/db/` the only place Prisma is imported.

## Do not touch
- `src/db/generated/` is generated. Run `pnpm db:generate`.
- `src/legacy/stripe-v1/` is mid-migration. Ask before editing.

## Workflow
- Run typecheck and the relevant tests after every change.
- Commit after each working step: `feat(scope): summary`.
- Never edit a migration that has been merged.

## Security
- Never log tokens, card data, or full email addresses.
- All SQL goes through Prisma. No raw string queries.
- Every route under `/admin` must call `requireRole('admin')`.

Notice what it leaves out: generic advice like "write clean code" or "follow best practices." Claude already tries to do that. Every line in CLAUDE.md should change behavior.

Write instructions, not descriptions

"We use Prisma" is a description. "All database access goes through src/db/; never import Prisma elsewhere" is an instruction. Instructions get followed. Descriptions get interpreted.

Emphasis works when used sparingly. Marking one or two rules with IMPORTANT raises compliance on those rules. Marking twenty dilutes all of them.

Monorepos and subdirectory files

In a monorepo, keep the root file about the whole repository: workspace tool, shared commands, cross-package rules. Put package-specific rules in each package's own CLAUDE.md. Claude picks those up when it works in that directory.

This matters most where rules conflict. An authentication package and a marketing site follow very different rules about logging, error messages, and dependencies. The patterns in my authentication implementation guide belong in the auth package's file, not in the frontend's.

Keeping it current

The best maintenance habit is the lesson-learned loop. Every time Claude makes a mistake that a written rule would have prevented, add that rule before you move on. You can simply tell Claude: "Add a rule to CLAUDE.md so this doesn't happen again," then review the line it writes.

Review CLAUDE.md changes in pull requests like any other code. If a rule is wrong, the whole team inherits the error.

Sizing

Every line costs context in every session. The official guidance is to keep each CLAUDE.md under about 200 lines, because longer files reduce adherence. Note that @ imports organize a file but do not save context: imported files load with the file that imports them. To actually defer material, reference it in backticks as "read docs/testing.md before writing tests," put path-specific rules in .claude/rules/ so they load only for matching files, and turn repeatable procedures into skills (Chapter 5), which load only when needed. (Claude Code docs: memory)

Warning

Pitfall: Letting /init output stand as-is. It is a starting point. It cannot know your traps, your security rules, or why the legacy module exists.

Tip

What to do this week

  • Audit your CLAUDE.md against the eight sections and fill the gaps.
  • Rewrite three descriptions as instructions.
  • Add one lesson-learned rule every time Claude repeats a mistake.

Key takeaways

  • CLAUDE.md is the only project knowledge Claude carries into every session; review it like code.
  • Cover purpose, stack, commands, conventions, architecture, do-not-touch areas, workflow, and security rules.
  • Write instructions, not descriptions, and keep each file under about 200 lines.
  • Add a rule every time Claude repeats a mistake a rule would have prevented.