How to write CLAUDE.md: the three levels (user, project, directory) and a ready-to-use template

Claude Code Published:

Where Claude Code looks for CLAUDE.md, which level wins, what belongs in it and what does not, plus a template you can drop into a small or medium web project today.

Verified on Sep 7, 2026 These tools change quickly. Please also check the latest official documentation. How articles are researched and verified
Contents
  1. The three levels
  2. Generate the first draft with /init
  3. What to write
    1. Frequently used commands
    2. Conventions to follow
    3. Places not to touch
    4. How to work
  4. What not to write
  5. Template for a small or medium web project
  6. Grow it during sessions
  7. Summary

If you keep repeating the same instructions to Claude Code, or the coding conventions you asked for are ignored again, the fix is usually a better CLAUDE.md.

CLAUDE.md is a Markdown file Claude Code loads automatically at the start of every session. This article sorts out what to put where across three levels, and gives you a template to start from.

KEY POINT

What you will learn

  • The places CLAUDE.md can live and when each is loaded
  • What is worth writing and what has little effect
  • A template for small and medium web projects

The three levels

LevelPathPurposeIn Git
User~/.claude/CLAUDE.mdPreferences shared by all your projects (language, tone, frequent commands)No
Project./CLAUDE.md or ./.claude/CLAUDE.mdTeam conventions, build steps, structureYes
Personal (per project)./CLAUDE.local.mdYour own notes and local environment detailsNo (add to .gitignore)

There is a fourth option: a CLAUDE.md inside a subdirectory. A file at packages/api/CLAUDE.md is loaded when Claude touches files in that directory. In a monorepo, put the overall policy at the root and package-specific rules in each package.

Run /memory to see which files are loaded. When you are not sure why an instruction is or is not in effect, look there first.

Generate the first draft with /init

