CLAUDE.md Examples: Four Real Files and What Each Line Does

Four annotated CLAUDE.md files, for a web app, a library, a monorepo root and your personal ~/.claude/CLAUDE.md, with the reason each line earns its place and the kinds of line that should never be there.

7 min read

A good CLAUDE.md is short and specific: the commands Claude cannot guess, the conventions that differ from the defaults, the few hard lines it must not cross, and the traps that have already cost someone an afternoon. Everything Claude can learn by reading the code stays out. Below are four realistic files, a web app, a library, a monorepo root and a personal user file, each followed by why every line is there. Then the lines that do not belong in any of them. Where these files sit in a repository and what goes in git is covered in Claude Code project structure; how several files stack across repositories is in managing multiple projects with CLAUDE.md.

The test every line has to pass

Anthropic’s Claude Code best practices (opens in a new tab) put it as one question: would removing this line cause Claude to make mistakes? If not, cut it. The file loads in full at the start of every session, so each line costs context every time, and a long file makes the lines that matter easier to miss. The documentation targets under 200 lines per file, says there is no required format, and asks for instructions concrete enough to check: “run npm test before committing”, not “test your changes”.

Example 1: a web app

CLAUDE.md (a Next.js app)
# Shopfront web app

## Commands
- Install: `pnpm install` (never npm or yarn; the lockfile is pnpm's)
- Dev server: `pnpm dev` on http://localhost:3000
- Before committing: `pnpm lint && pnpm typecheck && pnpm test`
- One test file: `pnpm test -- src/cart/cart.test.ts`

## Conventions
- Server components by default; add "use client" only for state or browser APIs.
- Data fetching goes through `src/lib/api.ts`. Never call fetch() in a component.
- Money is integer pence in code and formatted only in `formatPrice()`.
- Dates are stored and sent in UTC; convert to local time only in the UI.

## Do not
- Edit anything in `src/generated/`. Run `pnpm codegen` after changing the API schema.
- Commit `.env.local` or print its values.

## Gotchas
- Stripe webhooks need `pnpm stripe:listen` running, or checkout tests hang.

## Work tracking
- Tasks live on the team board (fenbs, project "shopfront"). At the start of a
  session call fenbs_get_context; comment on the task when you finish.
  • Commands: Claude would guess npm install and get a second lockfile. The single-test command matters because the example file in Anthropic’s own best practices tells Claude to prefer single tests to the whole suite.
  • Conventions: each one differs from what a model would do by default, and each is checkable. “Money is integer pence” prevents a class of bug no linter catches.
  • Do not: the generated folder is the classic case of a rule Claude cannot infer. Pair every “never” with what to do instead, so Claude is not left stuck.
  • Gotchas: one line that saves a hung test run and a confused session. This is the section the docs single out as worth keeping when trimming.
  • Work tracking: two lines pointing at where tasks live. The rhythm itself belongs elsewhere, as described below.

Example 2: a library

CLAUDE.md (a Python package)
# tidydates

Public API is everything exported from `tidydates/__init__.py`. Nothing else is public.

## Commands
- Set up: `uv sync`
- Tests: `uv run pytest`; one test: `uv run pytest tests/test_parse.py -k iso`
- Lint and types: `uv run ruff check . && uv run mypy tidydates`

## Rules
- IMPORTANT: never change the signature of a public function. Add a new
  keyword argument with a default, or a new function, and note it in CHANGELOG.md.
- Support Python 3.10 and later. No match statements on 3.9 code paths.
- No new runtime dependencies without asking. Test dependencies are fine.
- Every public function has a docstring with one runnable example; doctests run in CI.

<!-- Maintainers: the 3.10 floor is set by our largest downstream user. -->
  • The first line defines “public”, which decides what counts as a breaking change. Claude cannot infer a team’s compatibility promise from the code.
  • IMPORTANT is used once. The best-practices page suggests emphasis for the one instruction Claude keeps skipping, and warns that if many lines are emphasised, none stands out.
  • The dependency rule says what is allowed as well as what is not, so a test helper does not trigger a question.
  • The HTML comment at the end is for people. Per the memory documentation (opens in a new tab), block-level HTML comments are stripped before the file reaches Claude, so the reason is recorded at no context cost.

Example 3: a monorepo root

CLAUDE.md (the root of a pnpm and Turborepo monorepo)
# Acme monorepo

apps/web (Next.js), apps/api (Fastify), packages/* (shared libraries).
Each app and package has its own CLAUDE.md with its conventions.

## Commands (run from the root)
- `pnpm install`, then `pnpm turbo run build --filter=<package>`
- Tests for one package: `pnpm --filter <package> test`
- Never run `pnpm test` at the root during a task; it builds everything.

## Rules for every package
- Shared types live in packages/types. Do not copy a type into an app.
- A change to packages/* needs a changeset: `pnpm changeset`.
- Name the package in every commit message: "api: fix session expiry".
  • The first line is a map, and deliberately a one-line one. It tells Claude which name means what; the tree itself Claude can list.
  • The pointer to per-package files explains why this file is short. The large codebases guide (opens in a new tab) recommends this layout: rules for everything at the root, each package’s own conventions in its folder, loaded when Claude works there.
  • The root-test warning is a real trap. One line prevents a ten-minute build every time Claude wants to check something.
  • Only rules that apply to every package belong here. Anything about one app goes in that app’s file, or a path-scoped rule in .claude/rules/.

Example 4: your user file

~/.claude/CLAUDE.md
# How I work

- British English in prose, comments and commit messages.
- Before changing more than three files, show me the plan and wait.
- Explain a failing command's error before trying a different approach.
- Commit only when I ask. Never push.
- When I say "quick fix", change only what is needed and list anything else you noticed.
  • Every line is about you, not a project. The user file loads in every repository, and files are combined rather than merged, so a project rule here (“use pnpm”) will sooner or later contradict a project file, and Claude may follow either.
  • The lines describe how to work with you: when to stop and ask, how to report, what never to do on your behalf. Those are the things no repository can say.
  • Five lines is enough. A long user file taxes every session in every project.

Lines that do not belong

  • Anything Claude can read from the code: directory trees, dependency lists, file-by-file descriptions. The /doctor checkup proposes cutting exactly these from a checked-in file.
  • Self-evident advice: “write clean code”, “follow best practices”, “be careful”. Nothing checkable, nothing changes.
  • Long procedures such as how to cut a release. Those are skills, which load only when needed; see how to create a Claude skill.
  • Rules that must never be broken. CLAUDE.md is context Claude tries to follow, not enforcement. To block an edit to .env whatever Claude decides, use a deny rule or a PreToolUse hook, as the hooks guide (opens in a new tab) shows.
  • API documentation pasted in. Link to it, or put it in a skill’s reference file.
  • Anything that changes weekly: the current sprint, who is on leave, what is half done. It goes stale in the file and misleads the next session.
  • Secrets, tokens and customer details. The file is committed and read by every session.
  • Notes Claude learned for itself. That is auto memory’s job; see Claude Code memory.

The work list is not a line in CLAUDE.md

The most common thing that should not be in the file is a list of tasks. It changes daily, differs on every branch, and records nobody’s name against what was done. Example 1 shows the alternative: two lines that say where the tasks live and when to read and update them. With fenbs connected over MCP, those lines name the board’s project; the tasks, their lanes and their history stay on the board, where the team can see them and each change records whether a person or an assistant made it. The fuller set of instructions, and what a session looks like with them, is in a task-tracking workflow for Claude Code.

Checking a file works

  1. Start with /init, which drafts a file from the codebase, then cut everything that fails the one-question test.
  2. Run /context in a new session and check the file is listed under memory files.
  3. Ask Claude a question the file answers, such as “how do I run one test?”. If it asks you instead, the line is ambiguous.
  4. When Claude repeats a mistake the file already covers, the file is probably too long and the rule is buried. Shorten before you add emphasis.
  5. Review it like code: when a rule stops being true, delete it the same day.

Related

Connect the board your file points at: Claude Code integration. Rules files for other assistants, and how to keep one source with @AGENTS.md: AI context files compared. How context is spent in a session: context engineering for Claude Code.

Questions people ask.

How long should a CLAUDE.md file be?

The Claude Code documentation targets under 200 lines per file. Most good files are far shorter: commands, conventions that differ from the defaults, hard lines and known traps. Move procedures into skills and area-specific rules into path-scoped rules.

Is there a required format for CLAUDE.md?

No. It is plain Markdown. Headings and short bullet lists work best because Claude scans structure the way a person does, and each instruction should be specific enough to check.

What should go in the user-level ~/.claude/CLAUDE.md?

Only preferences that are true in every project: language, when to stop and ask, what never to do on your behalf. Project rules belong in the project file, because the files are combined and conflicting instructions may be followed either way.

Can I leave notes in CLAUDE.md that Claude does not read?

Yes. Block-level HTML comments are stripped before the file is added to Claude’s context, so you can explain why a rule exists for other maintainers without spending tokens on it.

Start with one thing.

There is nothing to set up first. Write one line and you’ve started.