Published Nov 9, 2026 ⦁ 23 min read

CLAUDE.md Examples: 10 Real Templates for Claude Code (Plus AGENTS.md)

Looking for CLAUDE.md examples you can copy? This page has ten complete files: a Next.js app, a FastAPI service, a monorepo with per-package files, an open-source library that shares one AGENTS.md with every coding agent, a data/ML repo, an iOS app, a personal ~/.claude/CLAUDE.md, a team file with commit and review rules, a CLAUDE.local.md, and a path-scoped rule. Before the examples you get the short version of how Claude Code finds and loads CLAUDE.md, how it treats AGENTS.md now that it reads it natively, and what belongs in the file versus in a hook or a skill. Everything here was checked against the Claude Code docs in November 2026.

< 200 lines
Recommended size per CLAUDE.md file
4 hops
Max depth of nested @path imports
4 MiB
Files larger than this are skipped entirely
40,000 chars
Per-file limit for on-demand CLAUDE.md and rules (200K context)
200 lines / 25KB
Part of auto memory's MEMORY.md loaded each session
60k+
Open-source projects using AGENTS.md

What is CLAUDE.md?

CLAUDE.md is a markdown file of instructions that Claude Code reads at the start of every session. Each session starts with an empty context window, so anything you'd otherwise re-explain (how to run tests, which helper to use, which folder not to copy) goes in this file. There is no schema and no required section. You write headings and bullets, and Claude reads them.

Two facts from the memory docs shape everything else on this page:

  • CLAUDE.md is context, not configuration. It is delivered as a user message after the system prompt. Claude reads it and tries to follow it, but nothing enforces it. If a rule must hold every single time, use a hook or a permission rule instead.
  • Every line costs attention on every task. The file loads into every session whether a line is relevant or not. Short, specific files get followed more reliably than long ones.

Claude Code also has auto memory: notes Claude writes for itself in ~/.claude/projects/<project>/memory/, with a MEMORY.md index. You write CLAUDE.md; Claude writes auto memory. Both load every session. When you say "remember that the API tests need Redis", Claude saves it to auto memory. When you say "add this to CLAUDE.md", it edits the file.

Where CLAUDE.md files live and which one wins

The docs list four locations. They load from broadest to most specific, and all of them are concatenated into context. Nothing overrides anything: a project line simply appears after a user line, so Claude reads it later.

Scope Location Shared with Use it for
Managed policy macOS /Library/Application Support/ClaudeCode/CLAUDE.md, Linux/WSL /etc/claude-code/CLAUDE.md, Windows C:\Program Files\ClaudeCode\CLAUDE.md Every user on the machine Company standards, compliance reminders. Can't be excluded.
User ~/.claude/CLAUDE.md Only you, all projects Your personal working style and tools
Project ./CLAUDE.md or ./.claude/CLAUDE.md Team, through git Commands, conventions, gotchas for this repo
Local ./CLAUDE.local.md Only you, this project Sandbox URLs, your test accounts. Add it to .gitignore.

On top of those, there are three ways to add more instructions:

  • Nested directories. Claude Code walks up from the directory you launch in and loads every CLAUDE.md and CLAUDE.local.md it finds at launch. Files in subdirectories below your working directory load on demand, the first time Claude reads, writes, or edits a file in that subdirectory. Within one directory, CLAUDE.local.md comes after CLAUDE.md.
  • .claude/rules/. Any .md file in .claude/rules/ (searched recursively) loads like .claude/CLAUDE.md. Add paths: frontmatter and the rule only loads when Claude touches a matching file. Personal rules go in ~/.claude/rules/ and apply to every project.
  • @path imports. A line like @docs/git-workflow.md pulls that file in. Relative paths resolve from the importing file, imports can nest four hops deep, and @~/... reaches your home directory. Imports help organization but not size: imported files load together with the file that imports them. Paths inside backticks are not imported, and external imports (paths outside your working directory) in a project file show a one-time approval dialog.

