Real CLAUDE.md Examples, Annotated
In short: Produce an evidence-backed CLAUDE.md for one real repository the user owns. Every line traces to a trap, command, check or ban the code cannot reveal.
| Key fact | Detail |
|---|---|
| What it covers | agents, software development, open source, prompt engineering |
| Tools | Claude, Claude Code, Anthropic, BigQuery, ChatGPT |
| Posts covered | 12 posts (3 S-tier, 3 A-tier) · top: Boris Cherny's personal CLAUDE.md… · primer.md + memory.sh — live-updating… · Claude Code Team Tips — Boris Cherny's 10… |
| Creators | @cooper.simson, @keshavsuki, @adam_ha_yes |
| Sources dated | Feb 2026 – Sep 2026 |
| Prompt system | Run-it-yourself prompts |
| Last verified | 2026-10-22 |
The CLAUDE.md files that actually change how Claude Code behaves are short lists of exact commands, codebase traps and hard bans, each with a reason attached. Generic advice like "write clean code" or "be concise" costs context on every turn and changes nothing, so the best files from Bun, PyTorch, MLflow and Anthropic's own repos spend almost no lines on it.
Category: Claude Code configuration / agent memory Sources checked: 2026-10-22. Eight public CLAUDE.md files, each pinned to the commit quoted; the official memory and best-practices docs; 12 saved posts from the DejaViewed catalog. Quoting: excerpts are verbatim and capped at 25 lines per repo, with a link to the pinned commit. Read the full files at the source; licenses are listed per repo.
What the official docs say
Anthropic's own guidance is short, and most of the good public files follow it whether they cite it or not.
- Where it lives.
./CLAUDE.mdor./.claude/CLAUDE.mdfor the team (committed),CLAUDE.local.mdfor personal notes (gitignored),~/.claude/CLAUDE.mdfor you across all projects. Files from parent directories are all loaded; CLAUDE.md files in subdirectories load when Claude works there. Source: How Claude remembers your project. - Start with
/init, then add what Claude cannot discover. The generated file covers build commands and structure; your job is the non-obvious part. - Under ~200 lines, concrete and checkable. "Run
npm testbefore committing", not "test your changes".@pathimports organise a file but do not reduce what it costs in context. - The deletion test. For each line ask: "Would removing this cause Claude to make mistakes?" If not, cut it. Source: Best practices for Claude Code.
- Emphasis is a budget. Put IMPORTANT on the one rule that keeps getting skipped; if every line shouts, none stands out.
- CLAUDE.md is advice, not enforcement. A rule that must never be broken belongs in a hook or a permission rule (see the hooks cookbook). Procedures that only matter sometimes belong in skills.
The eight files at a glance
| Repo | Lines | Last change to CLAUDE.md | License | What the file is mostly for |
|---|---|---|---|---|
| anthropics/claude-code | 40 | 2026-09-29 | All rights reserved | Security rules for CI jobs that run Claude |
| anthropics/anthropic-quickstarts | 68 | 2026-09-22 | MIT | Shared conventions + per-project commands |
| oven-sh/bun | 240 | 2026-10-22 | MIT (bundled JavaScriptCore is LGPL-2) | The debug-build trap and test discipline |
| denoland/deno | 433 | 2026-07-30 | MIT | A full contributor guide |
| pytorch/pytorch | 365 | 2026-10-19 | BSD-3-style | AI policy + gotchas, each with its reason |
| mlflow/mlflow | 240 | 2026-10-21 | Apache-2.0 | Knowledge-cutoff note, supply-chain rule, PR scope |
| dagster-io/dagster | 120 | 2026-08-26 | Apache-2.0 | An index into .claude/*.md files |
| excalidraw/excalidraw | 34 | 2025-05-25 | MIT | Close to raw /init output |
Many other large repos do not keep a root CLAUDE.md at all (on 2026-10-22: vercel/next.js, microsoft/vscode, astral-sh/uv, openai/codex, vitejs/vite and others), and a growing group keep their rules in AGENTS.md and point CLAUDE.md at it. That pattern gets its own section below.
1. Bun: name the trap, then repeat it where it bites
From oven-sh/bun CLAUDE.md, lines 7–12 and 107–108:
- **Build Bun**: `bun bd`
- Creates a debug build at `./build/debug/bun-debug`
- **CRITICAL**: do not set a timeout when running `bun bd`
- **Run tests with your debug build**: `bun bd test <test-file>`
- **CRITICAL**: Never use `bun test` directly - it won't include your changes
- **Run any command with debug build**: `bun bd <command>`
...
- **CRITICAL**: Do not write flaky tests. Do not use `setTimeout` or `await sleep(N)` to wait for a condition; poll with a deadline or `await` the event itself. You are not testing the TIME PASSING, you are testing the CONDITION.
- **CRITICAL**: Verify your test fails with `USE_SYSTEM_BUN=1 bun test <file>` and passes with `bun bd test <file>`. Your test is NOT VALID if it passes with `USE_SYSTEM_BUN=1`.
Why it works. The most natural command in the repo, bun test, silently runs the installed Bun and so tests none of your changes. Claude cannot discover that from the code; a human contributor learns it once, painfully. The file names the trap, gives the right command, and adds a check that proves a new test actually exercises the fix (fails on the system binary, passes on the debug build). That last rule is a verification oracle, not advice.
What's weaker. The file also carries a long crate-by-crate source map, which the official guide explicitly says to leave out, and the pinned version has a stray duplicated line inside a test example (line 70). These files rarely get reviewed like code.
2. PyTorch: policy first, then gotchas that each carry a reason
From pytorch/pytorch CLAUDE.md, lines 5–8, 63–65 and 101–104:
- **You may never act autonomously on GitHub.** Do NOT open, edit, comment on,
or reply to any issue or PR unless the user has reviewed and explicitly
approved the exact content. Fully-agent-generated contributions are banned and
will be closed.
...
Always check local memory for build configuration (env vars, incremental-build shortcuts, etc.) before running the build, and apply what you find. If nothing applicable is in memory, ask the user.
All build (both codegen, C++ and python) is done via `pip install -e . -v --no-build-isolation`.
You should NEVER run any other command to build PyTorch.
...
Ruff's S101 (`Use of assert detected`) must be fixed by rewriting the assert,
never by adding `# noqa: S101`. The lint message itself suggests the noqa; ignore
that suggestion. Plain `assert` is stripped by `python -O`, so a suppressed
assert is a check that silently does nothing in an optimized run.
Why it works. Every rule states the consequence it prevents: closed PRs, a wrong build, a check that vanishes under python -O. Rules with reasons generalise; Claude can apply the S101 reasoning to a case the file never mentions. The file also routes multi-step procedures to skills instead of inlining them, which keeps it lean.
3. MLflow: tell Claude what it does not know
From mlflow/mlflow CLAUDE.md, lines 5–7 and 89–97:
## Knowledge Cutoff Note
Claude's training data may lag behind current releases. When reviewing docs or code, don't flag unfamiliar names as speculative or non-existent. Assume the authors are referencing newer, valid resources (e.g., model names like GPT-5, GitHub runner types like ubuntu-slim, library versions, etc.).
...
### Package Cooldown Period
7-day cooldown on new package releases to guard against compromised or broken
versions that get pulled and yanked within a few days. Keep these in sync:
- Python: `exclude-newer = "P7D"` in `pyproject.toml` (`torch`/`torchvision` opted out).
- JavaScript: `min-release-age=7` in `.npmrc`; `npmMinimalAgeGate: 7d` in `.yarnrc.yml`.
Pass `--min-release-age=7` to any new `npx` invocations.
Why it works. The knowledge-cutoff note fixes a real, recurring failure in code review: a model "correcting" a model name or runner type that is newer than its training data. The cooldown rule is a supply-chain control spread across four config files; writing down "keep these in sync" is the only way an agent touching one of them knows about the other three.
4. Anthropic's claude-code repo: a file that is only guardrails
From anthropics/claude-code CLAUDE.md, lines 10–16 (short quotation for commentary; the repo is not open-licensed):
1. **Egress-firewall runner.** The job has `runs-on: ubuntu-24.04-firewall`,
a GitHub-hosted runner that filters the job's outbound network traffic. Do
not move a job that calls Claude to another runner.
2. **Network allow list.** `.github/egress-firewall.yaml` lists the hosts
those jobs may reach, besides any that GitHub's firewall allows by default.
Keep `mode: enforce`, which is what makes the firewall block the rest. Follow
that file's header when you add a host.
Why it works. No build commands, no style rules: the whole 40-line file protects the CI jobs that run Claude. It also names the workflow check that fails the build when a protection is broken, so the prose is backed by enforcement. That pairing (rule in CLAUDE.md, check in CI or a hook) is the pattern to copy for anything that must not regress.
5. anthropic-quickstarts: conventions that fail silently get explained
From anthropics/anthropic-quickstarts CLAUDE.md, lines 21–27 and 49–52:
### Testing & Code Quality
- **Lint**: `ruff check .`
- **Format**: `ruff format .`
- **Typecheck**: `pyright`
- **Run tests**: `pytest`
- **Run single test**: `pytest tests/path_to_test.py::test_name -v`
...
- **TypeScript**: Strict mode with proper interfaces
- **Components**: Function components with React hooks
- **Formatting**: Follow ESLint Next.js configuration
- **UI components**: Use shadcn/ui components library
Load-bearing vs filler in one file. The command block is gold, especially the single-test invocation that saves a full-suite run on every iteration. The style bullets are what /init tends to produce: things Claude reads from tsconfig.json and the existing components anyway. The same file's best line is a tagging convention whose wrong value "is ignored for attribution, with no error to warn you" (line 7). Silent failures are exactly what CLAUDE.md is for.
6. Dagster: a hub file, and a lesson in shouting
From dagster-io/dagster CLAUDE.md, lines 5–9 and 117–120:
- **Package Locations**: [.claude/python_packages.md](./.claude/python_packages.md) - Comprehensive list of all Python packages and their filesystem paths. **ALWAYS check this file first when looking for package locations.**
- **Development Workflow**: [.claude/dev_workflow.md](./.claude/dev_workflow.md) - Documentation of developer workflows in the Dagster OSS repo.
- **UI Workflow**: [.claude/ui_workflow.md](./.claude/ui_workflow.md) - UI/TypeScript development workflows and verification commands. **ALWAYS check after UI edits.**
- **Coding Conventions**: [.claude/coding_conventions.md](./.claude/coding_conventions.md) - Type annotations and code style conventions. **ALWAYS check this before writing data structures - use @record instead of @dataclass.**
- **CRITICAL**: After ANY Python code changes, ALWAYS run `just ruff` - this is mandatory and must never be skipped.
...
### Git Operations
- **NEVER use `git push` directly** - always ask the user before pushing changes to remote
- Do not automatically do git commit --amend on user's behalf since you lose track of what the agent has done
What to take. The index shape is good: the root file stays short and points at topic files Claude reads only when relevant. The @record instead of @dataclass rule and the "don't search inside .tox" rule are pure codebase knowledge. What to avoid. ALWAYS, CRITICAL and MANDATORY appear on most lines, and just ruff is demanded three times. A rule that must run after every edit is a PostToolUse hook, not a paragraph.
7. Deno: a contributor guide is not a CLAUDE.md
From denoland/deno CLAUDE.md, lines 28–33 and 189–192:
- Before committing, make sure `tools/format.js` is run to format your code
- Before committing, if only non-Rust was changed, make sure to run
`tools/lint.js --js` and fix any lint errors before committing
- If you changed Rust code, make sure to run `tools/lint.js` and fix any lint
errors before committing
- In the PR description, provide a clear summary of the changes you made, why
...
The main form of integration test in deno is the "spec" test. These tests can be
found in `tests/specs`. The idea is that you have a `__test__.jsonc` file that
lays out one or more tests, where a test is a CLI command to execute and the
output is captured and asserted against.
Mixed. The repo-specific scripts and the custom spec-test format are exactly what Claude cannot infer from generic Rust knowledge. But at 433 lines, more than twice the ~200-line target, the file also carries a table of contents, a quick start and troubleshooting tips like checking your internet connection. Every one of those lines loads on every session.
8. Excalidraw: the minimum viable file
From excalidraw/excalidraw CLAUDE.md, lines 12–25:
## Development Workflow
1. **Package Development**: Work in `packages/*` for editor features
2. **App Development**: Work in `excalidraw-app/` for app-specific features
3. **Testing**: Always run `yarn test:update` before committing
4. **Type Safety**: Use `yarn test:typecheck` to verify TypeScript
## Development Commands
yarn test:typecheck # TypeScript type checking
yarn test:update # Run all tests (with snapshot updates)
yarn fix # Auto-fix formatting and linting issues
Good enough to start. Thirty-four lines, unchanged since May 2025: where to work, what to run before committing. (The original wraps the three commands in a bash fence.) This is roughly what /init gives you, and it is a fine floor. The rest of this guide is about what to add on top.
The sections that recur, and which ones earn their lines
Across the eight files and the Boris Cherny breakdown, the same five kinds of content show up.
| Section | Seen in | Load-bearing when… | Cargo cult when… |
|---|---|---|---|
| Exact commands (build, test, single test, lint) | all eight | the obvious command is wrong (Bun) or there is only one allowed way (PyTorch) | it repeats npm test that package.json already shows |
| Verification rules | Bun, PyTorch, Dagster, Excalidraw | it names a check that can fail: "fails with USE_SYSTEM_BUN=1, passes with bun bd test" |
it says "make sure everything works" |
| Workflow and git rules | Deno, MLflow, Dagster, PyTorch | CI enforces it (DCO sign-off, claude/ branch prefix) or it protects reviewers (one concern per PR, no force-push) |
it restates generic etiquette nobody would violate |
| Memory and context pointers | Dagster, PyTorch ("check local memory"), primer.md pattern | the target file exists, is current and is read only when relevant | it imports everything with @ and the context bill grows anyway |
| Tool and action bans | PyTorch (GitHub), Dagster (push, amend), claude-code (runners) | the ban carries a reason and, ideally, a hook or CI check behind it | it is the only defence for something irreversible |
Rules of thumb drawn from the table:
- A rule needs a reason or a check. "Never X" survives; "Never X, because Y" generalises to cases you did not list.
- Write down only what the code cannot tell Claude. Style that lives in a linter config is already enforced.
- Anything irreversible needs enforcement outside the file. CLAUDE.md is read by the model, so a confused turn or a prompt injection can still ignore it.
The @AGENTS.md pointer pattern
A large share of big repos now keep their real instructions in AGENTS.md, the cross-tool convention, and make CLAUDE.md a pointer. Checked on 2026-10-22:
- One-line
@AGENTS.mdimport: getsentry/sentry, n8n-io/n8n, astral-sh/ruff, supabase/supabase, modelcontextprotocol/python-sdk, tldraw/tldraw, mastra-ai/mastra, grafana/grafana, ggml-org/llama.cpp. cloudflare/workers-sdk uses a five-line stub that says "See @AGENTS.md". - Symlink: PostHog/posthog (to AGENTS.md), huggingface/transformers (to
.ai/AGENTS.md), zed-industries/zed (to.rules).
If your team uses more than one coding agent, this is the sane default: one source of truth, and the official docs say Claude Code reads AGENTS.md when no CLAUDE.md exists. Put Claude-only material (hooks to know about, skills to use) below the import.
What the saved posts add
The DejaViewed catalog has a run of posts about CLAUDE.md. The useful ideas, with the posts they came from:
- Update it after every correction. Boris Cherny's team habit: end a correction with "update your CLAUDE.md so you don't make that mistake again" (Claude Code team tips). His personal file adds plan mode first, subagents for complex work and a lessons file (breakdown by @keshavsuki, the template version). Full analysis: Boris Cherny's CLAUDE.md.
- Keep volatile state out of it. CLAUDE.md goes stale when it carries "current status". A separate
primer.mdthat Claude rewrites at the end of each session, plus a launch hook that injects recent commits, keeps CLAUDE.md for durable rules (primer.md + memory.sh; guide: The primer.md pattern). - Prune for newer models. Rules written for older models can hold newer ones back; audit every rule and skill and delete dead weight (Claude setup purge). This matches the official deletion test.
- Give it a stable home in a file tree. A brain folder with CLAUDE.md, per-project context files and a short-term NOW file survives across sessions (agent workspace file tree).
- Domain rules belong there too. Design rules for a website build (Claude Code website build), UX laws as instructions (UX laws cheat sheet), or a writing style blacklist enforced by rules plus hooks (Humanizer skill).
- Know what you are overriding. The leaked system-prompt "brevity mandate" pushes minimal diffs; some projects override it in CLAUDE.md when code quality matters more (brevity mandate critique; see the leaked system prompt guide).
- Intro-level explainers. CLAUDE.md explained and have Claude build its own status dashboard are lighter, but fine starting points.
A minimal starter template
An original template that follows the patterns above. Replace every angle-bracket placeholder; delete any section you cannot fill with something specific.
# <project> — notes for Claude
## Commands
- Install: `<exact command>`
- Test one file: `<exact command> <path>` # use this while iterating
- Full suite: `<exact command>` # run before saying a task is done
- Lint/format: `<exact command>` # a PostToolUse hook also runs this
## Traps (things the code will not tell you)
- `<obvious command>` does NOT do what it looks like: <why>. Use `<right command>`.
- `<generated file>` is generated from `<source>`; edit the source, then run `<cmd>`.
- <env quirk, port, service that must be running, flaky area>
## Verification
- A task is done when `<test command>` passes and <observable check>.
- A new test must fail without the fix and pass with it.
## Boundaries
- Never <irreversible action> without asking: <reason>. (Enforced by <hook / CI check>.)
- Do not edit <paths> (<reason>).
## Pointers
- Architecture decisions: @docs/architecture.md
- Current state / next steps: primer.md (rewritten at end of each session)
Thirty lines or so. It grows only when a correction teaches you something the code cannot.
Anti-patterns
- The style essay. "Write clean, maintainable, well-documented code." Claude already tries; the line only costs context.
- The everything-is-CRITICAL file. When most lines shout, emphasis stops working. Spend it on one rule.
- The contributor guide paste. Table of contents, project history, troubleshooting for humans. Link to it instead.
- File-by-file maps. They rot fastest and Claude can list the directory itself.
- Status in the rules file. "Currently working on X" belongs in primer.md or an issue tracker.
- Advice standing in for enforcement. "Never push to main" with no hook or branch protection behind it.
- Write-only files. Rules added after incidents and never pruned; contradictions between old and new lines. Review it like code, and check what loaded with
/context. - Personal preferences in the team file. Put them in
CLAUDE.local.mdor~/.claude/CLAUDE.md.
Bottom line
Start from /init, then add only what the code cannot tell Claude: the command that looks right but isn't, the generated file you must not edit, the check that proves a change works, and the actions that need a human. Give every rule a reason, back the irreversible ones with a hook or CI check, keep volatile state in a separate file, and delete any line that fails the "would Claude get this wrong without it?" test.
Prompt system — run this yourself
Everything below is pasteable into Claude Code, Claude, or any agent. Use the one-shot when you want the whole result in one run; use the step prompts when you want to steer. Every step carries its own audit, and the gap audit at the end makes the agent find and fill what it missed.
Mission. Produce an evidence-backed CLAUDE.md for one real repository the user owns. Every line traces to a trap, command, check or ban the code cannot reveal. Irreversible rules are backed by a hook or CI check, and volatile state moves to primer.md. Done means an A/B run of 5 fixed tasks shows fewer trap hits or tool calls than no file and the old file, lint finds zero cargo-cult lines, and the file stays under 200 lines.
1 · Deeper, not bigger
Before running anything, make the task deeper rather than larger. Ask: what would a top professional do here that I am not asking for; what is the rawest material; which methods and tools; what, other than the model or me, proves it right. Then ask for exactly that.
- What a top professional would do (that you didn't ask for): A staff engineer would not copy Boris Cherny's sections or another repo's file. They would mine their own repo's failure history first: commands that look right but are wrong (Bun's
bun testversusbun bd test), generated files, flaky areas, and corrections typed into past sessions. Each line faces the official deletion test, 'Would removing this cause Claude to make mistakes?', with a measurement behind it. Anything irreversible becomes a hook or CI check, as the claude-code repo backs its egress-firewall rules with a workflow check. Then they A/B the file on real tasks instead of trusting how it reads. - Rawest material to start from: 1) The user's repo: package.json, pyproject.toml, Makefile or justfile,
.github/workflows/*.yml, linter configs, reverts ingit log, and any existing CLAUDE.md, AGENTS.md or CLAUDE.local.md. 2) Past transcripts in~/.claude/projects/<repo-slug>/*.jsonl, which record every correction the user typed. 3) The eight pinned files, read withgit show <sha>:CLAUDE.md: oven-sh/bun fec4a88, pytorch/pytorch 63ad7b4, mlflow/mlflow 007775d, anthropics/claude-code 7dbaea2, anthropics/anthropic-quickstarts 09bdac6, dagster-io/dagster f4de047, denoland/deno c439c90, excalidraw/excalidraw cc571c4. 4) code.claude.com/docs/en/memory and /best-practices. - Methods and tools:
git clone --filter=blob:noneplusgit show <sha>:CLAUDE.md | wc -lto verify quotes and line counts./initfor a baseline to diff against./contextfor the memory token cost.jqover transcript JSONL to pull correction turns.git worktree addfor isolated eval arms.claude -p '<task>' --output-format stream-json --verbosefor headless runs, countingtool_useevents. A stdlib Python lint that tags lines and flags filler, missing reasons, shouting density and discoverable rules. PreToolUse and PostToolUse hooks pluspermissions.denyin.claude/settings.json. - What proves it right (other than you or the model): A headless A/B eval: the same 5 tasks in three arms (no file, old file, new file), 3 runs each, scored on tool calls, wrong-command invocations, acceptance-test passes and wall time. A fails-without/passes-with proof for each trap, after Bun's
USE_SYSTEM_BUN=1rule. A hook test that attempts each banned action and is blocked. A cold-start teammate who completes a real task with the file.git showdiffs confirming every quote matches its pinned commit.
Rewritten prompt — ask for exactly that:
Write a CLAUDE.md for my repo at <path>, built from evidence, not templates. First mine ground truth: read the build, test and lint configs and CI workflows, and run each command. Note which obvious command is wrong, list generated files, and pull every correction I typed from ~/.claude/projects/<slug>/*.jsonl. Calibrate against eight files read with git show at pinned commits: bun fec4a88, pytorch 63ad7b4, mlflow 007775d, anthropics/claude-code 7dbaea2, anthropic-quickstarts 09bdac6, dagster f4de047, deno c439c90 and excalidraw cc571c4. Give every line a source and a reason. Cut anything a linter config, package.json or the directory tree already says. Keep the file under 200 lines with at most one ALL-CAPS rule. Turn every irreversible ban into a PreToolUse hook or CI check and name it in the file. Move status to primer.md. If AGENTS.md exists, start with @AGENTS.md. Prove it with 5 real tasks run headless with no file, the old file and the new file, 3 runs each. Return the file, a provenance table, the hook config, the eval table and a gap list.
2 · One-shot prompt
ROLE AND STANDPOINT: You are a staff engineer writing the CLAUDE.md for the repository at <REPO_PATH>. Treat the file as code. Every line must earn its context cost with evidence, and anything that must never happen gets enforcement outside the file. Do not copy template sections such as Boris Cherny's 'Workflow Orchestration' unless this repo's evidence calls for them.
CONTEXT:
- The official docs (code.claude.com/docs/en/memory and /best-practices) set a target under about 200 lines and ask for concrete, checkable lines. They pose the deletion test: 'Would removing this cause Claude to make mistakes?' Emphasis is a budget, and CLAUDE.md is advice, not enforcement.
- Reference files, read at pinned commits with `git show <sha>:CLAUDE.md`. oven-sh/bun fec4a8850: `bun test` runs the installed Bun, so use `bun bd test`, and a test must fail with USE_SYSTEM_BUN=1. pytorch/pytorch 63ad7b4a3: each gotcha carries its reason. mlflow/mlflow 007775d93: a knowledge-cutoff note and a cooldown kept in sync across 4 configs. anthropics/claude-code 7dbaea237: 40 lines of CI guardrails backed by a workflow check. dagster-io/dagster f4de04765: a good index file, but CRITICAL on most lines. denoland/deno c439c90d8: a 433-line contributor guide. excalidraw/excalidraw cc571c468: 34 lines, close to /init output.
- The @AGENTS.md pointer pattern (getsentry/sentry, astral-sh/ruff) and the primer.md pattern for volatile state.
HARD CONSTRAINTS:
1. Every line has a provenance entry: file:line, transcript turn, command output or CI log.
2. Under 200 lines, with at most one IMPORTANT or CRITICAL.
3. No line restates package.json, a linter config, tsconfig or the directory tree.
4. Every 'never' rule states its reason. Each irreversible one names the hook, deny rule or CI check that enforces it, which you also write.
5. No status, TODOs or dates. Those go to primer.md. Personal preferences go to CLAUDE.local.md.
6. Verify every public quote against its pinned SHA.
DELIVERABLES, IN ORDER:
1. ground_truth.md: commands run with exit codes, generated files, CI checks, memory files with line and /context token counts, and corrections mined from ~/.claude/projects/<slug>/*.jsonl.
2. lint_old.csv: each existing line (or /init output) tagged and marked keep, cut, move-to-hook or move-to-primer.
3. CLAUDE.md shaped as Commands, Traps, Verification, Boundaries and Pointers, using only the sections evidence fills.
4. provenance.csv mapping each line to a source and a reason.
5. Hook and permission changes in .claude/settings.json, plus a test showing each ban blocked.
6. eval/: 5 real tasks, a runner for three arms (none, old, new) with 3 runs each via `claude -p --output-format stream-json`, and results.csv.
7. gap_report.md.
BUILT-IN GAP ANALYSIS: Keep a GAPS list as you work. Log suspected traps you could not reproduce, commands you could not run, corrections you could not classify, and rules kept without measurement. Fill what you can before finishing and mark the rest UNVERIFIED with a reason.
SELF-QUESTIONS BEFORE FINISHING:
- Which obvious command here does the wrong thing, and does the file name it?
- Which line would I cut first, and why is it still there?
- Does each verification rule name a check that can fail?
- Which ban has no hook behind it?
- Did ~/.claude/CLAUDE.md load identically in every eval arm?
- Did any eval prompt hint at the rule it tests?
STOP CONDITIONS: Stop when the new arm is no worse than old on every metric and better on at least one, lint is clean and every hook test passes. Stop and ask if the eval would touch production, push to a remote or need secrets you lack.
RETURN FORMAT: A table of deliverable paths. An eval table with arms as rows and median tool calls, trap hits, acceptance passes and wall time as columns. Final line count and token count. The GAPS list marked VERIFIED, UNVERIFIED or FIXED.
3 · Step-by-step prompts
Step 1 — Establish ground truth
Goal: Inventory what the user's repo actually does and verify the eight reference files at their pinned commits.
Build ground_truth.md for the repo at <REPO_PATH>. Part A, the user's repo: list every memory file present (CLAUDE.md, .claude/CLAUDE.md, CLAUDE.local.md, AGENTS.md, subdirectory CLAUDE.md files, ~/.claude/CLAUDE.md) with line counts, and record the memory token cost from /context. Read package.json, pyproject.toml, Makefile, justfile and .github/workflows/*.yml. Extract every build, test, single-test and lint command. Run each one and record exit code and duration. Mark any command whose obvious form is wrong, as `bun test` is in Bun. List generated files and the scripts that produce them. Part B, the reference corpus: in scratch, `git clone --filter=blob:none` oven-sh/bun, pytorch/pytorch, mlflow/mlflow, anthropics/claude-code, anthropics/anthropic-quickstarts, dagster-io/dagster, denoland/deno and excalidraw/excalidraw. Run `git show <sha>:CLAUDE.md | wc -l` at fec4a8850, 63ad7b4a3, 007775d93, 7dbaea237, 09bdac604, f4de04765, c439c90d8 and cc571c468. Expect 240, 365, 240, 40, 68, 120, 433 and 34 lines.
Expect: ground_truth.md with a commands table (command, source, exit code, seconds, trap y/n), a generated-files list, a memory-files table and an 8-row reference table of expected and observed line counts.
Audit before moving on: Fail if any command was listed but not run without a stated reason, or if a reference count differs without a note. Re-run or re-check out the SHA. Never edit the expected numbers to match.
Step 2 — Mine corrections and failure history
Goal: Turn past sessions and git history into a ranked list of mistakes Claude actually makes in this repo.
Using ground_truth.md, mine evidence of real mistakes. 1) Run `jq -r 'select(.type=="user") | .message.content | strings' ~/.claude/projects/<slug>/*.jsonl` and keep user turns that correct the agent: 'no', 'don't', 'wrong', 'use X instead', 'I told you', and every 'update your CLAUDE.md' request, which is Boris Cherny's team habit. 2) Read the reverts, fixups and follow-up fix commits from `git log --oneline -n 200`. 3) Read the last 30 CI failure logs if `gh run list` works. 4) Cluster each correction as wrong command, edited generated file, skipped verification, unwanted irreversible action, linter-catchable style, stale knowledge (the MLflow knowledge-cutoff case) or scope creep. Count each cluster. Write corrections.csv with turn_ref, quote, cluster, count and candidate_rule. Write every candidate rule PyTorch style, as 'Never X, because Y'.
Expect: corrections.csv sorted by count, with at least 10 rows if transcripts exist, each citing a transcript file and line or a commit SHA.
Audit before moving on: Fail if a candidate_rule lacks a reason or a traceable quote. Fail if linter-catchable style produced a rule, because it belongs in the linter config. If no transcripts exist, log the gap and use git and CI only.
Step 3 — Lint the existing file
Goal: Score every current line against the deletion test and the recurring-sections table.
Write lint_claude_md.py using only the standard library. It tags each non-blank line as command, trap, verification, workflow_git, pointer, boundary or filler, and raises these flags. FILLER: no command, path, tool name or number, as in 'write clean, maintainable code'. NO_REASON: a never, always or must rule with no reason or named check. SHOUTING: ALWAYS, NEVER, CRITICAL, MANDATORY or IMPORTANT more than once per 40 lines, the Dagster failure. DUPLICATE: a command demanded twice or more, as Dagster demands `just ruff` 3 times. DISCOVERABLE: restates a package.json script or a rule in .eslintrc, ruff.toml or tsconfig. VOLATILE: holds a date, 'currently' or an unfinished to-do marker. MAP: a file-by-file source map. UNENFORCED_BAN: a push, force, delete, deploy or publish ban with no matching hook in .claude/settings.json. Run it on the user's file, or on fresh /init output if none exists, and on all 8 reference files as calibration. Write lint_old.csv with line, text, tag, flags and decision.
Expect: lint_claude_md.py, lint_old.csv and a calibration table of flag counts for each reference repo.
Audit before moving on: Calibration must match the guide: Dagster flags SHOUTING and DUPLICATE, Deno is flagged for length, Excalidraw is mostly commands, and PyTorch has few NO_REASON flags. If not, fix the heuristics before trusting them.
Step 4 — Draft the new CLAUDE.md
Goal: Write the smallest file that encodes every evidenced trap, command, check and boundary.
From ground_truth.md, corrections.csv and lint_old.csv, draft CLAUDE.md in the guide's starter shape: Commands (install, test one file, full suite, lint), Traps, Verification, Boundaries and Pointers. Fill a section only with evidenced lines, and delete any section you cannot fill. Each trap names the wrong command, why it is wrong and the right one. Each verification line names a check that can fail. If the repo has a without-fix / with-fix toggle like Bun's USE_SYSTEM_BUN=1, encode it. Each boundary states its reason and its enforcer. If the model keeps 'correcting' newer names, add MLflow's knowledge-cutoff note. If AGENTS.md exists or the team uses other agents, make line 1 `@AGENTS.md`, move the shared rules there, and keep only Claude-specific notes below. Point current state at primer.md and put personal preferences in CLAUDE.local.md. Write provenance.csv with each line number, its source and its reason.
Expect: CLAUDE.md under 200 lines, ideally 30 to 80, and provenance.csv with one row per non-blank line.
Audit before moving on: Run the linter on the draft. Fail on FILLER, NO_REASON, DUPLICATE, DISCOVERABLE, VOLATILE or MAP, on more than one emphasis keyword, or on a line without provenance. Fix and re-lint. UNENFORCED_BAN may stand until step 5.
Step 5 — Move enforcement out of prose
Goal: Back every irreversible boundary with a hook, permission rule or CI check, and prove each one blocks.
For each Boundaries line, add real enforcement. 1) Irreversible shell actions such as `git push`, `git push --force`, `rm -rf`, deploys and package publishing get a PreToolUse hook on the Bash matcher in .claude/settings.json. The script reads tool-input JSON on stdin and exits 2 with a reason on a match. Use a `permissions.deny` rule where a pattern suffices. 2) A run-after-every-edit rule, like Dagster's `just ruff`, becomes a PostToolUse hook on Edit|Write, and the prose shrinks to 'a PostToolUse hook runs <cmd>'. 3) Rules that must hold in CI follow the anthropics/claude-code pattern: point to a workflow step that fails the build. 4) Procedures needed only sometimes move to .claude/skills/<name>/SKILL.md, as PyTorch routes procedures to skills. Write tests/hooks_test.sh, which pipes crafted JSON into each hook and asserts exit 2 for banned inputs and exit 0 for allowed ones. Update CLAUDE.md so each boundary names its enforcer.
Expect: Updated .claude/settings.json, hook scripts in .claude/hooks/, a passing hooks_test.sh, and zero UNENFORCED_BAN flags.
Audit before moving on: Run hooks_test.sh and show the output. Fail if a banned case exits 0 or an allowed one exits 2. Add near-misses such as git push --dry-run and git status as allowed cases.
Step 6 — Build the A/B session eval
Goal: Measure whether the new file changes behavior on real tasks.
Create eval/. Pick 5 tasks from the last month of real work, each under 15 minutes. At least 2 must hit a documented trap, such as needing the single-test command or touching a generated file. At least 1 must tempt a boundary, such as 'ship this fix', which invites a push. Write tasks as plain requests that never mention the rule under test. Create three git worktrees from one base SHA: arm_none without CLAUDE.md, arm_old with the original and arm_new with the new file and hooks. Keep ~/.claude/CLAUDE.md identical across arms and record its hash. run.sh runs each arm, task and run 1-3 with `claude -p "$(cat tasks/N.md)" --output-format stream-json --verbose > logs/<arm>_<N>_<run>.jsonl` and records wall time. score.py counts tool_use events, known-wrong commands from the trap list, blocked-hook events, edits to generated files, and whether the acceptance test passes. Headless runs get no corrections, so trap hits and failed acceptance tests stand in for them.
Expect: eval/tasks/1..5.md, run.sh, score.py, 45 logs and results.csv with one row per arm, task and run.
Audit before moving on: Fail if arms differ in base SHA, a prompt names its rule, or a log is empty or truncated. Re-run failures. A win in 1 of 3 runs does not count.
Step 7 — Validate against oracles and write the gap report
Goal: Decide ship or revise on external evidence and record what is still unproven.
Run every oracle and write gap_report.md. 1) A/B: compute medians per arm from results.csv. The new arm passes if acceptance passes are at least equal to the old and none arms, and trap hits or tool calls are strictly lower. 2) Traps: for each Traps line, show the wrong command misbehaving and the right one working, Bun-style. 3) Hooks: paste hooks_test.sh output. 4) Lint: show zero flags, the line count, and the /context token cost before and after. 5) Quotes: diff each cited reference excerpt against `git show <sha>:CLAUDE.md | sed -n '<range>p'`. 6) Have a teammate, or a fresh agent session with no history, do one task cold and record where it stalled. List every CLAUDE.md line the eval never exercised as UNMEASURED. Rank the gaps by the cost of the mistake they allow. Cut cheap UNMEASURED lines and note the rest for the next correction cycle. End with ship or revise.
Expect: gap_report.md with the A/B table, trap proofs, hook results, lint and token delta, quote diffs, cold-start notes, an UNMEASURED list and a verdict.
Audit before moving on: Fail if the verdict is ship while any oracle failed or was skipped without a reason. If A/B shows no gain, say so, cut the file toward the minimum and re-run step 6.
4 · Gap analysis and audit
Run this after the build. It makes the agent enumerate its own claims, mark what is verified, rank the gaps and fix the top ones.
You are an independent auditor who did not write this CLAUDE.md. Inputs: CLAUDE.md, provenance.csv, ground_truth.md, corrections.csv, .claude/settings.json, hooks_test.sh, eval/results.csv and gap_report.md. 1) List every claim the file makes: each command, trap, verification rule and boundary. Mark each VERIFIED if you re-ran it this session and it behaved as stated, UNVERIFIED if you could not run it, or FALSE if it behaved differently, with output attached. 2) Re-run lint_claude_md.py and hooks_test.sh yourself instead of trusting pasted output. 3) Sample 10 provenance rows and open each cited source. Mark any row whose source does not say what the row claims. 4) Look for what is missing: a correction cluster with no rule, a CI check that often fails but goes unmentioned, an unlisted generated file, or a boundary with no enforcer. 5) Check the eval for confounds: shared base SHA, identical user-level memory, hint-free prompts and 3 runs per cell. 6) Rank findings by the cost of the mistake each allows. Fix the top 3 now and re-lint. 7) Report the claims table, the fixes and what you could not fix and why.
Questions the agent must ask itself before it says done:
- Which command in this repo looks right but silently does the wrong thing, the way
bun testdoes in Bun, and is it in Traps? - Did I read every reference excerpt at its pinned SHA, or trust the guide's quote?
- Which lines would /init have produced anyway, and do they pass the deletion test?
- Does any line restate what ruff.toml, .eslintrc, tsconfig or package.json already enforces?
- Is there a without-fix / with-fix toggle here like USE_SYSTEM_BUN=1, and did I encode it?
- Which correction cluster from the transcripts has no rule, and is that deliberate?
- Does every never rule carry a reason, so Claude can generalize it the way PyTorch's S101 rule generalizes?
- Which ban is still prose only, and what would get through a confused turn or a prompt injection?
- If a teammate runs Codex or Cursor, do they get the same rules through AGENTS.md?
- Did user-level and parent-directory CLAUDE.md files load identically in every eval arm?
- Am I winning only on tasks chosen because they test my rules?
5 · What proves it right
- Headless A/B eval:
claude -pruns 5 real tasks in three arms from one base SHA, 3 runs each. The new arm's median trap hits and tool calls are at or below both others, with acceptance tests passing at least as often. - Trap reproduction, Bun-style: each Traps line has captured output of the wrong command misbehaving and the right one succeeding.
- hooks_test.sh: crafted tool-input JSON for each banned action makes the PreToolUse hook exit 2, and near-misses like
git push --dry-runexit 0. - Pinned-commit diff:
git show <sha>:CLAUDE.mdmatches every cited excerpt exactly, and line counts match 240/365/240/40/68/120/433/34. - Cold-start reviewer: a teammate or fresh agent session completes one eval task from the new file alone without stalling on missing context.
6 · Failure modes
- Cargo-culting a template. Sign: sections like 'Self-Improvement Loop' with no provenance row. Fix: delete every line without a source in this repo.
- Everything is CRITICAL. Sign: the SHOUTING flag fires and the one rule that matters still gets skipped. Fix: keep one emphasis keyword and turn other must-run rules into hooks.
- Advice standing in for enforcement. Sign: a 'never push' line with no hook, and an eval run that pushes. Fix: add a PreToolUse hook or deny rule and test it.
- Contributor-guide bloat, Deno-style. Sign: over 200 lines, a table of contents and a high /context cost. Fix: link the human guide and keep only agent-relevant traps.
- Unmeasured wins. Sign: one lucky run, or task prompts that hint at the rule. Fix: 3 runs per cell, hint-free tasks, and honest no-gain reports.
- Write-only growth and forked truth. Sign: contradicting rules, rising length, or other agents breaking rules Claude follows. Fix: re-lint after every correction and use @AGENTS.md as the single source.
7 · Agent direction (unattended runs)
Start with local evidence: repo configs and CI, then transcripts in ~/.claude/projects, then the 8 reference repos cloned with --filter=blob:none into scratch. Cache excerpts and line counts in refs.json so they are fetched once. Spawn one sub-agent for the mechanical reference verification in step 1. Spawn another to write the eval tasks in step 6 without seeing CLAUDE.md, so the prompts stay hint-free. Keep the keep/cut decisions and the ship verdict in the main loop. Work in a branch or worktree. Never push, publish or edit CI on a shared branch. Ask before merging hooks that block teammates' commands, and ask if tasks need secrets or production services. Cap the eval at 45 headless runs and report the spend. Return CLAUDE.md, provenance.csv, settings and hook changes, lint_claude_md.py, eval/ with results.csv, gap_report.md, and a summary of line count, token cost before and after, A/B medians and the verdict.
Prompt system updated 2026-10-22 · all prompt systems · JSON