$catMANUAL||~30 min

Claude Code Memory System Guide: CLAUDE.md, Auto Memory, and Rules in Practice

advertisement

Claude Code Memory System Guide: CLAUDE.md, Auto Memory, and Rules in Practice

Every time you open Claude Code, it acts like it has amnesia. The code style you agreed on, the project architecture, even the bugs you corrected last session — all gone. This isn't a bug. It's by design. Each Claude Code session starts with a fresh context window.

But Claude Code does have memory. Three kinds, actually. Once I figured out how they work, my productivity with Claude Code roughly doubled. No more re-explaining the project structure every session, no more correcting the same mistakes.

Let me walk through each memory mechanism and what I've learned using them day to day.

The Two Core Memory Systems

Claude Code has two complementary memory systems, both loaded at the start of every conversation:

  • CLAUDE.md files — instructions you write to give Claude persistent context
  • Auto Memory — notes Claude writes itself based on what it learns

One is something you actively feed it. The other it accumulates on its own. Get both right, and Claude Code goes from "new intern every session" to "developer who already knows the codebase."

CLAUDE.md: Your Project Manual for Claude

A CLAUDE.md is just a Markdown file that Claude reads at the start of every session. Think of it as an onboarding document for a new teammate — except this teammate loses their memory every time.

When to add to CLAUDE.md

Not everything belongs here. The official guidance is simple:

  • Claude made the same mistake twice
  • A code review caught something Claude should have known
  • You typed the same correction you typed last session
  • A new teammate would need the same context

In other words: stuff you're tired of repeating.

Where to put CLAUDE.md files

This is where it gets confusing. CLAUDE.md can live in several locations, each with different scope:

User level~/.claude/CLAUDE.md Your personal preferences that apply to all projects. "I prefer pnpm over npm." "Use 2-space indentation."

Project level./CLAUDE.md or ./.claude/CLAUDE.md Team-shared project conventions. Committed to git, visible to everyone. "Build with pnpm build." "Tests use vitest."

Local level./CLAUDE.local.md Your personal preferences for this specific project. Not committed to git. "My local DB password is xxx." "I like running unit tests before committing." Add it to .gitignore.

Directory level — CLAUDE.md in subdirectories Only loaded when Claude reads files in that subdirectory. Good for module-specific rules in large projects.

The loading order walks up from the filesystem root to your current directory, so project-level instructions override user-level ones.

How to write effective CLAUDE.md files

The biggest mistake I made was writing a CLAUDE.md that was too long. Claude stopped following it — too much content, and it couldn't focus on what mattered.

A few things I learned the hard way:

Keep it under 200 lines. CLAUDE.md consumes context window tokens. Longer files actually reduce compliance. If you have a lot of content, split it into .claude/rules/ with path-scoped loading.

Be specific, not vague. "Use 2-space indentation" beats "format code properly." "API handlers live in src/api/handlers/" beats "keep files organized." The more concrete, the better Claude follows.

Avoid contradictions. If two rules conflict, Claude picks one at random. Periodically audit your CLAUDE.md and rules directory for outdated or contradictory instructions.

Use Markdown structure. Headers, lists, grouping. Claude scans structure the same way humans do — organized beats wall-of-text every time.

A practical CLAUDE.md example

markdown
1
# Project Overview
2
 
3
Next.js 15 + Turso database full-stack site.
4
Deployed on Vercel, auto-deploy on push to main.
5
 
6
# Build & Test
7
 
8
- Install deps: `pnpm install`
9
- Dev server: `pnpm dev`
10
- Build: `pnpm build`
11
- Test: `pnpm test` (vitest)
12
- Must run `pnpm lint` before committing
13
 
14
# Code Standards
15
 
16
- TypeScript strict mode
17
- Functional components only, no classes
18
- Tailwind CSS for styling
19
- Error handling with try-catch, never swallow errors
20
 
21
# Project Structure
22
 
23
- `src/app/` — Next.js App Router pages
24
- `src/components/` — Reusable components
25
- `src/lib/` — Utilities and database operations
26
- `src/api/` — API routes

Short and focused. Claude reads it every session and immediately knows how the project works.

Importing other files

CLAUDE.md supports @path/to/file syntax for importing:

markdown
1
See @README for project overview and @package.json for available commands.
2
 
3
# Additional Instructions
4
- Git workflow @docs/git-instructions.md

Imported files get loaded into context at startup alongside the CLAUDE.md that references them. Note: this doesn't reduce token usage — the full content still enters the context window. But it does keep things organized.

AGENTS.md compatibility

If your repo already uses AGENTS.md for other AI coding tools, you can import it directly:

markdown
1
@AGENTS.md
2
 
3
## Claude Code Specifics
4
- Use plan mode for changes under src/billing/

Or just symlink: ln -s AGENTS.md CLAUDE.md.

.claude/rules/: Path-Scoped Rules

When your project grows beyond what a single CLAUDE.md can handle, .claude/rules/ comes to the rescue. The killer feature: rules can be scoped to specific file paths, so they only load when Claude is working with matching files.

Basic setup

Create a .claude/rules/ directory with topic-specific files:

code
1
your-project/
2
├── .claude/
3
│   ├── CLAUDE.md
4
│   └── rules/
5
│       ├── code-style.md
6
│       ├── testing.md
7
│       └── security.md

Rules without a paths field load unconditionally at startup.

Path-specific rules

This is where it gets powerful. Use YAML frontmatter with a paths field:

markdown
1
---
2
paths:
3
  - "src/api/**/*.ts"