Two smaller details that are easy to miss: block-level HTML comments (<!-- note for humans -->) are stripped before the file reaches Claude, so you can leave maintainer notes for free. And the project-root CLAUDE.md survives /compact, because Claude Code re-reads it from disk; nested files and path-scoped rules reload the next time Claude touches a matching file.

Commands that create and maintain CLAUDE.md

Command What it does
/init Scans the codebase and writes a starter CLAUDE.md with build, test, and convention notes. If one exists, it suggests improvements instead of overwriting. It also pulls in .cursor/rules/, .cursorrules and .github/copilot-instructions.md.
CLAUDE_CODE_NEW_INIT=1 then /init Interactive flow: asks which artifacts to set up (CLAUDE.md, skills, hooks), explores with a subagent, asks follow-ups, and shows a proposal before writing. Also reads AGENTS.md, .windsurf/rules/, .clinerules and more.
/memory Lists every CLAUDE.md, CLAUDE.local.md and memory location, opens one in your editor (creating it if needed), and toggles auto memory.
/context all Shows what's in context, including the Memory files list.
/doctor Setup checkup. For CLAUDE.md it proposes cuts for content Claude can derive from the code.
/doctor prompt-audit Finds outdated, conflicting, or broken instructions across CLAUDE.md, AGENTS.md, rules and skills (v2.1.283+). Changes nothing until you approve.
/import codex, gemini or cursor Copies another agent's instruction files, MCP servers and commands into Claude Code.

The old # shortcut, where starting a message with # added a line to memory, was removed in v2.0.70. Many older guides still show it. Today you ask Claude in plain words ("add to CLAUDE.md: use pnpm") or edit the file through /memory. See our Claude Code commands guide for the rest of the slash commands.

  1. v0.2.54Starting a message with # adds it to memory
  2. v2.0.64.claude/rules/ directory added
  3. v2.0.70# shortcut removed: tell Claude to edit CLAUDE.md instead
  4. v2.1.59Auto memory: Claude saves its own notes, managed with /memory
  5. v2.1.69InstructionsLoaded hook event fires when CLAUDE.md or rules load
  6. v2.1.277Native AGENTS.md support when a project has no CLAUDE.md
  7. v2.1.283/doctor prompt-audit checks instruction files for stale or conflicting lines

CLAUDE.md vs AGENTS.md: does Claude Code read AGENTS.md?

Yes, since v2.1.277. Many top-ranking articles still say it doesn't, which was true for most of 2025 and early 2026. The current rule is a fallback:

Your repo has Claude Code reads
AGENTS.md, and no CLAUDE.md or CLAUDE.local.md in the working directory or above AGENTS.md
AGENTS.md and a CLAUDE.md or CLAUDE.local.md on the path Only the CLAUDE.md files
A CLAUDE.md that imports @AGENTS.md CLAUDE.md, with AGENTS.md included through the import

Your ~/.claude/CLAUDE.md, the managed CLAUDE.md, and .claude/rules/ don't count for that check, so they keep loading alongside AGENTS.md. A CLAUDE.local.md does count: adding one silently stops Claude from reading the repo's AGENTS.md. Claude Code never reads AGENTS.local.md, AGENTS.override.md or anything under .agents/.

You can change the default in /config under Project instructions: claude-md-or-agents-md (default), claude-md-and-agents-md (both, CLAUDE.md first), claude-md, or managed-only. In a settings file it lives under the built-in plugin ID, and only user, --settings or managed settings are honored:

{
  "pluginConfigs": {
    "cc-plugin-agents-md@builtin": {
      "options": { "instructionFiles": "claude-md-and-agents-md" }
    }
  }
}

The setup that works everywhere: keep the shared instructions in AGENTS.md and put a small CLAUDE.md next to it that starts with the import. It works on any version, with any Project instructions value, and never loads AGENTS.md twice:

@AGENTS.md

## Claude Code
- Use plan mode for changes under `src/billing/`.

