The Complete Guide to Claude Code Memory: CLAUDE.md · Auto Memory · claude-mem Plugin Comparison and Practical Setup
If you've been using Claude Code for a while, you've probably run into this situation. You spent two hours yesterday digging into an ESM/CJS interop issue and got everything sorted out including the tsconfig.json settings — but when you open a new session today, Claude acts like it has no idea and starts asking questions from scratch. It feels like onboarding a new teammate every single morning.
Claude Code's memory system exists to solve this problem. But it's not a single feature — it's composed of three layers with entirely different roles, which makes it easy to get confused about what each one actually does at first. I found myself wondering why I needed CLAUDE.md separately when Auto Memory already exists, and what on earth the claude-mem plugin was supposed to be.
This post is aimed at developers already using Claude Code. It explains how CLAUDE.md, Auto Memory, and claude-mem differ from one another, and how you can combine them in a real project — with concrete examples throughout.
Core Concepts
A Three-Layer Memory Architecture
"Claude Mem" is not an official feature name — it's a general term for the memory layers in the Claude Code ecosystem. The similarly named claude-mem is a separate community plugin, which we'll cover later. Getting the role of each layer straight up front makes the rest of this much easier to follow.
| Layer | Who writes it | Storage location | Characteristics |
|---|---|---|---|
| CLAUDE.md | Developer, manually | Project root or ~/.claude/ |
Static rules, Git-committable |
| Auto Memory | Claude, automatically | ~/.claude/projects/<git-root>/memory/ |
Dynamic, updated each session |
| claude-mem plugin | Community extension | Local SQLite DB | Full session archive + re-injection |
Layer 1: CLAUDE.md — Static Rules Shared by the Team
A markdown file that is automatically loaded into the context window when a session starts. It's well-suited for rules that change infrequently and that the entire team must follow — things like build commands, coding conventions, and architectural decisions.
# Project Rules
## Build & Test
- Build: `pnpm build` (do not use npm)
- Test: `pnpm test`
## Code Style
- TypeScript strict mode
- Use async/await (no Promise.then())
- 2-space indentation
## Architecture
- NestJS: business logic in Service only, keep Controllers thin
- API middleware location: src/middleware/auth.ts
## Known Issues
- ESM/CJS interop: always check moduleResolution in tsconfig.jsonBecause it's markdown, you can edit it directly in vim and include it in your PRs. In a monorepo, committing .claude/CLAUDE.md to Git means every team member starts with the same context.
Warning: In practice, if CLAUDE.md gets too long, Claude tends to follow the content toward the end less reliably. It's more effective to keep only what Claude absolutely must know and split the rest into separate files.
Layer 2: Auto Memory — A Diary Claude Writes for Itself
This feature automatically saves what Claude learns during a session to markdown files. It's enabled by default with no additional configuration required. Files are stored under ~/.claude/projects/<git-root>/memory/ and organized into four categories.
~/.claude/projects/my-project/memory/
├── user_preferences.md # User's working style
├── feedback_testing.md # Feedback on testing approaches
├── project_auth_rewrite.md # In-progress project context
└── reference_grafana.md # Pointers to external systemsEach file follows a frontmatter format, and the description field is especially important.
---
name: Testing Approach Feedback
description: Decision to avoid mocks in database-related tests
type: feedback
---
DB tests must use a real database. There was a case where mock tests passed but the production migration failed.
**Why:** An incident last quarter caused by mock/prod environment mismatch
**How to apply:** Always use a real DB connection when writing DB-related test code"How does it find relevant memories without a vector DB?" — I was puzzled by this at first too. The key is that the Sonnet model reads the description field of each memory file and directly assesses semantic relevance to the current session. Without any external embedding service or vector DB, the language model itself picks the relevant files using its own understanding.
Database-Free Memory Architecture: The biggest advantage is low operational complexity, but selection quality may degrade once you have hundreds of memory files. For large teams, adding a vector search layer like Milvus is worth considering.
Layer 3: claude-mem Plugin — Full Session Archive
A community-developed MCP plugin with a different purpose from Auto Memory. Where Auto Memory stores "what Claude learned in the current project," claude-mem archives every conversation from every session to a SQLite3 DB and re-injects relevant context at the start of the next session. It's especially useful when you move between machines frequently or have accumulated a very large number of sessions.
Bonus Feature: Auto Dream — Memory Consolidation
Released in March 2026, this feature periodically cleans up and consolidates accumulated memories. The two behaviors you'll notice most in practice are:
First, it converts relative dates to absolute dates.
Before: "Switched from Express to Fastify yesterday"
After: "Switched from Express to Fastify on 2026-03-15"Second, it detects and resolves contradictory entries. If an old entry about Express remains after the switch to Fastify, it deletes or updates the older entry in favor of the more recent one. That said, the conflict-resolution logic isn't perfect, so important entries still benefit from periodic manual review.
Practical Application
Basic Setup
Example 1: Maintaining Codebase Context Across Multiple Sessions
This is the most fundamental pattern — never having to re-explain debugging insights accumulated over 20 sessions. By documenting known issues in CLAUDE.md, Claude starts every new session already aware of that context.
# CLAUDE.md — located at project root
## Known Issues & Gotchas
- **ESM/CJS interop**: Some packages in this project are CJS only.
Symptom: `ERR_REQUIRE_ESM` runtime error
Fix: Check `moduleResolution: "bundler"` in tsconfig.json
- **Environment variable loading order**: dotenv must be loaded at the very top of the app entry point.
Violation causes: undefined env vars in some services
## Directory Structure
- Tests: `__tests__/` (Jest)
- API middleware: `src/middleware/`
- Type definitions: `src/types/`Here's roughly what Auto Memory adds automatically on top of that:
---
name: Build Tool Configuration
description: Package manager and build commands for this project
type: project
---
Build: pnpm build (npm not available — workspace hoisting conflicts)
Test: pnpm test --passWithNoTests
Lint: pnpm lint (runs eslint then tsc --noEmit in that order)| What gets saved | Type | Practical effect |
|---|---|---|
| Build commands, package manager | project | No need to re-explain "use pnpm" every session |
| Test directory location | project | Auto-detects where to create test files |
| Debugging insights | feedback | Avoids repeating mistakes from previous sessions |
| External system pointers | reference | No need to re-enter Grafana dashboard URLs, etc. |
Example 2: Team-Shared CLAUDE.md (Monorepo Pattern)
When different team members explain things differently to Claude, the results become inconsistent — a common frustration in practice. Sharing CLAUDE.md via Git solves this.
my-monorepo/
├── .claude/
│ └── CLAUDE.md # Team-wide rules (Git-committed)
├── apps/
│ ├── web/
│ │ └── CLAUDE.md # Web app-specific rules
│ └── api/
│ └── CLAUDE.md # API server-specific rules
└── packages/# .claude/CLAUDE.md — monorepo root
## Package Manager
Using pnpm workspace. To install in an individual package:
`pnpm --filter @myapp/web add <package>`
## Shared Type Package
Import shared types from the `@myapp/types` package.
Do not define duplicate types.
## PR Rules
- Branches: feature/*, fix/*, chore/*
- Commit messages: imperative mood (Korean is fine)
- Example: "인증 미들웨어에 JWT 갱신 로직 추가"Advanced Setup
Example 3: Configuring the claude-mem Plugin
This pattern is based on a documented real-world case of sharing over 3,400 session records between two servers. It's useful for developers who frequently move between machines.
# Install claude-mem
pnpm add -g claude-mem
# Initialize (creates a per-project DB)
claude-mem init// Register claude-mem in your MCP config file
// ~/.claude/mcp_settings.json
{
"mcpServers": {
"claude-mem": {
"command": "claude-mem",
"args": ["serve"],
"env": {
"CLAUDE_MEM_DB_PATH": "/Users/yourname/.claude-mem/sessions.db"
}
}
}
}Warning: Tilde (
~) expansion may not apply to environment variables in JSON. It's recommended to use the full absolute path instead of~.
To move the DB file between servers, you can copy it with scp. Keep in mind this is a one-way copy — if you work on both servers simultaneously, whichever one writes last wins.
# One-way copy: local → remote
scp ~/.claude-mem/sessions.db user@remote-server:~/.claude-mem/sessions.dbThe PreToolUse hook is particularly useful: if a file has been read before, it blocks the actual Read tool call and injects only the cached summary instead. This saves a noticeable number of tokens that would otherwise be spent on redundant file reads.
Pros and Cons
Honestly, this system doesn't always work perfectly. You'll get a lot more out of it if you know both its strengths and its limits.
Advantages
| Item | Details |
|---|---|
| Directly editable | It's markdown — edit it in vim right away and include it in PRs |
| Fully inspectable | You can open memory files and immediately see what's stored |
| Git integration | Worktrees and subdirectories share the same memory directory |
| Token efficiency | Async prefetch + LLM selection loads only relevant files |
| Zero-config automation | Auto Memory is on by default, no setup required |
| Team collaboration | Commit CLAUDE.md to Git to share context across the team |
Disadvantages and Caveats
| Item | Details | Mitigation |
|---|---|---|
| Memory quality degradation | After 20–30 sessions, contradictory entries may coexist | Enable Auto Dream; monthly manual review recommended |
| Long CLAUDE.md | If it gets too long, compliance with later content may drop | Keep only core rules; split the rest into separate files |
| Relative date problem | Expressions like "yesterday" or "last week" become meaningless over time | Enable Auto Dream or use absolute dates when saving |
| Large-scale memory search | LLM-based selection hits performance limits past hundreds of files | Add a vector search layer like memsearch + Milvus |
| Privacy | claude-mem stores entire sessions in a local SQLite DB | Store the DB path on a secured volume for sensitive code |
Context Window: The maximum length of text an LLM can process in a single pass. Both CLAUDE.md and Auto Memory files are loaded into this space, so the more content you accumulate, the less room remains for actual work — and the influence of earlier content diminishes.
Auto Memory ≠ Fine-tuning: Saving a memory does not update model weights. It works via context injection, which means relevant memories must be selectively loaded each session to have any effect.
The Most Common Mistakes in Practice
-
Trying to put everything in CLAUDE.md — Writing it like a project wiki causes the important rules to get ignored. It's far more effective to keep only what Claude absolutely must not be unaware of.
-
Confusing the roles of Auto Memory and CLAUDE.md — CLAUDE.md holds rules that the team has deliberately defined; Auto Memory holds what Claude has learned from experience. Editing Auto Memory files directly is possible, but team rules should always be explicitly written in CLAUDE.md.
-
Leaving memory files unattended — Trusting Auto Memory to handle everything on its own and neglecting it for dozens of sessions means incorrect assumptions saved early on will keep getting injected. It's worth opening
~/.claude/projects/directly about once a month and cleaning out stale entries.
Closing Thoughts
The key to Claude Code's memory system is this: it maintains context across sessions using nothing more than markdown files — no complex infrastructure required. Even just creating a single CLAUDE.md right now will make a noticeable difference starting from your very next session. In practice, it has meaningfully cut down the time I spend re-establishing context at the start of each session.
Three steps you can take right now:
-
Create CLAUDE.md: Make a
CLAUDE.mdfile in your current project root and start with just three things: your build command, package manager, and known issues. Even starting withecho "# Project Rules\n\n- Build: pnpm build" > CLAUDE.mdis enough. -
Check Auto Memory: After working through one session with Claude Code, browse
~/.claude/projects/directly to see what Claude has remembered. If anything is incorrect, just edit the markdown file directly. -
Apply to your team: Once you've validated it solo, share the context with everyone via
git add .claude/CLAUDE.md && git commit -m "프로젝트 Claude 컨텍스트 규칙 추가".
Next post: Beyond Claude Code memory — multi-agent orchestration where multiple agents each maintain their own independent memory while collaborating through shared context. A look at the A2A (Agent-to-Agent) protocol and shared memory design strategies.
References
Official Documentation
In-Depth Analysis
- Claude Code Memory System Explained: 4 Layers, 5 Limits, and a Fix - Milvus Blog
- Inside Claude Code: The "Database-Free" Memory Architecture - Medium
- Claude Code Deep Dive Part 4: Why It Uses Markdown Files Instead of Vector DBs - DEV Community
- Auto Memory and Auto Dream: how Claude Code learns and consolidates its memory
- Claude Code Memory Guide (2026): CLAUDE.md vs Auto Memory vs Plugins - LaoZhang AI Blog
- Claude Code Source Leak: The Three-Layer Memory Architecture - MindStudio
Community Cases