Run /init at the repository root and Claude inspects the project and writes a draft. Do not keep it as is. Cut:

  • Anything you can learn from the README (a long description of the project's purpose)
  • Anything Claude can discover by looking (directory listings)

Keep only the agreements you cannot see by reading the code.

用語解説

Import syntax: A line such as @docs/coding-style.md pulls that file into CLAUDE.md. Use it to keep long conventions in separate files.

What to write

Frequently used commands

Prevents Claude from guessing and running the wrong command.

## Commands
- Tests: `npm test` (unit) / `npm run test:e2e` (E2E, needs Docker running)
- Lint: `npm run lint` — must pass before committing
- Build: `npm run build`
- DB migrations: `npm run db:migrate`

Conventions to follow

A short "why" helps Claude act in the spirit of the rule when it hits a case you did not anticipate.

## Conventions
- Every new function gets a JSDoc comment (API docs are generated from types)
- Never use `any`; use `unknown` and narrow it
- Dates go through `date-fns`; do not add `moment` (bundle size)

Places not to touch

## Do not modify
- `src/generated/` (generated code; edit `schema/` instead)
- Existing files under `migrations/` (add new files instead)

How to work

## Workflow
- For changes touching 3+ files, outline the plan as bullet points before editing
- Never report "done" while tests are failing
- One logical change per commit

What not to write

ContentWhy
Directory trees or file listingsClaude explores on its own; the list goes stale and becomes wrong
Generic best practices ("write readable code")Vague instructions do not change behavior
Secrets, internal URLs, credentialsCLAUDE.md is committed. Do not put secrets in CLAUDE.local.md either; use environment variables
Huge specificationsThey cost context every session. Import only the parts you need with @

CLAUDE.md costs context on every session

The whole file is sent at the start of each session. Keeping a project CLAUDE.md around 100–200 lines balances the strength of the instructions against token usage. See Managing context in Claude Code.

Template for a small or medium web project

# Project overview
Next.js + TypeScript admin dashboard. API lives in `apps/api` (NestJS).

## Commands
- Dev server: `pnpm dev`
- Tests: `pnpm test` (always run the tests related to files you changed)
- Lint / format: `pnpm lint && pnpm format`
- Type check: `pnpm typecheck`

## Conventions
- Function components + hooks only; no class components
- Styling with Tailwind. CSS Modules exist only for legacy code
- API response types live in `packages/types` and are shared by front and back end
- Do not swallow errors; throw `AppError`

## Do not modify
- `packages/types/generated/` (generated from OpenAPI)
- `.github/workflows/` (propose changes instead)

## Workflow
- Read the related tests before changing code
- For changes touching 3+ files, present the plan first
- Include the test command you ran and its result in the completion report

## References
@docs/architecture.md

Grow it during sessions

Type a line beginning with # during a conversation and Claude offers to save it to CLAUDE.md. Telling Claude "from now on, do X" out loud does not survive to the next session; anything you find yourself repeating should be written down with #, and the file grows naturally.

For sharing the same content with Codex's AGENTS.md and Gemini CLI's GEMINI.md, see the Japanese article on context-file sharing; an English version will follow.

Summary

  • Place CLAUDE.md at the user, project and personal levels and check what is loaded with /memory
  • Write only agreements you cannot see in the code: commands, conventions, no-go areas and workflow
  • Leave out directory trees and generic advice; import long documents with @
  • Add to it during sessions with #

FAQ

Where should CLAUDE.md go?
Rules for all your projects go in ~/.claude/CLAUDE.md, shared project rules in CLAUDE.md at the repository root, and personal notes in CLAUDE.local.md.
What if CLAUDE.md gets too long?
Split it with the import syntax, for example @docs/architecture.md. A CLAUDE.md placed in a subdirectory is only loaded when Claude works in that directory.
Is CLAUDE.md the same thing as .cursorrules or AGENTS.md?
They play the same role of briefing the agent, but each product reads its own file. A separate article covers how to share content between them.

Questions & answers

Q. CLAUDE.md is injected into the system prompt at session start, so why is it not applied before the first answer?

Answer by the editorsSource: GitHub anthropics/claude-code Issue #98533

The premise doesn't match the documentation: CLAUDE.md is not in the system prompt. The memory documentation states it directly:

CLAUDE.md content is delivered as a user message after the system prompt, not as part of the system prompt itself. Claude reads it and tries to follow it, but there's no guarantee of strict compliance, especially for vague or conflicting instructions.

So the expectation that it must be applied because it is in the system prompt doesn't hold. You can confirm the file loaded by running /context and checking the list under Memory files — if it is listed, Claude can see it.

For better adherence, the docs name three things:

  • Make instructions concrete enough to verify. "Use 2-space indentation" rather than "format code properly"
  • Look for conflicting instructions across your CLAUDE.md files, nested CLAUDE.md files in subdirectories, and .claude/rules/. When two rules contradict each other, Claude may pick one arbitrarily
  • Keep each file under 200 lines. Longer files consume more context and reduce adherence, per the docs

For an instruction that must run at a specific point — before every commit, after each file edit — write it as a hook instead of prose. Hooks execute as shell commands at fixed lifecycle events and apply regardless of what Claude decides to do.

If you want instructions at the system prompt level, pass --append-system-prompt at launch. It is better suited to scripts and automation than to interactive use.

Q. My CLAUDE.md lists 11 mandatory project rules, but they are ignored across sessions. Can CLAUDE.md rules be enforced?

Answer by the editorsSource: GitHub anthropics/claude-code Issue #97999

CLAUDE.md shapes what Claude tries to do. It is not the mechanism that decides what is allowed. The official permissions documentation states this directly:

Permission rules are enforced by Claude Code, not by the model. Instructions in your prompt or CLAUDE.md shape what Claude tries to do, but they don't change what Claude Code allows.

So a rule like "nothing executes without an explicit go-ahead in this session" is not guaranteed by writing it in CLAUDE.md. The file is loaded, but following it is left to the model's judgement. The same page names the four things that do enforce: /permissions, permission rules, a permission mode, and a PreToolUse hook.

For anything you genuinely need blocked, write it in permissions in settings.json. Rules are evaluated deny → ask → allow, and the first match in that order determines the outcome. Specificity does not change the order, so a broad deny beats a narrower allow.

{
  "permissions": {
    "ask": [
      "Bash",
      "Edit"
    ],
    "deny": [
      "Bash(rm -rf *)"
    ]
  }
}

For conditions that rules cannot express, use a PreToolUse hook. Per the docs, PreToolUse hooks run before the permission prompt on every tool call, and their output can deny the call, force a prompt, or skip the prompt. A hook that exits with code 2 stops the call before permission rules are even evaluated.

Hook decisions do not bypass permission rules, though: deny and ask rules are evaluated regardless of what the hook returns, so a matching deny still blocks the call and a matching ask still prompts even when the hook returned "allow".

On the cross-session part: CLAUDE.md is loaded every session, but how the model treats a summary of earlier context is its own judgement. If that behavior has to be fixed, pin it with permissions or a hook rather than with prose.

For the full setup, see Configuring permissions in Claude Code's settings.json.

Primary sources

This article was drafted by AI from official documentation and reviewed by the site operator before publishing. Found a mistake? Let us know via the contact page.