A symlink (ln -s AGENTS.md CLAUDE.md) also works if you have nothing Claude-specific to add. The docs warn against it if anyone clones on Windows: Git checks a committed symlink out as a one-line text file unless core.symlinks is on. Claude's Edit tool also refuses to write through a symlink and edits AGENTS.md instead. Supabase's repo uses the import approach: its CLAUDE.md is the single line @AGENTS.md.

CLAUDE.md vs AGENTS.md vs Cursor rules vs Copilot instructions

CLAUDE.md AGENTS.md .cursor/rules/ .github/copilot-instructions.md
Read by Claude Code (Copilot's coding agent also accepts a root CLAUDE.md) Codex, Cursor, Copilot agent, Gemini CLI, Jules, Zed, Windsurf, Aider and more; Claude Code as a fallback Cursor GitHub Copilot
Format Markdown, no schema Markdown, no schema .mdc with description, globs, alwaysApply frontmatter Markdown
Personal and org scopes ~/.claude/CLAUDE.md, CLAUDE.local.md, managed policy file None in the spec User rules and team rules in Cursor settings Personal and org instructions in GitHub settings
Path scoping .claude/rules/*.md with paths: globs, plus nested CLAUDE.md Nested AGENTS.md, nearest file wins globs field .github/instructions/*.instructions.md with applyTo
Imports @path, up to 4 hops Not in the spec (Claude Code expands @path in AGENTS.md it reads) @file references, read on demand rather than inlined No
Nested files All ancestors concatenated; subfolders load on demand Closest file takes precedence n/a n/a

Sources: agents.md, Cursor rules docs, GitHub Copilot repository instructions.

Best for Teams that only use Claude Code: CLAUDE.md only
You get every scope, imports and path-scoped rules with nothing to keep in sync.
Best for Teams or open-source repos where people use several agents: AGENTS.md + CLAUDE.md with @AGENTS.md
One shared file for Codex, Cursor and Copilot, plus a few Claude-only lines below the import.
Best for Repos where nobody needs Claude-specific lines: AGENTS.md alone
Claude Code v2.1.277+ reads it directly. Just don't add a CLAUDE.local.md, or switch Project instructions to claude-md-and-agents-md.

CLAUDE.md best practices: what to put in and what to leave out

The official best practices page boils it down to one test: write only what Claude couldn't work out from the code itself. That gives you four kinds of lines worth keeping:

  1. How to check work. The exact install, test, typecheck and lint commands, and how to run a single test file. This is the most useful line in most files.
  2. Places where the code misleads. An old pattern that's everywhere but new code must not copy. A folder that looks dead but is still served.
  3. Decisions that aren't in the repo. Which error helper the team settled on, how deploys work, what needs a migration review.
  4. Anything you've had to correct twice.

Leave out:

  • Architecture tours and file trees. The docs list "describe your architecture and file layout in CLAUDE.md" under advice you can stop following. Claude reads the repo itself. One line pointing at a non-obvious folder is fine; a full tree is not.
  • Style rules a tool already enforces. If Prettier, Ruff or ESLint handles it, don't spend context on it. Run the formatter from a hook.
  • ALL CAPS and IMPORTANT. Current models follow a plainly worded line. If a line keeps getting missed, either the file is too long or the rule needs a hook.
  • Long procedures. A release checklist or incident runbook belongs in a skill, which only loads when it's needed. Browse ready-made ones in our agent skills directory.
  • Secrets. CLAUDE.md is committed and read by every session. Point at .env.example instead.

Write each instruction so you could verify it: "Use 2-space indentation" beats "format code properly", and "API handlers live in src/api/handlers/" beats "keep files organized". If two lines contradict each other, Claude may pick either one, so prune old rules when you add new ones.

Rules that belong in hooks or settings instead

The docs are blunt about this: "CLAUDE.md is for guidelines, and Claude is allowed to decide a guideline doesn't apply." Anything with zero exceptions moves to configuration the harness enforces. "Always run the formatter" becomes a PostToolUse hook in .claude/settings.json:

{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Edit|Write",
        "hooks": [
          { "type": "command", "command": "npx prettier --write --ignore-unknown \"$(jq -r '.tool_input.file_path')\"" }
        ]
      }
    ]
  }
}

"Never read .env" becomes a permission deny rule, which holds in every permission mode:

{
  "permissions": {
    "deny": ["Read(./.env)", "Read(./.env.local)", "Read(./secrets/**)"]
  }
}

"Don't touch the migrations folder" becomes a PreToolUse hook that exits with code 2 for paths under migrations/. Keep the softer preferences, like "prefer named exports", in CLAUDE.md, because they have exceptions. Our Claude Code hooks guide has copy-paste versions of these.

Anatomy of a good CLAUDE.md

Here is a short project file with every part annotated. The annotations are HTML comments, which Claude Code strips before loading, so you could even leave them in.

# invoice-api
<!-- 1. One line of identity: stack and package manager. Claude can't guess "pnpm only" from a lockfile it hasn't read yet. -->
Node 22, TypeScript strict, Fastify, Prisma on Postgres. pnpm only.

## Commands
<!-- 2. Exact commands, including how to run ONE test. This is what Claude uses to check its own work. -->
- Install: `pnpm install`
- Typecheck: `pnpm tsc --noEmit`
- All tests: `pnpm vitest run`
- One file: `pnpm vitest run src/routes/invoices.test.ts`

## Conventions
<!-- 3. Only conventions that differ from defaults or that the code contradicts. -->
- Use the error helpers in `src/lib/errors.ts`. Never throw raw strings.
- Money is integer cents everywhere (`amountCents`). No floats.

## Gotchas
<!-- 4. The traps that cost you a correction last week. -->
- `src/legacy/` still serves /v1 traffic. Don't copy its callback style.
- Integration tests need `DATABASE_URL`; see `.env.example`.

## More
<!-- 5. Imports for detail that's worth always having, and pointers (not imports) for detail that isn't. -->
- Git workflow: @docs/git-workflow.md
- Release steps are in the `release` skill. Don't run them unless asked.

That's 20 lines that do the job. Every section answers a question Claude would otherwise ask or guess wrong.

CLAUDE.md examples for 10 common setups

Each example below is a complete file you can paste and edit. Swap the commands for your own, delete what doesn't apply, and keep each file well under 200 lines. Real public files worth reading for comparison: anthropic-quickstarts (conventions plus per-project commands), claude-agent-sdk-python (workflow commands first), Next.js AGENTS.md (a large monorepo), and graphiti (a Python library).

1. Next.js + TypeScript app

File: ./CLAUDE.md. Scope: everyone working in the repo.

# Acme Dashboard

Next.js 15 App Router, TypeScript strict, Tailwind, Drizzle ORM on Postgres. pnpm only.

## Commands
- Dev: `pnpm dev` (port 3000)
- Typecheck: `pnpm tsc --noEmit`
- Lint: `pnpm lint`
- Unit tests: `pnpm vitest run`
- One test file: `pnpm vitest run src/lib/billing.test.ts`
- E2E (dev server must be running): `pnpm playwright test e2e/checkout.spec.ts`
- After editing `src/db/schema.ts`: `pnpm drizzle-kit generate`, then read the SQL in `drizzle/`

## Conventions
- Server Components by default. Add "use client" only for state, effects or browser APIs.
- Mutations go through Server Actions in `src/app/**/actions.ts`. `src/app/api/` is for webhooks only.
- Validate every action input with the zod schemas in `src/lib/validation/`.
- Merge class names with `cn()` from `src/lib/utils.ts`.
- Throw `AppError` from `src/lib/errors.ts`, never raw strings.

## Gotchas
- `src/legacy/` (pages router, SWR) still serves /v1. Don't copy its patterns.
- `NEXT_PUBLIC_*` vars are inlined at build time. Restart `pnpm dev` after editing `.env.local`.
- To test checkout, run `stripe listen --forward-to localhost:3000/api/stripe/webhook` first.

## Before you finish
- Run the typecheck and the tests for the files you touched.

2. Python / FastAPI service

File: ./CLAUDE.md. Scope: team.

# orders-service

FastAPI, SQLAlchemy 2.0 (async), Alembic, Postgres. Python 3.12, managed with uv.

## Commands
- Install: `uv sync`
- Run: `uv run fastapi dev app/main.py`
- Tests: `uv run pytest -q`
- One test: `uv run pytest tests/api/test_orders.py::test_create_order -x`
- Lint and format: `uv run ruff check --fix . && uv run ruff format .`
- Types: `uv run mypy app`
- New migration: `uv run alembic revision --autogenerate -m "what changed"`, then read the file before applying

## Conventions
- Routers in `app/api/routes/`, one file per resource. Business logic in `app/services/`, never in route functions.
- Pydantic v2 schemas: requests end in `In`, responses in `Out` (`OrderIn`, `OrderOut`).
- Get DB sessions from the `get_session` dependency. Don't create engines or sessions by hand.
- Money is integer cents (`amount_cents: int`).
- Raise `HTTPException` only in routes. Services raise the errors in `app/errors.py`.

## Gotchas
- Tests need Postgres from `docker compose up -d db`. A connection error means it isn't running.
- `app/models/__init__.py` must import every model, or autogenerate misses the table.
- Store timestamps as timezone-aware UTC. Don't use `datetime.utcnow()`.

3. Monorepo root with per-package files

In a monorepo, the root file holds rules for every package and each package adds its own. Start Claude in apps/api/ and it loads both apps/api/CLAUDE.md and the root file, with nothing from apps/web/. Start at the root and each package's file loads when Claude first works there. This is the layout the large codebases guide recommends.

File: ./CLAUDE.md (root). Scope: whole repo.

# Acme monorepo

pnpm workspaces + Turborepo.
- `apps/web`: Next.js storefront
- `apps/api`: Hono API on Node 22
- `packages/ui`: shared React components
- `packages/db`: Prisma schema and client

## Commands (from repo root)
- Install: `pnpm install`
- Build one package and its deps: `pnpm turbo run build --filter=@acme/api...`
- Test one package: `pnpm --filter @acme/api test`
- Typecheck all: `pnpm turbo run typecheck`

## Rules for every package
- Import other packages by workspace name (`@acme/ui`), never by a relative path into another package.
- Schema changes in `packages/db/prisma/schema.prisma` need `pnpm --filter @acme/db prisma migrate dev --name <change>` and a note in the PR.
- Any change under `packages/` needs a changeset: `pnpm changeset`.

Each app has its own CLAUDE.md with stack-specific rules.

File: apps/api/CLAUDE.md. Scope: loads when Claude works in apps/api/.

# apps/api

Hono on Node 22, zod validation, Prisma via `@acme/db`.

- Dev: `pnpm --filter @acme/api dev` (port 8787)
- One test file: `pnpm --filter @acme/api test -- src/routes/invoices.test.ts`
- Every route validates input with `zValidator` and returns errors in the shape from `src/lib/http-error.ts`.
- Auth middleware is `src/middleware/auth.ts`. Public routes must be listed in `PUBLIC_ROUTES` there or they return 401.
- Never import from `apps/web`.

File: apps/web/CLAUDE.md. Scope: loads when Claude works in apps/web/.

# apps/web

Next.js App Router. UI components come from `@acme/ui`. Don't add new ones here unless they are page-specific.

- Dev: `pnpm --filter @acme/web dev` (port 3000, expects the API on 8787)
- Data fetching: call the typed client in `src/lib/api.ts`, never `fetch` the API directly.
- Product images go through `next/image` with the loader in `next.config.ts`.

If other teams' CLAUDE.md files keep loading for you, skip them in your own .claude/settings.local.json with claudeMdExcludes. Patterns match absolute paths:

{
  "claudeMdExcludes": ["**/apps/legacy-admin/**"]
}

4. Open-source library (AGENTS.md shared with every agent)

Contributors to an open-source project use whatever agent they like, so the instructions live in AGENTS.md and CLAUDE.md imports them.

File: ./AGENTS.md. Scope: every contributor and every agent.

# tinyparse

Zero-dependency TypeScript parser combinator library, published to npm. Supports Node 18+ and modern browsers.

## Setup and checks
- Install: `npm ci`
- Test: `npm test` (vitest). One file: `npx vitest run test/sequence.test.ts`
- Build: `npm run build` (tsup, ESM and CJS into `dist/`)
- Size budget: `npm run size`. CI fails if the minified bundle passes 4 kB.

## Rules
- No runtime dependencies. Dev dependencies are fine.
- Every exported function needs a TSDoc comment with an `@example` block. The docs site is generated from them.
- The public API is whatever `src/index.ts` exports. Everything else is internal.
- Test through the public API, not internals.
- Breaking changes need a migration note in `docs/migrating.md`.

## Pull requests
- Title in Conventional Commits form: `feat(combinators): add sepBy1`.
- Record changes with `npx changeset`. Never edit `CHANGELOG.md` by hand.

File: ./CLAUDE.md. Scope: Claude Code users only.

@AGENTS.md

## Claude Code
- Use plan mode before changing anything in `src/core/`. It is the hot path.
- Run `npm run bench -- core` before and after changes in `src/core/` and put both numbers in the PR description.

5. Data / ML repo

File: ./CLAUDE.md. Scope: team. ML repos benefit the most from CLAUDE.md, because the things that bite (data leakage, seeds, long GPU runs) are invisible in the code.

# churn-model

Python 3.11 with uv. PyTorch, Polars, Hydra configs, DVC for data, MLflow for tracking.

## Commands
- Env: `uv sync`
- Get data: `dvc pull` (needs AWS credentials for the `ml-data` profile)
- Smoke train on a 1% sample: `uv run python -m churn.train experiment=smoke`
- Full train: `uv run python -m churn.train experiment=baseline` (GPU, about 40 minutes; ask me before running)
- Tests: `uv run pytest tests -q`

## Layout that isn't obvious
- Hyperparameters live in `conf/`. Change them there, not in code.
- `data/raw/` is DVC-tracked and read-only. Derived data goes to `data/processed/` through `churn/pipelines/`.
- `notebooks/` is for exploration. Code that gets reused moves into `churn/` with a test.

## Rules
- Seed with `churn.utils.seed_everything(cfg.seed)`, never `torch.manual_seed` directly.
- Split by `customer_id`, not by row, or evaluation leaks. Use `churn.data.split.customer_split`.
- Log metrics with `churn.tracking.log_metrics` so they land in MLflow.
- Never commit anything from `data/`, `mlruns/` or model checkpoints.
- Prefer Polars. Use pandas only where a library requires it.

6. Mobile app (SwiftUI / iOS)

File: ./CLAUDE.md. Scope: team. Mobile builds have long, exact commands that Claude would otherwise guess at.

# Trailhead iOS

SwiftUI, iOS 17+, Swift 6 language mode with strict concurrency. Xcode project with Swift Package Manager dependencies.

## Commands
- Build: `xcodebuild -scheme Trailhead -destination 'platform=iOS Simulator,name=iPhone 16' build`
- Test: `xcodebuild -scheme Trailhead -destination 'platform=iOS Simulator,name=iPhone 16' test`
- One test class: add `-only-testing:TrailheadTests/RouteStoreTests`
- Lint: `swiftlint --strict`
- Format: `swiftformat .`

## Architecture choices
- One folder per feature in `Trailhead/Features/<Feature>/` with a View, an `@Observable` model and a Service.
- All networking goes through `APIClient` in `Trailhead/Core/Networking/`. It handles token refresh and retries.
- Persistence is SwiftData. A model change needs a new `VersionedSchema` and a stage in `Trailhead/Core/Persistence/Migrations.swift`.

## Gotchas
- Don't hand-edit `project.pbxproj`. The app target uses synchronized folders, so new files under `Trailhead/` are picked up.
- User-facing text goes in `Localizable.xcstrings`. No hardcoded strings in views.
- `Secrets.xcconfig` is gitignored. If the build fails on a missing `API_BASE_URL`, copy `Secrets.example.xcconfig`.

7. Personal ~/.claude/CLAUDE.md

File: ~/.claude/CLAUDE.md. Scope: only you, in every project. This is where your working style goes, so you never put personal taste in a team file.

# About me
- Backend developer: Go, TypeScript, Postgres. New to Swift, so explain iOS-specific choices briefly.

# How I like to work
- Ask before adding a dependency.
- For changes touching more than three files, show a short plan and wait for my OK.
- Keep diffs minimal. Don't reformat lines you didn't change.
- If you're unsure how a library API works, read the installed version's source instead of guessing.

# Style I prefer everywhere
- Early returns over nested ifs.
- Comments explain why, not what.

# My machine
- Use `rg` and `fd` instead of grep and find.
- `gh` is logged in. Use it for PRs and issues.
- Default to pnpm for JS and uv for Python, but if a repo has another lockfile, follow the lockfile.

Personal rules that should apply everywhere but only to certain files can go in ~/.claude/rules/ with a paths: filter, for example ~/.claude/rules/sql.md scoped to **/*.sql.

8. Team CLAUDE.md with commit and review rules

File: ./CLAUDE.md (or ./.claude/CLAUDE.md). Scope: team, reviewed in PRs like any other doc.

# Payments API: team rules

## Commands
- Everything CI runs: `make check` (lint, typecheck, unit tests)
- Contract tests: `make contract`

## Branches and commits
- Never commit to `main`. Branch as `<type>/<ticket>-<slug>`, e.g. `fix/PAY-412-refund-rounding`.
- Conventional Commits: `type(scope): summary`, imperative, summary under 72 characters.
- One logical change per commit. Don't mix refactors with behavior changes.
- Put the ticket in the commit body: `Refs: PAY-412`.

## Before opening a PR
- `make check` passes.
- New or changed endpoints: update `openapi.yaml` and add a contract test in `tests/contract/`.
- At most one migration per PR. It must be reversible and be called out under a "Migration" heading.

## PR description
- Sections: Summary, Why, How tested, Risk. Under 20 lines.

## Reviewing code
- Review in this order: correctness, security (authorization on every handler, no secrets or card data in logs), migrations, tests, then style.
- Any change under `src/ledger/` needs a second reviewer from the payments-core team. Say so in the review.
- Leave comments only. Don't approve or merge.

Claude Code ships its own commit and PR instructions. If yours compete with them, the docs suggest turning the built-in ones off with includeGitInstructions in .claude/settings.json, and setting the trailer text with attribution:

{
  "includeGitInstructions": false,
  "attribution": { "commit": "", "pr": "" }
}

"Never commit to main" is a rule with no exceptions, so if it really matters, back it with a PreToolUse hook or an ask permission rule for Bash(git push *) as well.

9. CLAUDE.local.md for personal project notes

File: ./CLAUDE.local.md. Scope: only you, only this project. Add it to .gitignore.

# My local setup
- My dev database is `postgres://localhost:5433/orders_dev` (Docker on 5433, not 5432).
- Seed test users with `uv run python scripts/seed.py --user me`.
- I'm working on the refunds rewrite on branch `feat/PAY-398-refunds`. Treat `app/services/refunds_v2.py` as the new code and `refunds.py` as the old.

Two catches. A gitignored CLAUDE.local.md only exists in the worktree where you created it; to share personal notes across worktrees, import a file from home instead (@~/.claude/orders-service.md). And if the repo relies on AGENTS.md, creating a CLAUDE.local.md stops Claude from reading AGENTS.md unless you switch Project instructions to claude-md-and-agents-md.

10. Path-scoped rule in .claude/rules/

File: .claude/rules/api.md. Scope: team, but it only loads when Claude reads or edits a file matching paths. This is how you keep the root file short as a project grows.

---
paths:
  - "src/api/**/*.ts"
  - "tests/api/**/*.test.ts"
---

# API rules
- Validate request bodies with the zod schemas in `src/api/schemas/`. Don't hand-roll checks.
- Every new endpoint needs an entry in `openapi.yaml`. CI fails without it.
- Return errors with `problem()` from `src/api/errors.ts` (RFC 9457 problem details).
- Handlers stay thin: parse, call a service, return.

paths is the only frontmatter field Claude Code reads in a rule file. Globs support brace expansion (src/**/*.{ts,tsx}), and a rule with no paths loads every session like .claude/CLAUDE.md.

CLAUDE.md template you can start from

If you want a blank CLAUDE.md template rather than an example, this is the skeleton every file above follows. Fill in what applies and delete the rest:

# <project name>

<stack in one line>. <package manager> only.

## Commands
- Install:
- Dev:
- Typecheck:
- Lint:
- All tests:
- One test:

## Conventions
- <a rule that differs from the default or that old code contradicts>

## Gotchas
- <something that cost you a correction>

## Before you finish
- <the check Claude should run on its own work>

Checklist before you commit a CLAUDE.md

  • The file is under 200 lines, and /status shows no size warning.
  • The first section has exact commands, including how to run one test.
  • Every line passes the test: would Claude get this wrong without it?
  • No file trees, dependency lists or architecture essays Claude can read from the repo.
  • No style rules a formatter or linter already enforces.
  • No secrets, tokens or internal URLs you wouldn't put in the README.
  • Personal preferences are in ~/.claude/CLAUDE.md or a gitignored CLAUDE.local.md, not the team file.
  • Rules with zero exceptions are hooks or permissions.deny entries, not CLAUDE.md lines.
  • Long procedures are skills; folder-specific rules are nested CLAUDE.md files or .claude/rules/ with paths:.
  • Paths you mention but don't want imported are in backticks.
  • /context all lists the file under Memory files in a fresh session.
  • /doctor prompt-audit reports no conflicts with your rules, nested files or AGENTS.md.

Context isn't free: every line of CLAUDE.md is sent with each request. If you want to see what a file costs, paste it into our token counter. And if you're still choosing a tool, our AI coding agents comparison shows which agents read AGENTS.md, CLAUDE.md or their own rules format.

FAQ

What is a CLAUDE.md file?

It's a markdown file of project instructions that Claude Code loads into context at the start of every session. It holds the commands, conventions and gotchas you'd otherwise repeat in every conversation. There's no required format; headings and bullets work best.

Where should I put CLAUDE.md?

Put the team file at the repo root as ./CLAUDE.md or ./.claude/CLAUDE.md and commit it. Personal preferences for all projects go in ~/.claude/CLAUDE.md, and personal notes for one project go in ./CLAUDE.local.md, which you add to .gitignore. Subdirectories can have their own CLAUDE.md, which loads when Claude works there.

Does Claude Code read AGENTS.md?

Yes, since v2.1.277, but by default only when there's no CLAUDE.md or CLAUDE.local.md in your working directory or above it. To use both, start your CLAUDE.md with @AGENTS.md, or set Project instructions to claude-md-and-agents-md in /config.

How long should a CLAUDE.md be?

The official docs recommend under 200 lines per file. Longer files cost more context and get followed less reliably. Move folder-specific rules into nested files or .claude/rules/ with paths:, and procedures into skills.

Should CLAUDE.md be committed to git?

Yes, the project CLAUDE.md is meant to be shared through version control and reviewed in PRs like other docs. Keep CLAUDE.local.md out of git; Claude Code doesn't add it to .gitignore for you unless you use the CLAUDE_CODE_NEW_INIT=1 flow of /init.

Why is Claude ignoring my CLAUDE.md?

Run /context all to confirm the file loaded at all. If it did, the usual causes are a file that's too long, vague lines, or two files that contradict each other. For rules that must always hold, use a hook or a permission deny rule, since CLAUDE.md is guidance Claude can decide doesn't apply.

Does CLAUDE.md survive /compact?

The project-root CLAUDE.md does: Claude Code re-reads it from disk after compaction. Nested CLAUDE.md files and path-scoped rules load again the next time Claude touches a matching file. Instructions you only gave in chat are lost, so move anything important into the file.