← Back to articles
AI-generated image

Writing CLAUDE.md: stop explaining things every time

Where to put it, how to write it, how long it should be, and what to use when you need to enforce a rule.

Written by AI · 7 min · For people who have used Claude Code once
Claude CodeCLAUDE.mdMemory
What this article covers

CLAUDE.md is the premise you hand over at the start of every session. This covers where to put it, what to write, and what it cannot enforce.

Every session starts from a blank slate

Claude Code starts each session with a fresh context. What was said in the previous conversation isn’t carried over by itself. Two mechanisms carry knowledge into the next session.

Both are passed in as context, not as enforced settings. For things you want enforced, use the methods in a later section.

CLAUDE.mdAuto memory
Written byYouClaude itself
ContentsInstructions and rulesWhat it learned from your corrections and preferences
LoadedEvery sessionEvery session (up to the first 200 lines or 25KB)

Where to put it

Where you put it changes how far it reaches and who shares it. Files are loaded from the broadest scope to the most specific, so project instructions enter the context after user instructions.

The order CLAUDE.md files are loadedUserPreferences for every project~/.claude/CLAUDE.mdParent directoriesShared rules, e.g. a monorepo../CLAUDE.mdProjectConventions shared with your team./CLAUDE.mdLocalYour own notes (add to .gitignore)./CLAUDE.local.mdAll loaded at launch and concatenated top to bottom (not overridden)CLAUDE.md in a subdirectoryLoaded when Claude reads or writesa file in that directory
Figure 1. CLAUDE.md files in the working directory and above are concatenated at launch, broadest first. Those in subdirectories are loaded when needed.

Files in the working directory and its parent directories are all loaded at launch, and they are concatenated rather than overriding each other. A CLAUDE.md in a subdirectory is loaded when Claude reads or writes a file in that directory.

ScopeLocationShared with
User~/.claude/CLAUDE.mdOnly you (all projects)
Project./CLAUDE.md or ./.claude/CLAUDE.mdYour team (via source control)
Local./CLAUDE.local.mdOnly you (this project). Add it to .gitignore

Draft one with /init

You don’t have to write it from scratch. Run /init at the project root and Claude examines the codebase, then generates a CLAUDE.md from the build commands, test steps and conventions it finds. If a CLAUDE.md already exists, it suggests improvements instead of overwriting it. The result is a draft: always read it and fix anything that differs from your team’s rules.

Run inside Claude Code
/init

Write it so it can be checked

CLAUDE.md is passed in as context, so how you write it changes how well it is followed. Make instructions concrete enough to verify. Aim for under 200 lines per file; longer files use more context and are followed less reliably. If two instructions contradict each other, Claude may pick one arbitrarily, so remove stale instructions regularly.

  • Not “format code properly” but “use 2-space indentation”
  • Not “test your changes” but “run npm test before committing”
  • Not “keep files organized” but “API handlers live in src/api/handlers/”

Example: CLAUDE.md for a small project

Here is an example for an imaginary project. It uses only things that can be checked (commands, locations and prohibitions) as bullets under headings.

CLAUDE.md example
# Project basics

## Commands
- Tests: `npm test` (always run before committing)
- Type check: `npm run typecheck`

## Structure
- API handlers live in `src/api/handlers/`
- Shared types go in `src/types/`

## Conventions
- Use 2-space indentation
- Add tests for any new function in the same PR

## Don’t touch
- Don’t edit existing files in `migrations/` (add new ones only)

Splitting and sharing: @imports and .claude/rules/

Writing @path inside CLAUDE.md expands and loads that file at startup, for example “See @README for project overview and @package.json for available npm commands.” Imports help organize a long file, but they don’t reduce context use, because imported files are also loaded at startup. Instructions that matter only for some files go in .claude/rules/ as path-scoped rules, which are loaded only when Claude works with matching files.

.claude/rules/api.md example (the frontmatter paths field selects the target)
---
paths:
  - "src/api/**/*.ts"
---
In API handlers, always validate input before processing it.

Don’t rely on CLAUDE.md for what must be enforced

The contents of CLAUDE.md are instructions Claude tries to follow, not enforcement. Writing “don’t read .env,” for example, doesn’t by itself forbid reading it. For operations you must block reliably, use permission deny rules or a PreToolUse hook. Permission settings are covered in the next article.

Checking when it isn’t working

When instructions aren’t followed, first suspect that they aren’t loaded. Run /context and check whether the CLAUDE.md you expect appears in the Memory files list. A file that isn’t listed is invisible to Claude. Running /memory lists the locations of your CLAUDE.md and auto memory files and lets you edit them directly. If a file is too long, a warning appears at startup and in /status.

Run inside Claude Code
/context   # list the Memory files
/memory    # file locations, and the auto memory on/off switch

Official references

Claude Code — How Claude remembers your project ↗
PAIBOT / DEVELOPMENT JOURNALBack to articles →

Find what you need

Searches titles, tags and body text esc to close