Deep dive12 min read

The CLAUDE.md Memory System - Deep Dive

SFEIR Instituteβ€’

TL;DR

The CLAUDE.md file is Claude Code's persistent memory, automatically loaded into the context window at each session. Mastering its hierarchy (project, user, auto-memory) and its modular rules allows you to configure a consistent and productive development agent from one session to the next.

The CLAUDE.md file is Claude Code's persistent memory, automatically loaded into the context window at each session. Mastering its hierarchy (project, user, auto-memory) and its modular rules allows you to configure a consistent and productive development agent from one session to the next.

CLAUDE.md is a Markdown configuration memory file that Claude Code automatically loads at the start of each session to customize its behavior, conventions, and persistent instructions. This mechanism is the primary lever for personalizing the agent. Most teams that use Claude Code seriously rely on at least one CLAUDE.md file in their projects.

SFEIR Institute trainings

Claude Code Training

1 day Β· Fundamentals

View program

AI-Augmented Developer

2 days Β· Intermediate

View program

What is CLAUDE.md and why is this file essential?

CLAUDE.md is a Markdown file placed at the root of a project or in the user directory ~/.claude/. Claude Code detects it and loads it into the context window (delivered as a user message after the system prompt) before any interaction. This mechanism transforms the agent into a contextualized assistant.

Without CLAUDE.md, each new session starts from scratch. You lose team conventions, critical file paths, and workflow preferences. With a well-written CLAUDE.md, Claude Code applies your rules from the very first command.

In practice, a concise CLAUDE.md noticeably reduces the manual corrections you have to repeat across sessions on a large TypeScript project. The file acts as a contract between you and the agent, ensuring consistency of the produced code.

To understand how Claude Code works as an autonomous agent, check the article What is agentic coding? which lays the conceptual foundations.

AspectWithout CLAUDE.mdWith CLAUDE.md
Code conventionsRe-explained each sessionApplied automatically
Critical pathsRediscovered by explorationKnown at startup
Initial context timeSlower (rediscovered)Fast (known at startup)
Cross-session consistencyLowHigh

Key takeaway: CLAUDE.md is the memory configuration file that persists your instructions between Claude Code sessions.

How does the memory hierarchy work in Claude Code?

Claude Code implements a three-level hierarchy of memory files. Each level has a different scope and priority. Understand this architecture to structure your instructions in the right place.

Level 1: Project CLAUDE.md (repository root)

This file can live either at the root of your Git repository (./CLAUDE.md) or under ./.claude/CLAUDE.md. It is shared with the entire team via version control. Place here code conventions, project architecture, and build commands. For completeness, the hierarchy also supports a managed-policy CLAUDE.md set by your organization and a local CLAUDE.local.md for personal, unversioned project notes.

# CLAUDE.md (project root)
- Framework: Next.js 15 with App Router
- Tests: Vitest, run with `npm run test`
- Style: Prettier + ESLint, 2-space tabs
- Never modify files in /generated/

Level 2: User CLAUDE.md (~/.claude/CLAUDE.md)

This file is specific to your machine. It is not versioned. Configure here your personal preferences: response language, commit style, preferred tools.

# ~/.claude/CLAUDE.md
- Respond in English
- Use bun instead of npm
- Always suggest unit tests

Level 3: Auto Memory (~/.claude/projects/.../memory/)

Claude Code creates and maintains this directory automatically. It stores patterns discovered over the course of sessions. This level is detailed in a dedicated section below.

For a complete view of context management and its impact on memory, explore the context management deep dive.

LevelFileScopeVersionedSpecificity
1./CLAUDE.md or ./.claude/CLAUDE.mdProject (team)YesMost specific
2~/.claude/CLAUDE.mdUserNoBroader
3~/.claude/projects/.../memory/Project + userNoAuto-generated context

All of these files (project CLAUDE.md, user CLAUDE.md, and auto-memory) are loaded as context rather than enforced configuration. When instructions conflict, Claude Code resolves them non-deterministically rather than applying a strict precedence between levels.

