CLAUDE.md: templates and the project context Claude Code actually uses

How Claude Code loads CLAUDE.md, a template for a Next.js project, what belongs in it, and how to point it at the plan instead of copying the plan into it.

Last reviewed 2026-08-27 · View as Markdown

What the file is, and what reads it

Every Claude Code session starts with a fresh context window. CLAUDE.md is what survives the reset — "instructions you write to give Claude persistent context", loaded at the start of every conversation. Its sibling is auto memory: notes Claude writes for itself under ~/.claude/projects/<project>/memory/, which the documentation calls "learnings and patterns" rather than rules.

Both are context, not configuration: "To block an action regardless of what Claude decides, use a PreToolUse hook instead." A line saying "never push to main" is a strong suggestion; a hook is a rule. Write the file knowing which of the two you needed.

Where a Claude Code memory file can live

These files are the Claude Code project context: what the model knows about the repository before you type a word. They live in four places, listed here in load order from broadest scope to most specific, so a project instruction appears in context after a user instruction.

ScopeLocationWhat belongs there
Managed policymacOS /Library/Application Support/ClaudeCode/CLAUDE.md; Linux and WSL /etc/claude-code/CLAUDE.md; Windows C:\Program Files\ClaudeCode\CLAUDE.mdOrganisation-wide standards. Cannot be excluded by individual settings
User~/.claude/CLAUDE.mdYour preferences, across every project on the machine
Project./CLAUDE.md or ./.claude/CLAUDE.mdCommands, layout, conventions. Committed, so the team shares it
Local./CLAUDE.local.mdYour own notes for this repository. Add it to .gitignore

Project instructions for Claude Code go in the third row, and that is the file most of this guide is about. A preference nobody else voted for belongs in the second, not in a file the whole team pays for on every session.

How the files are found

Claude Code loads CLAUDE.md and CLAUDE.local.md from the working directory and every directory above it. Discovered files are concatenated rather than overriding each other, ordered from the filesystem root down, so the file closest to where you launched is read last, and CLAUDE.local.md is appended after CLAUDE.md at each level. Files in subdirectories below the working directory are not loaded at launch; they are included when Claude reads files there.

Two commands settle any argument about what loaded. /context lists the loaded files under Memory files; if one is not there, Claude cannot see it. /memory lists the locations across user and project scope, including files that do not exist yet, and opens the one you pick in your editor.

Imports, and what they do not solve

A CLAUDE.md pulls in other files with @path/to/import. Relative paths resolve against the file containing the import, not the working directory; imports nest to a maximum depth of four hops; parsing skips code spans and fenced blocks, so `@README` in backticks mentions a path without importing it.

See @README for the project overview and @package.json for the scripts.
Git workflow: @docs/git-instructions.md

The caveat is in the documentation itself: imported files "load at launch", so splitting a long file into imports "helps organization but doesn't reduce context". If the file is too big, imports will not save you.

An import in a project file whose path resolves outside the working directory triggers a one-time approval dialog, because someone else may have committed it; imports in your own user-scope files are trusted. Such a home-directory import is also the documented way to share personal instructions across git worktrees, where a gitignored CLAUDE.local.md exists only in the worktree that created it.

Generating one with /init, then cutting it back

/init analyses the codebase and writes a starting file; if one already exists it "suggests improvements rather than overwriting it". It reads Cursor rules from .cursor/rules/ or .cursorrules and Copilot rules from .github/copilot-instructions.md on the way. With CLAUDE_CODE_NEW_INIT=1 it explores with a subagent and shows a reviewable proposal before writing anything, and also reads AGENTS.md, .windsurf/rules/, .windsurfrules and .clinerules.

Generated files are always too long, because the generator writes down what it just discovered. Delete every line Claude could rediscover by reading the repository. /doctor proposes that trim for a checked-in file: it cuts directory layouts, dependency lists and architecture overviews, and keeps pitfalls, rationale and conventions that differ from tool defaults.

What to put in CLAUDE.md