4
---
5
# API Development Rules
6
 
7
- All API endpoints must include input validation
8
- Use standard error response format
9
- Include OpenAPI documentation comments

This rule only activates when Claude reads files under src/api/. Otherwise, it doesn't consume context at all.

Glob patterns supported:

  • **/*.ts — all TypeScript files
  • src/**/* — everything under src/
  • src/components/*.tsx — React components in a specific directory
  • src/**/*.{ts,tsx} — multiple extensions

This is incredibly useful for large projects. Frontend rules only apply to frontend files. Backend rules only to backend files. No cross-contamination.

User-level rules

~/.claude/rules/ applies to every project on your machine:

code
1
~/.claude/rules/
2
├── preferences.md    # My coding preferences
3
└── workflows.md      # My preferred workflows

User-level rules load before project rules, so project rules take priority.

Auto Memory: What Claude Learns on Its Own

This is the feature I find most impressive. Auto memory lets Claude take notes as it works — build commands, debugging insights, architecture decisions, code style preferences, workflow habits. It doesn't save something every session. It decides whether the information would be useful in a future conversation.

Where it lives

Each project gets its own memory directory: ~/.claude/projects/<project>/memory/. The <project> path is derived from the git repo, so all worktrees and subdirectories within the same repo share one memory directory.

code
1
~/.claude/projects/<project>/memory/
2
├── MEMORY.md          # Index, loaded every session
3
├── debugging.md       # Debugging patterns
4
├── api-conventions.md # API design decisions
5
└── ...

MEMORY.md is the index. The first 200 lines (or 25KB, whichever is smaller) load at session start. Topic files like debugging.md are loaded on demand when Claude needs them.

What it actually remembers

After using it for a while, I noticed Claude had picked up things like:

  • "This project uses pnpm, not npm"
  • "Tests use vitest, not jest"
  • "The DB connection string is in .env.local"
  • "That SSR hydration error happened because the component accessed window on the server"

Every new session, it carries this knowledge. Especially the debugging lessons — once it remembers a mistake, it doesn't repeat it.

Managing auto memory

Type /memory in Claude Code to see everything that's loaded — CLAUDE.md files, rules, and auto memory. You can toggle auto memory on/off, and open the memory folder to edit files directly.

Auto memory files are plain Markdown. Edit or delete them anytime. If Claude remembered something wrong, just fix it.

To manually tell Claude to remember something: "Remember that this project uses pnpm." Claude saves it to auto memory. For CLAUDE.md instead: "Add this to CLAUDE.md."

What survives /compact

Project-root CLAUDE.md survives compaction — after /compact, Claude re-reads it from disk and re-injects it. Subdirectory CLAUDE.md files don't auto-reload; they load next time Claude reads a file in that directory.

So put critical instructions in the root CLAUDE.md. Otherwise they might get "forgotten" after compaction.

Auto memory is unaffected by compaction — it lives on disk and gets re-read at session start regardless.

Practical Organization Tips

After months of use, here's the system I settled on:

CLAUDE.md holds:

  • Project architecture and directory layout
  • Build, test, deploy commands
  • Team coding standards
  • Important "always do X" rules

CLAUDE.local.md holds:

  • Local dev environment config
  • Personal preferences (doesn't affect team)
  • Test database/service addresses

.claude/rules/ holds:

  • Module-specific rules (frontend, backend, database)
  • Path-specific rules (API validation, component standards)
  • Special requirements for sensitive directories (billing, auth)

Auto memory:

  • Let Claude accumulate it naturally
  • Periodically review and remove stale entries
  • Debugging lessons — let Claude record them itself, more accurate than you writing them

Common Issues

Claude isn't following CLAUDE.md

Run /memory to verify the file is loaded. If loaded but ignored, make instructions more specific. If a rule must be enforced (like "run lint before commit"), use a Hook instead — Hooks are mandatory, CLAUDE.md is advisory.

CLAUDE.md is too large

Over 200 lines and compliance drops. Split into .claude/rules/ with path scoping. Or use @import for separate files (though this doesn't reduce token usage, just organization).

Auto memory saved something wrong

Go to ~/.claude/projects/<project>/memory/ and edit or delete. All plain text, no special format.

Monorepo interference from other teams' CLAUDE.md

Use claudeMdExcludes in .claude/settings.local.json:

json
1
{
2
  "claudeMdExcludes": [
3
    "**/monorepo/CLAUDE.md",
4
    "/path/to/other-team/.claude/rules/**"
5
  ]
6
}

Need system-prompt-level instructions

CLAUDE.md is injected as a user message, not a system prompt. For system-prompt level, use --append-system-prompt. But this needs to be passed every invocation, so it's better for scripts and automation.

Wrapping Up

Claude Code's memory system looks simple — just a few Markdown files — but the difference between using it well and ignoring it is huge. The key is finding balance: enough context for Claude to understand the project, but not so much that it gets drowned in noise.

My current setup: CLAUDE.md stays around 50 lines with core rules and build commands. Module-specific rules go in the rules directory. Auto memory stays on, and I check what Claude recorded every once in a while. Now every time I open Claude Code, it already knows 80% of the context. I just need to tell it what to do.

Planning to dig into the Hooks system next — that's the real enforcement mechanism, not relying on Claude's "judgment." Will write about that when I get to it.

Questions? Drop them in the comments.

advertisement

Claude Code Memory System Guide: CLAUDE.md, Auto Memory, and Rules in Practice — AI Hub