Key takeaway: three memory levels coexist (project, user, and auto-memory), all concatenated into context, with conflicts resolved non-deterministically rather than by a fixed precedence.

How to write an effective CLAUDE.md?

A performant CLAUDE.md follows precise principles. concise files achieve a better rule application rate. Keep your CLAUDE.md concise: an overly long file wastes context unnecessarily.

Structure by thematic sections

Organize your file into clear blocks with Markdown headings. Claude Code reads the file sequentially and assigns more weight to the first lines.

# Architecture
- pnpm monorepo with 3 packages: api, web, shared
- Database: PostgreSQL 16 via Prisma 5.x

# Conventions
- Component names in PascalCase
- Custom hooks prefixed with use
- No `any` in TypeScript

# Commands
- Build: `pnpm build`
- Tests: `pnpm test --run`
- Lint: `pnpm lint`

Be directive, not descriptive

Write imperative instructions. Replace "The project uses TypeScript" with "Use TypeScript strict for all new files". Claude Code treats imperatives as rules, descriptions as optional context.

Imperative, concrete instructions are followed more consistently than descriptive prose, though Claude Code never guarantees strict compliance.

Specify prohibitions

Negative rules are as powerful as positive ones. List explicitly what Claude Code must not do.

# Prohibitions
- NEVER modify files in /migrations/
- Do not use moment.js (use date-fns)
- Do not create .env files with real values

To further optimize your file, the CLAUDE.md memory system optimization guide provides advanced structuring techniques.

Key takeaway: a short, imperative, and section-structured CLAUDE.md maximizes the rule application rate.

What are the benefits of modular rules.claude/rules/?

The .claude/rules/ directory lets you split your instructions into thematic files. Each .md file in this folder is loaded as an additional CLAUDE.md. This approach solves the problem of CLAUDE.md becoming too long.

Directory architecture

.claude/
β”œβ”€β”€ rules/
β”‚ β”œβ”€β”€ testing.md # Testing rules
β”‚ β”œβ”€β”€ api-conventions.md # API REST conventions
β”‚ β”œβ”€β”€ security.md # Security rules
β”‚ └── git-workflow.md # Git workflow
β”œβ”€β”€ CLAUDE.md # Global user file
└── projects/
 └── <hash>/
 └── memory/
 └── MEMORY.md # Auto-memory

Create one file per domain. Splitting rules into focused per-topic files tends to improve adherence and is easier to maintain than one long CLAUDE.md.

Conditional loading

Files in .claude/rules/ support YAML frontmatter for conditional, path-scoped loading:

---
paths: ["**/*.test.ts"]
---
# Testing Rules
- Use describe/it, not test()
- Mock external dependencies with vi.mock
- Each test should have a single assert

This file only loads when Claude Code is working on *.test.ts files. You thereby reduce noise in the system prompt and gain tokens for useful context.

To understand how these rules interact with the Git workflow, check the Git integration best practices.

ApproachMax Recommended LinesMaintainability
Single CLAUDE.md200Medium
Modular rules50 per fileHigh
Mixed (CLAUDE.md + rules/)100 + 5x30High

Key takeaway: modular rules in .claude/rules/ offer a better application rate and simplified maintenance compared to a monolithic file.

How does Auto Memory work with MEMORY.md?

Auto-memory is a mechanism through which Claude Code creates and automatically updates files in ~/.claude/projects//memory/, where is a project-derived directory name based on your git repository (or the project root when outside git). The main file is MEMORY.md, loaded into the context window at the start of each session (the first 200 lines or first 25KB, whichever comes first).

Writing mechanism

Claude Code writes to MEMORY.md when it detects a recurring pattern or a correction you apply multiple times. The process follows these steps:

  1. You correct a Claude Code behavior
  2. The agent identifies an implicit rule
  3. It checks whether MEMORY.md already contains this information
  4. If not, it adds a concise entry