The test for a line is whether it is a fact Claude should hold in every session and cannot derive from the code. Add to the file when Claude makes the same mistake a second time, when you type a correction you also typed last session, or when a new teammate would need the same context.

SectionBelongsDoes not belong
CommandsInstall, dev, test, lint, typecheck, and the order to run them before a commitEvery script in package.json
LayoutWhere things live when the path does not say so; what is generatedA full directory tree, wrong by the next branch
ConventionsChoices a linter cannot enforce: naming, error handling, how a migration is addedThe style guide; that is the linter's job
GotchasWhat bit the last three people, with a date next to itAnything discoverable in a minute
Where the plan livesHow to reach the backlogThe backlog itself

Two sizing rules come from the documentation: target under 200 lines, because "longer files consume more context and reduce adherence", and a file over 4 MiB is skipped entirely. Contradictions are worse than omissions — when two rules conflict, "Claude may pick one arbitrarily".

When instructions genuinely are large, the answer is not imports but .claude/rules/: one Markdown file per topic, with a paths frontmatter field — paths: ["src/app/api/**/*.ts"] — that loads a rule only when Claude works with matching files. Rules without paths load at launch with the same priority as .claude/CLAUDE.md; personal ones in ~/.claude/rules/ load first.

A CLAUDE.md example for a Next.js project

A complete CLAUDE.md for Next.js work — App Router, TypeScript, Prisma, pnpm. Every line is a command, a convention a linter cannot enforce, or something that bit somebody; none of it repeats what the agent reads off the directory tree, which is the content /doctor cuts. The last section points at the plan rather than containing it. The specifics are yours to change; the shape is the reusable part.

# CLAUDE.md

Next.js 16 App Router, TypeScript, Prisma, pnpm workspaces.

## Commands

pnpm install                # Node 22; run `corepack enable` if pnpm is missing
pnpm dev
pnpm build                  # must pass before a commit — `next dev` hides type errors
pnpm test                   # vitest; add a path to run one file
pnpm lint && pnpm typecheck # CI runs exactly these two

Database work needs `docker compose up -d db` and `pnpm prisma migrate dev` once.

## Layout

- `src/lib` — server-side helpers, no React imports. Importing React there is
  the mistake that turns a server helper into a client bundle.
- `prisma/schema.prisma` — run `pnpm prisma generate` after editing it. The
  generated client is not committed.

## Conventions

- `'use client'` goes on the leaf component that needs state or an event handler,
  never on a page or a layout.
- Route handlers return `Response.json(...)`. Error shape is `{ error: string }`.
- A schema change is a migration plus a `schema.prisma` edit in one commit. Never
  edit a migration that has been applied.

## Gotchas

- `params` in a page or route handler is a Promise and must be awaited. Examples
  written against Next 14 will look right and fail to build. (2026-08)
- `src/lib/db.ts` is imported by middleware; a Node-only dependency added to it
  breaks the build with an unhelpful edge-runtime error. (2026-07)

## Where the plan lives

Work is tracked in Autoplans, not in this file and not in a TODO.md. The project id
is in `.autoplans/project.json` — read it and call `list_tasks` with that id rather
than listing every project. Move a finished task to `waiting_for_review`, not
`completed`, unless you ran the tests yourself.

The minimal version

A new repository needs none of that. Start here and let the file earn its length one correction at a time:

# CLAUDE.md

pnpm dev / pnpm test / pnpm lint. All three must pass before a commit.

- Source in `src/`, tests beside the file they cover as `*.test.ts`.
- Server Components by default; `'use client'` only where state is needed.
- Tasks live in Autoplans; the project id is in `.autoplans/project.json`.

Five lines that are true beat fifty that were true in June. Both CLAUDE.md templates follow one rule: commands first, then only what surprised somebody.

CLAUDE.md vs AGENTS.md

