ON THIS PAGE (9 SECTIONS)
- ✓CLAUDE.md works best as project memory — commands, conventions, and architecture notes — not as a wishlist of behaviors you hope the model follows.
- ✓Explicit off-limits sections (migrations, auth, billing) matter more than general instructions like "be careful."
- ✓Keep it short and specific. A long CLAUDE.md that repeats itself gets skimmed the same way a long onboarding doc does.
CLAUDE.md is a plain markdown file that Claude Code reads automatically at the start of a session, and most of the confusion we see about it comes from treating it like a prompt — something you write once, hoping the right phrasing will make the agent behave. It works much better treated as project memory: the things a new engineer would need to know before touching the codebase, written down so the agent does not have to rediscover them, or guess, every single session.
The useful contents of a CLAUDE.md fall into a few concrete categories: what the project actually is, the exact commands to build, run, and test it, the conventions we expect code to follow, which parts of the codebase are off-limits without a human sign-off, and a short note on what "done" means before the agent reports back. None of this is exotic. It is the same information you would put in a README for a human, except phrased as instructions and kept short enough that it does not get lost in a long context window.
What actually earns a spot in the file
Commands are the highest-value section, because agents will guess at build and test commands if you don't give them, and the guesses are frequently wrong for anything beyond a bare `npm test`. Writing the exact commands — including flags for a specific test suite, or a typecheck step separate from the build — saves a surprising number of wasted iterations where the agent runs the wrong thing, sees a confusing error, and starts debugging a problem that does not exist.
The off-limits section is the one we are strictest about, because it is the one place where a vague instruction is genuinely dangerous. "Be careful with authentication code" is not a boundary; an agent can read that and still decide a specific change looks safe. Naming the exact files or directories — migrations, auth middleware, billing webhooks, deploy configuration — and saying explicitly that changes there require a human before merge is a boundary an agent can actually respect, because it does not require judgment to follow.
The instructions that work are the ones that remove judgment calls, not the ones that ask for better judgment. "Never bypass signature verification" is enforceable. "Write secure code" is not.
A generic template
This is close to the shape we use across our own projects, stripped of anything specific to a particular codebase. It is meant to be a starting point, not something to copy verbatim — the value is in the specificity you add for your own project, not the section headers themselves.
| 1 | # Project: <name> |
| 2 | |
| 3 | ## What this is |
| 4 | One or two sentences describing what the product does and who uses it. |
| 5 | Agents work better with context, not just rules. |
| 6 | |
| 7 | ## Commands |
| 8 | - Install: `npm install` |
| 9 | - Dev server: `npm run dev` |
| 10 | - Build: `npm run build` |
| 11 | - Test (unit): `npm run test` |
| 12 | - Test (e2e): `npm run test:e2e` |
| 13 | - Lint: `npm run lint` |
| 14 | - Type check: `npm run typecheck` |
| 15 | |
| 16 | ## Before you say you're done |
| 17 | - Run lint and typecheck, and fix anything you introduced. |
| 18 | - Run the relevant test suite. Do not report success without running it. |
| 19 | - Do not claim a fix works if you have not executed the code path. |
| 20 | |
| 21 | ## Code conventions |
| 22 | - TypeScript, strict mode. No `any` unless justified in a comment. |
| 23 | - Functional React components, no class components. |
| 24 | - Styling: Tailwind utility classes only, no inline styles. |
| 25 | - Prefer editing existing files over creating new ones. |
| 26 | |
| 27 | ## Off-limits without explicit human approval |
| 28 | - /migrations/** — schema changes are reviewed by a human before merge. |
| 29 | - /src/lib/auth/** — authentication and session logic. |
| 30 | - /infra/** — Terraform and deployment configuration. |
| 31 | - Anything that touches billing or payment webhooks. |
| 32 | |
| 33 | ## Architecture notes |
| 34 | - API routes live in /src/server/routes, one file per resource. |
| 35 | - Shared types live in /src/types and are the source of truth — don't |
| 36 | redefine shapes inline elsewhere. |
| 37 | - Background jobs go through the queue in /src/jobs/queue.ts; don't call |
| 38 | external APIs directly from request handlers. |
| 39 | |
| 40 | ## Git / PR conventions |
| 41 | - Small, focused commits. One logical change per commit. |
| 42 | - Branch names: feature/<short-name> or fix/<short-name>. |
| 43 | - Do not force-push to main. |
| 44 | |
| 45 | ## What "done" looks like |
| 46 | A change is done when it builds, passes lint and tests, and includes any |
| 47 | necessary doc or comment updates. Partial implementations should say so |
| 48 | explicitly rather than being presented as complete. |
How we actually use this
In practice, our own CLAUDE.md files are shorter than the template above and grow over time rather than being written all at once. We add a line to the off-limits section the first time an agent gets close to something we did not want touched, and we add a command when we notice an agent guessing at one instead of using the one we meant. It is a living document that reflects mistakes we have already caught, not a spec we designed up front — which is honestly how most useful engineering documentation gets written, human-facing or not.
Nested files for larger codebases
Claude Code will also pick up a CLAUDE.md placed in a subdirectory, and that matters once a codebase is big enough that one root-level file starts trying to describe too many unrelated parts of the system. A monorepo with a frontend, a backend API, and an infrastructure directory benefits from three shorter, focused files instead of one long one that mixes React conventions with Terraform rules. We keep the root file for things that are true everywhere — the overall architecture, the top-level commands, the universal off-limits list — and push anything specific to one part of the codebase down into that directory's own file. This also means an agent working only in the frontend does not have to load context about infrastructure conventions it will never touch in that session.
Length is a cost, not a virtue
The instinct when something isn't working is often to add more instructions. We have found the opposite is usually true for CLAUDE.md: a file that has grown past a page or two starts getting skimmed the same way a long onboarding document gets skimmed by a new hire, and instructions buried in the middle stop having any effect at all. When a section gets long, that is usually a sign it should be a rule about a specific file path rather than a paragraph of general guidance. We periodically go back and cut lines that turned out not to matter, the same way we would prune a stale comment in the code itself.
Who actually owns the file
A question we underestimated early on: who is allowed to edit CLAUDE.md, and does a change to it get reviewed like any other change? We treat it exactly like code now — edits go through a pull request, and a change to the off-limits section in particular gets read carefully, because loosening a boundary there is a security-relevant decision even though the file itself is just markdown. Early on we let anyone update it ad hoc when something annoyed them in a session, and the file drifted into contradicting itself within a couple of months — one section said to always run the full test suite, another said unit tests were sufficient for small changes, and nobody had reconciled the two. Treating it as reviewed documentation rather than a scratchpad fixed that.
What this does not replace
We do not treat CLAUDE.md as a substitute for review, and we would be overstating its value if we implied otherwise. It reduces the number of times an agent wanders somewhere it should not and cuts down on wasted iterations from wrong commands, but the final gate on anything that ships is still a named engineer reading the actual diff. A well-written CLAUDE.md makes that review faster and less frustrating; it does not make it optional. Any team telling you an instructions file alone is sufficient governance for AI-written code is skipping the part of the job that actually matters.
The mistake we see most often when teams first try this
The most common misstep is writing a CLAUDE.md once, during a burst of enthusiasm after setting up Claude Code for the first time, and then never touching it again. It reads well on day one and quietly goes stale — a command changes, a new directory gets added that should be off-limits, a convention shifts — and six months later the file is actively giving wrong instructions instead of no instructions, which is worse than not having one at all. The fix is not complicated: review it the same way you would review any documentation that has drifted, on a cadence tied to actual changes in the project rather than a calendar reminder nobody acts on. If a pull request changes the build command, updating CLAUDE.md is part of that same pull request, not a follow-up task that never happens.
If you are integrating AI coding agents into your own workflow and want help setting up guardrails that hold up under real usage rather than looking good in a demo, that is the kind of AI Integration work we take on — the boring, specific instructions that actually change agent behavior, not a slide about "AI governance."
References & Prior Art
Claude Code Architecture and Project Steering Configuration
Anthropic Developer Relations • Anthropic PBC (2025)
Context Engineering for Coding Agents: Steering LLMs with Repository Architecture
Simon Willison • Simon Willison’s Weblog (2025)
Vishal
Founder & Engineering LeadVishal leads engineering at Vasiva, establishing project memory conventions, tool boundaries, and architecture rules for coding agents.