# MEMORY.md (automatically generated)
- The project uses bun, not npm
- E2E tests are in /tests/e2e/ and use Playwright
- Always run `bun run typecheck` before committing

Size limit

Only the first 200 lines of MEMORY.md, or the first 25KB (whichever comes first), are loaded at the start of every session; the rest is not loaded. Regularly check the size of your file with:

wc -l ~/.claude/projects/*/memory/MEMORY.md

A 200-line MEMORY.md consumes only a small fraction of Claude's available context window.

Complementary thematic files

In addition to MEMORY.md, you can create files like debugging.md or patterns.md in the same directory. Reference them from MEMORY.md so Claude Code consults them as needed.

To get started properly with Claude Code and configure your memory environment from installation, follow the installation and first launch guide.

Key takeaway: the auto-memory MEMORY.md is generated by Claude Code itself, loaded into context (only the first 200 lines or first 25KB, whichever comes first), and complements manual CLAUDE.md files without replacing them.

When should you NOT use CLAUDE.md as a configuration solution?

CLAUDE.md is not the answer to all configuration needs. Here are the situations where other approaches are preferable.

Decision tree

  • If your rule concerns a single file type -> use .claude/rules/ with a paths: frontmatter
  • If your rule is a secret or API key -> use environment variables, never CLAUDE.md
  • If your rule changes every session -> pass it in the prompt directly, not in CLAUDE.md
  • If your rule exceeds 400 lines -> split into modular rules
  • If you work in a team and the rule is personal -> place it in ~/.claude/CLAUDE.md, not at the root

Known limitations

CLAUDE.md does not support complex conditional logic. You cannot write "if main branch, then...". Modular rules with paths: offer file-based filtering, but not by Git branch or environment variable.

An overly verbose CLAUDE.md degrades performance. A very long CLAUDE.md consumes meaningfully more of the context window and tends to reduce adherence. This budget reduces the space available for the source code that Claude Code analyzes.

To understand how context is managed and optimized beyond CLAUDE.md, the context management optimization guide provides complementary strategies.

NeedRecommended SolutionWhy Not CLAUDE.md
Secret / API keyEnvironment variableRisk of accidental commit
File-specific rule.claude/rules/ with paths:Pollutes the global prompt
One-time instructionDirect promptUnnecessary memory overload
Architecture documentationDedicated ADR fileCLAUDE.md is not a wiki

Key takeaway: reserve CLAUDE.md for persistent, cross-cutting, and non-sensitive instructions. Everything else has a better home.

How to structure memory for a multi-developer team project?

In a team context, Claude Code's memory configuration requires a shared strategy. Define a common root CLAUDE.md and let each developer customize their user file.

# Root CLAUDE.md (versioned)
## Architecture
- Nx monorepo with 4 apps: web, api, admin, mobile
- Node.js 22 LTS, TypeScript 5.7 strict

## Workflow
- Branches: feature/<ticket>, fix/<ticket>
- Conventional commits mandatory
- PR review required before merge

## Prohibited
- Do not use console.log in production (use the logger)
- Do not modify /packages/shared/ without review

Each developer adds their local preferences in ~/.claude/CLAUDE.md: language, personal tools, aliases. These files are never versioned.

A team sharing a well-structured root CLAUDE.md typically spends fewer review comments re-explaining code conventions.

To discover how these configurations integrate into your first interactions with Claude Code, read the guide on your first conversations.

SFEIR Institute offers the Claude Code one-day training that includes a hands-on CLAUDE.md configuration workshop on a real project. You will learn to structure your project memory and leave with a ready-to-use template.

Key takeaway: in a team, version a shared root CLAUDE.md and leave individual preferences in the user file.

What are the edge cases and subtle behaviors of the memory system?

Several Claude Code memory behaviors are not obviously documented. Anticipate these cases to avoid surprises.

Loading order

Claude Code concatenates the different memory files into context, from broadest to most specific:

  1. Managed-policy CLAUDE.md (if configured by your organization)
  2. ~/.claude/CLAUDE.md (global user)
  3. ./CLAUDE.md or ./.claude/CLAUDE.md (project root)
  4. .claude/rules/*.md (modular rules, loaded with the same priority as the project CLAUDE.md)
  5. ~/.claude/projects//memory/MEMORY.md (auto-memory)

These files are concatenated as context, not enforced configuration. When two instructions conflict, the resolution is not deterministic: Claude may pick one arbitrarily. There is no strict load-order rule by which auto-memory overrides a project CLAUDE.md. In practice, Claude Code avoids writing instructions in MEMORY.md that contradict an existing CLAUDE.md.

The documented load limit

This is documented behavior, not a silent surprise: only the first 200 lines or first 25KB of MEMORY.md (whichever comes first) are loaded into context, and anything beyond that is not loaded. There is no error to signal it, so a file that grows past the limit quietly stops contributing its later lines. Monitor the size with a pre-session hook or dedicated script:

#!/bin/bash
LINES=$(wc -l < ~/.claude/projects/*/memory/MEMORY.md)
if [ "$LINES" -gt 180 ]; then
 echo "Warning: MEMORY.md approaching limit: $LINES/200 lines"