AGENTS.md is the cross-tool version of the same idea — agents.md calls it "a dedicated, predictable place to provide the context and instructions to help AI coding agents work on your project", with no schema: "just standard Markdown. Use any headings you like." The asymmetry is the whole story, checked against each tool's current documentation:

ToolReadsFalls back to CLAUDE.md
Claude CodeCLAUDE.md, ./.claude/CLAUDE.md, CLAUDE.local.mdIt is the primary name; AGENTS.md is not read
OpenCodeAGENTS.mdYes — "used if no AGENTS.md exists"
CodexAGENTS.override.md, then AGENTS.md, root downNo, unless you add it to project_doc_fallback_filenames

Claude Code's documentation states it plainly: "Claude Code reads CLAUDE.md, not AGENTS.md." A repository carrying only the plural file gives Claude Code nothing. Do not maintain two copies; make one import the other. This site's own repository does that — packages/web/CLAUDE.md is a single line, @AGENTS.md — and anything Claude-specific would go below the import:

@AGENTS.md

## Claude Code

Use plan mode for changes under `src/app/api/`.

A symlink, ln -s AGENTS.md CLAUDE.md, does the same job when there is nothing to add, but on Windows it needs Administrator privileges or Developer Mode, so the import is the portable choice. /import appends a one-time copy of another agent's configuration instead — useful during a migration, not a way to keep two files in step. The longer argument for one file over two is in CLAUDE.md, AGENTS.md and context rot; the tool-by-tool detail is in the AGENTS.md guide.

Point the file at the plan instead of pasting the plan into it

The section that rots fastest is a task list, a "current sprint" or a roadmap pasted into CLAUDE.md because that is what the agent reads. It is accurate on the day it is written; a week later the agent follows it with exactly the confidence it had on day one, which is the failure described in preventing AI context rot. The fix is a pointer: CLAUDE.md holds the durable half, how to reach the plan, and the plan lives where it can change without a commit.

In a repository linked to Autoplans the pointer is one file. .autoplans/project.json carries the project id, travels with the repository, and is read by every Autoplans surface, so "which project is this?" has one answer per repository rather than one per tool:

// .autoplans/project.json
{
  "projectId": "1fb3fe7d-e3f9-4992-ae18-29b2bade4bd4",
  "name": "My project",
  "url": "https://autoplans.dev/dashboard/projects/1fb3fe7d-...",
  "linkedAt": "2026-08-26T10:00:00.000Z"
}

Commit that, add the "Where the plan lives" section from the template above, and the backlog reaches the session through tools rather than prose. The Claude Code plugin supplies them: add the marketplace, run /plugin install autoplans, and paste an Autoplans API key when Claude Code prompts for one. The session then has list_tasks, create_task, update_task and the rest of the MCP tools, plus /plan, /start, /tasks and /finish as slash commands and an autoplans skill. A command's body loads when you run it, so the procedure is not sitting in every session's context the way a CLAUDE.md paragraph is.

None of this requires Autoplans. GitHub issues with an agreed "ready" label work, as long as the agent has a tool that can read them; so does any tracker behind an MCP server. What matters is that the instruction file names the source of truth and never becomes it. Why a coding agent needs a backlog, not a prompt makes the longer case; Projects covers linking a folder.

CLAUDE.md best practices, in one list

  • Keep it under 200 lines; adherence drops as the file grows, and a file over 4 MiB is skipped.
  • Commands first, and every one must run as written.
  • Be specific enough to verify. "Use 2-space indentation", not "format code nicely".
  • Date the gotchas. A warning with a date is easy to retire; one without lives forever.
  • Preferences go in ~/.claude/CLAUDE.md, machine-specific notes in a gitignored CLAUDE.local.md.
  • Move procedures to skills, path-specific instructions to .claude/rules/. If you would resent reading a section aloud every session, it does not belong here.
  • Import AGENTS.md rather than duplicating it, and never paste the backlog in.
  • Run /context after a change to confirm the file loaded.

Give the agent a plan it can read.

Describe a project, get a backlog, connect it over MCP. Free, no card.

Start free