CLAUDE.md: The Developer’s Persistent Instruction File for Claude Code

Claude.ai preferences shape how Claude behaves across chat sessions. CLAUDE.md does something different: it shapes how Claude Code behaves inside a specific project. The two are related in principle but distinct in practice, and conflating them causes confusion.

This article is about CLAUDE.md – what it is, how it works, and how to write one that actually holds Claude Code to a consistent standard across every session in your project.

What CLAUDE.md is

CLAUDE.md is a plain text file written in Markdown that you place at the root of a project directory. When Claude Code starts an agentic session in that directory, it reads the file automatically and treats its contents as standing instructions for the duration of the session.

It functions as a project-level system prompt. The distinction matters: Claude Code has no memory between sessions. Every time it opens a project, it starts from zero. CLAUDE.md is the mechanism that prevents that reset from erasing everything you have already established about how the project should be handled.

It is specific to Claude Code – the command-line agentic tool – not to Claude.ai chat sessions. If you are not using Claude Code, CLAUDE.md does not apply to you. The equivalent for Claude.ai chat is the preferences field in your profile settings.

What belongs in it

The file should contain instructions Claude Code will need to consult repeatedly throughout a project. Five categories cover most use cases.

Tech stack and environment. The language, framework, runtime, and any tooling Claude Code needs to know about before it touches a file. Stating this explicitly prevents Claude Code from making plausible but wrong assumptions – reaching for JavaScript when the project is TypeScript, or targeting the wrong Node version.

Standing rules. Instructions that apply to every task without exception. Run tests after every change. Keep commits small and scoped to a single concern. Never modify production configuration without an explicit instruction to do so. These are the rules you would otherwise type at the start of every session. Write them once in CLAUDE.md and stop repeating yourself.

Verification requirements. Claude Code will complete a task and hand it back. Without explicit verification rules, it will do so whether the output works or not. Telling it to lint, run tests, and check for console errors before considering a task done shifts the first line of quality control from you to the tool.

Scope constraints. Claude Code performs best inside tight boundaries. Giving it unlimited scope on a large task produces drift – additions you did not ask for, changes to files that were not in the brief, decisions made silently. The rule “one task at a time; if the scope is large, outline sub-tasks and confirm before starting” is worth including in every CLAUDE.md.

A bug log. Claude Code has no memory between sessions. A bug it introduced last Tuesday and you fixed together is a bug it is fully capable of introducing again today, because it has no record of the previous occurrence. Adding a running log of confirmed bugs – root cause, fix applied, pattern to avoid – gives Claude Code the institutional memory it would otherwise lack entirely.

What does not belong in it

CLAUDE.md is not a place to put all project documentation. Signal density matters: the more noise you add, the less reliably Claude Code attends to the instructions that actually matter. A working CLAUDE.md is usually under 300 lines. If yours is longer, it is probably carrying content that belongs in a separate reference file or in inline comments.

Do not include information that changes frequently. CLAUDE.md is a standing instruction document, not a changelog or a task list. Mixing stable rules with volatile information dilutes both.

File placement and scope

The primary CLAUDE.md sits at the project root. Claude Code also supports nested CLAUDE.md files in subdirectories, which apply only when Claude Code is operating within that subdirectory. This is useful for monorepos or projects where different modules operate under different conventions – a backend directory might carry different rules than a frontend one.

Instructions in a subdirectory CLAUDE.md layer on top of the root file rather than replacing it. The root rules remain active; the subdirectory rules extend or override them for work in that scope.

A minimal starting structure

Most projects can start with something close to this:

# Project: [Name]

## Stack
- Language: TypeScript
- Runtime: Node 20
- Framework: [your framework]
- Test runner: Jest

## Rules
- Run tests after every feature change
- Commit in small, single-concern units
- Do not modify .env files without explicit instruction
- One task per request; outline sub-tasks for large requests before starting

## Verification before handback
- [ ] Lint passes
- [ ] All tests pass
- [ ] No console errors

## Bug Log
[Add entries here as issues are identified and resolved]

This is enough to give Claude Code a working brief for most projects. Extend it as your project’s specific patterns and constraints become clear.

The relationship to Claude.ai preferences

Claude.ai preferences and CLAUDE.md address the same underlying problem – Claude has no persistent memory – but at different levels. Preferences operate at the user level across all chat sessions. CLAUDE.md operates at the project level within Claude Code agentic sessions.

If you use both Claude.ai for general work and Claude Code for development, both are worth configuring. They do not overlap and they do not conflict. Each handles the context problem in its own domain.

The pattern is consistent across both: write the instructions once, in the right place, with enough specificity to be unambiguous. The tool reads them. You stop repeating yourself. The output improves from the first message of every session.

Discover more from fastai.news

Subscribe now to keep reading and get access to the full archive.

Continue reading