Claude Code's auto-memory system stores knowledge in a file called MEMORY.md. It's loaded into every conversation. It has a hard limit of 200 lines — everything after line 200 gets truncated. We hit 182 lines and almost ran out of room. So we built a three-tier architecture that retains 100% of our knowledge while cutting the index to 83 lines. Here's how.
Claude Code's memory system works like this: you save memories (user preferences, project context, feedback, gotchas) and they get written to individual .md files. An index file called MEMORY.md references all of them. This index is loaded into the context window at the start of every conversation.
The catch: MEMORY.md has a hard 200-line limit. Lines after 200 are silently truncated. As your project grows — more nodes, more services, more feedback, more gotchas — you fill up fast.
Most people hit this wall and do one of two things: stop saving memories (losing future knowledge), or delete old ones (losing past knowledge). Both are bad.
MEMORY.md is an index — a pointer file. It gets loaded automatically, but the files it points to are read on demand via the Read tool. Claude can read any file in the project at any time. So the index doesn't need to contain everything — it just needs to know where everything is.
We ran the numbers on our setup: 28 memory files totaling ~100KB. That's roughly 25,000 tokens. With a 1M token context window, that's 2.5% of context. We'd been cramming everything into a 200-line flat file when we had effectively unlimited room.
Slim routing table. Only the essentials needed in 80%+ of sessions: core node IPs, feedback rules, user preferences, project paths, cost guardrails. Points to Tier 2 and 3 for everything else.
All memory files concatenated into one dense text file. Claude reads it with the Read tool when it needs detail beyond what's in the index. No vision parsing, no lossy compression — just text.
Memory files synced to an Obsidian vault, auto-indexed every 30 minutes by 4 RAG backends (vector, visual, knowledge graph, hybrid). Best for questions like "what did we decide about X?" or "where was that gotcha about Y?" Not everyone has this — but if you have any RAG system, wire your memories into it.
Most conversations only need Tier 1. You ask Claude to SSH into a server — it already knows the IP from the slim index. You ask for TTS — it knows not to use the wrong voice. You say "make it so" — it knows that means full autonomy.
When a conversation goes deeper — "what's the exact TestFlight upload flow?" or "what did the fleet model eval score?" — Claude reads the full reference file. One Read call, 25K tokens, every detail preserved.
For truly open-ended questions — "what do we know about DGX Spark gotchas?" — it searches the RAG. Semantic retrieval across all memory files, weighted by recency, connected by knowledge graph.
The key is that MEMORY.md explicitly tells Claude about the other tiers. The header says: "For full details, read memory-full-reference.md." Claude knows where to look.
| Metric | Before | After | Change |
|---|---|---|---|
| MEMORY.md lines | 182 | 83 | 54% reduction |
| Free headroom | 18 lines | 117 lines | 6.5× more room |
| Capacity used | 91% | 42% | — |
| Information retained | 100% | 100% | Zero loss |
| On-demand detail | Read individual files | One file, 25K tokens | Simpler |
| Semantic search | None | 4 RAG backends | New capability |
Before landing on the text-based approach, we tried something more exotic: rendering all memory into a dense info-graphic JPG and having Claude read it via its multimodal vision capabilities.
We built a 2400×4000px HTML page with every memory file rendered in a tight 3-column grid, color-coded by tier. Screenshotted it with Chrome headless. The image looked great.
Retrieval accuracy: ~60-70%. Section headers and structure were readable. Tier badges and color coding came through. But specific values — IP addresses, UDIDs, passwords, CLI flags — were too small to parse reliably. Vision on dense monospace text at 9px just isn't there yet.
Verdict: Images are a nice supplementary layer for visual overview, but not a reliable primary store. Dense text read via the Read tool gives 100% accuracy. We kept the JPG as a bonus Tier 1.5 but the real win is the text concatenation approach.
MEMORY.md.memory-full-reference.md. This is your Tier 2 — readable on demand.#!/bin/bash # Concatenate all memory files into one dense reference OUTPUT="memory-full-reference.md" echo "# Claude Memory — Full Reference" > "$OUTPUT" echo "> Generated: $(date +%Y-%m-%d)" >> "$OUTPUT" echo "" >> "$OUTPUT" for f in *.md; do [ "$f" = "MEMORY.md" ] && continue [ "$f" = "$OUTPUT" ] && continue echo "---" >> "$OUTPUT" echo "## FILE: $f" >> "$OUTPUT" echo "" >> "$OUTPUT" cat "$f" >> "$OUTPUT" echo "" >> "$OUTPUT" done echo "Built: $(wc -l < "$OUTPUT") lines"
# Project Memory — Routing Table > **Three-tier memory system.** > - **Tier 1 (this file)**: Core essentials (~80 lines) > - **Tier 2**: [memory-full-reference.md](memory-full-reference.md) > — ALL files concatenated (~25K tokens). Read when you need details. > - **Tier 3**: RAG search — memory files indexed for semantic retrieval ## Core Rules ... (your most-used 80% of knowledge here) ...
The 200-line limit exists because MEMORY.md is loaded into every conversation. Anthropic wants it slim to protect the context window. Fair.
But with Opus/Sonnet's 200K+ context (and 1M for some plans), 25K tokens is noise. You're not going to notice 2.5% of your context used for memory. Especially when the alternative is losing knowledge or spending the first 5 minutes of every conversation re-discovering things Claude already knew yesterday.
The trick is separating the always-loaded index from the on-demand knowledge store. The index is small and fast. The store is complete and accurate. You get both.