fi

Encoding and special characters

CLAUDE.md must be encoded in UTF-8. Special characters in code blocks are correctly interpreted, so plain UTF-8 Markdown is the safest choice for your memory files.

The agentic coding deep dive explores other subtle Claude Code behaviors related to agent autonomy.

To learn more about the memory system's inner workings, also check the CLAUDE.md memory system FAQ which answers the most frequently asked questions.

Key takeaway: the loading order and the documented 200-line/25KB load limit of MEMORY.md are the two most common pitfalls to be aware of.

How to diagnose and debug a Claude Code memory issue?

When Claude Code does not follow an instruction from your CLAUDE.md, follow this structured diagnostic procedure.

Step 1: Verify loading

Run the /memory command in Claude Code to inspect and edit the currently loaded memory files. It lists the loaded CLAUDE.md, CLAUDE.local.md, and rules files, lets you open any of them in your editor, and lets you toggle auto memory.

$ claude
> /memory
# Lists the loaded CLAUDE.md / CLAUDE.local.md / rules files
# and lets you open them in an editor or toggle auto memory

Step 2: Look for conflicts

Compare your different memory files. A MEMORY.md that contains "use npm" while your project CLAUDE.md says "use bun" creates a conflict. Because all memory files are concatenated as context (not enforced configuration), Claude Code resolves such conflicts non-deterministically rather than by a fixed precedence, so the outdated entry may still be applied.

Step 3: Purge auto-memory if necessary

# Back up then reset MEMORY.md
cp ~/.claude/projects/*/memory/MEMORY.md ~/backup-memory.md
echo "" > ~/.claude/projects/*/memory/MEMORY.md

Diagnostic tree

  • Claude Code ignores a rule -> verify it is in a loaded file (not beyond line 200)
  • Claude Code applies an outdated rule -> search MEMORY.md for a contradictory entry
  • Claude Code mixes two projects -> check the project-derived directory name in ~/.claude/projects/

A common cause of memory problems is an outdated MEMORY.md entry that conflicts with a current project CLAUDE.md rule.

To deepen your understanding of the CLAUDE.md memory system as a whole, the reference article covers the fundamentals.

If you want to master these advanced mechanisms and learn to effectively debug your augmented development environment, SFEIR Institute offers the AI-Augmented Developer training over 2 days, with hands-on labs covering memory configuration, debugging, and advanced workflows. To go even further, the AI-Augmented Developer - Advanced one-day training deepens system prompt optimization strategies and multi-agent architectures.

Key takeaway: the /memory command is your first diagnostic reflex. It lets you edit the CLAUDE.md and manage auto-memory.


Recent articles about Claude

Claude Code Training

This topic is covered in Module 3 of our Claude Code training

Getting Started and Basic Interactions

1-day training β€’ 60% hands-on labs β€’ Expert instructors

View full program