CLAUDE.md is the instruction file Claude Code reads before doing anything in your project. Get it right and Claude works the way you expect — respecting your conventions, staying inside its lane, and remembering what matters between sessions. Get it wrong and you spend time correcting outputs that should have been right the first time. This guide covers everything you need to write one that actually works.
When Claude Code starts a session in a project, it looks for a CLAUDE.md file in the repository root and loads it automatically. No API call required, no system prompt to configure — it's just a Markdown file that Claude reads as its operating instructions for that codebase.
This matters because the default behavior of a general-purpose model is rarely the right behavior for a specific project. Your team might use tabs over spaces, a custom commit message format, a specific test runner, or a policy about never modifying generated files. None of that is in Claude's training data. Without a CLAUDE.md, you're correcting those details on every session. With one, you say it once and it sticks.
The file also travels with the codebase. New contributors get the same Claude behavior as the rest of the team. Agents running in CI see the same instructions as the developer running locally. That consistency is worth a lot in practice.
Most effective CLAUDE.md files share the same structure: a brief identity section, a capabilities block, explicit permissions, behavioral preferences, and iron laws. The order matters — Claude's attention is highest on early content.
# [Project or Agent Name]
[One sentence: what this agent does or what this project is.]
## CRITICAL: [Most important constraint]
[State it plainly. NEVER do X — instead do Y.]
## Project Context
- Language / stack: [e.g., TypeScript, Node 20, Postgres]
- Test runner: [e.g., Vitest — run with `npm test`]
- Linter: [e.g., ESLint — run with `npm run lint`]
- Key conventions: [e.g., use named exports, no default exports]
## Permissions
- You MAY read any file in this repo without asking
- You MAY run `npm test` and `npm run lint` without asking
- You MUST ask before: deleting files, modifying lock files,
making network requests, pushing to remote
## Behavior
- Prefer editing existing files over creating new ones
- Match the style of the surrounding code — don't introduce new patterns
- When uncertain, show the plan before executing it
- Keep commits atomic: one logical change per commit
## Memory
- Store session notes in /docs/agent-notes.md
- Check that file at session start for ongoing work context
## Iron Laws
1. NEVER commit secrets, API keys, or credentials — instead
warn and suggest environment variables
2. NEVER modify files in /generated/ — instead regenerate
them using the documented build command
3. NEVER run destructive database commands without a dry-run
flag first
This is where most CLAUDE.md files underinvest. Claude already knows how JavaScript works. It doesn't know that your project uses pnpm instead of npm, or that the test suite takes 3 minutes and shouldn't be run on every file change, or that the src/legacy/ directory is untouched by convention. Explicit project context eliminates a category of corrections that would otherwise happen constantly.
This is where preferences live — things you care about that aren't hard constraints. Format, style, how to handle ambiguity, when to ask vs. proceed. Keep each item specific and behavioral. "Be concise" is not actionable. "Keep responses under 5 sentences unless the question requires a longer answer" is.
The most common structural mistake in a CLAUDE.md is treating everything as equally important. When every instruction carries the same weight, none of them do. The model has to guess what you actually care about — and it will guess wrong in the cases where it matters most.
The distinction is simple: an iron law is a constraint that must never be overridden, regardless of context or user request. A preference is a behavioral default that can flex when there's a good reason.
Iron laws go in a dedicated section with a header that signals their status — ## Iron Laws or ## CRITICAL. Each one follows the same pattern:
NEVER [specific behavior] — instead [recovery path]
The recovery path is what separates a functional iron law from a dead end. "NEVER delete production data" leaves the agent stuck when it encounters a case where data needs to be removed. "NEVER delete production data without an explicit confirmed backup — instead show the backup status and ask for confirmation" gives it a path that satisfies the constraint without refusing to work.
How many iron laws do you need? The working range is 3 to 7. Fewer than 3 means important failure modes probably aren't covered. More than 10 means you're including preferences and aspirations alongside real constraints — which dilutes the signal and makes the actual hard limits less prominent.
To find your real iron laws: run Claude on the highest-stakes version of each task it handles and note the worst possible output. Each genuine catastrophe becomes an iron law. If you haven't stress-tested it, you don't yet know what the iron laws should be.
Claude's default behavior is conservative — it asks before writing files, confirms before running commands, and hedges on anything that feels consequential. That's the right default for interactive use. It's the wrong default for agents that run unattended: CI pipelines, scheduled tasks, automated code reviewers.
The Permissions section in your CLAUDE.md is where you explicitly expand or restrict what Claude will do without prompting. The pattern is two-sided: grant explicit permission for the common safe case, require explicit confirmation for the uncommon dangerous case.
## Permissions
# What the agent can do without asking:
- You MAY read any file in the repository
- You MAY run the test suite and linter
- You MAY create new files in src/ and tests/
- You MAY open draft PRs to the main branch
# What always requires confirmation:
- You MUST ask before deleting any file
- You MUST ask before modifying .env files or secrets
- You MUST ask before running any command that modifies
state outside this repository
- You MUST ask before pushing to a protected branch
The asymmetry matters: without the permission grants, Claude will interrupt the workflow with confirmations on every routine action. Without the explicit "must ask" cases, it may proceed on something destructive that you expected it to confirm first.
Agents running without a human in the loop need stricter defaults for anything irreversible. A human reviewer can catch a bad file write before it's committed. A headless agent cannot. For headless contexts, add a dedicated section:
## Headless Mode
This agent runs in automated pipelines without human review.
- NEVER perform any action that cannot be undone without
explicit confirmation via a config flag
- On any unexpected state (missing files, failing tests,
ambiguous instructions), STOP and write a status report
to /workspace/agent-status.md rather than guessing
The "stop and write a status report" pattern is more useful than a refusal. The agent produces a record of what it found and why it stopped, which a human can review and resolve. A bare refusal with no output gives you nothing to work with.
Claude doesn't retain memory between sessions by default. Everything learned in one session is gone when the next one starts. For a coding agent, this means re-explaining project context constantly — unless you design around it.
CLAUDE.md is for stable instructions: conventions, iron laws, permission modes, and project context that changes rarely. Don't use it as a session log or accumulate running notes inside it. It will grow unwieldy and the early content — your actual instructions — will get compressed out of effective context.
A separate memory file is for dynamic facts: ongoing work status, decisions made in previous sessions, preferences learned over time, open questions. The pattern that works:
## Memory
- Persistent notes live in /docs/agent-notes.md
- Check that file at the start of every session
- Add to it when you: make a non-obvious architectural
decision, learn a user preference, complete a major task,
or encounter a problem worth flagging for the next session
- Keep it under 200 lines — summarize older entries rather
than appending indefinitely
The size limit is not cosmetic. Memory files that grow without bound become noise that dilutes the signal. A 500-line memory file takes meaningful context budget and most of it won't be relevant to the current session. The instruction to summarize older entries keeps the file useful as it ages.
Facts that change slowly and matter repeatedly: the reason a particular architectural decision was made, a preference the developer expressed, the current state of in-progress work, known issues to avoid re-investigating. Not: full conversation transcripts, temporary debugging notes, or facts the agent can look up in seconds. The test: would knowing this at the start of a fresh session meaningfully change what the agent does?
If you're starting from scratch or want to rebuild an existing file, the CLAUDE.md Writer on helloandy.net generates a complete, structured CLAUDE.md from a short description of your project and agent. It handles the section structure, permission patterns, and iron law format — you provide the specifics for your project.
If you have an existing CLAUDE.md and want to know where it's weak, the CLAUDE.md Auditor scores it across eight dimensions: trigger clarity, permission specificity, iron law quality, memory structure, section organization, behavioral precision, recovery path coverage, and headless safety. It tells you exactly which sections to fix rather than giving you a generic quality score.
Generate a complete CLAUDE.md for your project, or audit the one you have.
CLAUDE.md Generator → Audit Existing CLAUDE.md