Skip to content

Latest commit

 

History

12 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Claude Memory Manager

A Claude Code skill that adds a write spec, placement routing, and a hub-first index budget
on top of built-in auto-memory — so recall still works at file 250, not just file 15.

Claude Code 2.1+ MIT

English | 中文


Why

Claude Code's auto-memory gets the mechanics right: plain markdown in ~/.claude/projects/<slug>/memory/, a MEMORY.md index loaded at session start, topic files read on demand, a type and a modified timestamp in each file's frontmatter. What it doesn't give you is discipline. After a few months of real use, three failure modes show up:

  1. Fragmentation. The same topic accretes across five near-duplicate files. Claude updates none of them — or the wrong one — and every session re-learns what a previous session already knew.
  2. Vague descriptions. Native recall has no semantic search. Discovery is literally "scan the index lines, pick by description, Read the file". An entry indexed as "Supabase issues" will never be found again.
  3. Index overflow. Only the first 200 lines or 25KB of MEMORY.md load per session, and the 25KB is enforced as characters, not bytes. Since v2.1.210, Claude at least gets an error right after a write crosses the line. But the error comes after the fact, and its only advice is "shorten it", so the index gets squeezed under pressure, usually by trimming the very descriptions recall depends on. Hand edits and older versions still truncate with no signal at all.

This skill treats memory as an engineered retrieval system with a fixed budget, not a journal: a typed write spec, a routing rule for where each fact belongs, and a hub-first index that stays far below the load limit — plus a one-command audit that flags drift before it costs you.

The design

Three questions, three mechanisms.

1. How to write — a typed schema

Every entry is one file, one topic: <type>_<topic>.md with required frontmatter (name / description / type). The four types match the native ones:

  • feedback — a lesson learned or a correction. Must carry a Why section: without the reasoning, the next session re-litigates the same decision and often lands on the same wrong conclusion. The Why is what makes a lesson stick.
  • reference — natively, a pointer to an outside resource; this skill also uses it for deep topic references, SOPs, and hub pages.
  • project — state snapshots: architecture, in-flight work, decision records.
  • user — the user's role, expertise, and preferences.

The description is the retrieval key, so it must pack scenario keywords + the conclusion — "browser-side supabase.from() mutation deadlocks after tab switch, use fetch() against the REST API", never "Supabase issues". If you can't imagine the future question that would match it, the description isn't done.

2. Where to write — locality routing

Write it where you'll trip over it. Not everything belongs in memory:

Trigger Destination Mechanism
Staring at one line/block; the WHY fits in a sentence Inline code comment 100% hit rate when editing that file, zero index cost
A multi-point contract over a known set of files .claude/rules/*.md + paths: Injected when Claude reads, writes, or edits a matching file
A scenario / error class / cross-file or platform pitfall Memory (this system) Recalled via index description
A rule for every session (commands, stack, preferences) CLAUDE.md Always loaded

With anti-over-migration guardrails: if removing the specific file still leaves a general lesson, it stays in memory; platform/SDK behavior stays in memory; tombstones and investigation SOPs stay in memory. Empirically (full audit of a 175-file production library): only ~15% of entries bind to a single file, and most of those already existed as code comments — index bloat comes from weak governance, not from file-local junk.

One trap worth knowing before you move contracts into rules: if .claude/rules (or a rule file) is a symlink to somewhere outside the project, Claude Code treats it like an external import, and even after you approve it, only rules without paths: load. Every path-scoped rule in that directory goes quiet. Keep rules in a real directory inside the repo, and after adding one, Read a matching file to confirm it was injected.

3. How much to write — a hub-first index budget

The 200-line / 25KB load limit is the hard wall the design leans against. The index is budgeted like a cache, not grown like a log:

  • Hub-first — MEMORY.md holds only crown entries (⭐⭐⭐ / ⚠️⚠️, "read this before touching X") plus one pointer line per group. Every other entry lives in the group's hub file (reference_<group>_hub.md) from day one. Non-crown entries cost one extra Read hop; in exchange, the always-loaded layer stops competing with itself for space.
  • Two lines below the wall — a safety line at 190 lines / 23,000 characters, and a target line at 120 lines / 16,000 characters. Stay under the target and the native overflow error never fires.
  • Short link labels and aggregate lines — [foo-bar](feedback_foo_bar.md), never the full filename twice; rarely-needed entries share one line (topic → [a](f1.md) · [b](f2.md) · [c](f3.md)).
  • String length, not bytes — the docs phrase the limit as "25KB", but the enforced measure is string length (= characters; CJK is 3 bytes per character in UTF-8). Verified by locating the actual cut: a 37.9KB / 27,972-character index truncated exactly at the 25,000-character mark. And wc -m only counts characters under a UTF-8 locale; in a bare shell it quietly counts bytes. The audit script pins a UTF-8 locale and, like Claude Code since v2.1.211, ignores frontmatter and HTML comments when it measures.

When the index still grows past its target, slim in this order: migrate file-local entries out → delete true tombstones → move crowns to the top → push entries down into hubs → compress descriptions last. Compressing first is the intuitive move, and it's exactly what the native "shorten it" error nudges toward. It's also the only step that damages the retrieval key itself.

Full trade-off notes → references/design-philosophy.md

vs the built-in tools

The built-in system is the substrate — this skill never fights it, it makes Claude write to a spec the substrate rewards:

Auto-memory alone With this skill
Write spec Native types, free-form content 4 types, required frontmatter, Why on feedback
Decision protection Conclusions get re-litigated Why section preserves the reasoning
Placement Everything lands in memory 4-level routing; file-local facts become code comments or path rules
Index size Error after a write crosses the limit Budgeted in characters, hub-first, kept well under the limit
Duplication New file per session whim Update-over-create, frozen groups, hub pages
Health check None for the memory directory One-command audit: 5 hard checks + 8 soft signals + compliance score

Two other built-ins sit next to it, not in its place:

  • /doctor prompt-audit (v2.1.283+) reviews CLAUDE.md, rules, skills, and other instruction files for outdated or conflicting content. By default it doesn't cover the auto-memory directory; that's what this audit is for.
  • consolidate-memory (Anthropic's skill, where available) does a periodic merge-and-prune pass over memory. It's a good first opinion for a big cleanup; this skill decides what the result should look like.

For semantic retrieval over chunked storage, look at vector-backed tools like Mem0, Letta, or Zep — different problem. The native runtime does no embedding recall, so the leverage isn't in adding vectors; it's in making the index the runtime does read actually work.

Battle-tested

These rules weren't designed on a whiteboard. They come from a production library (CJK-heavy, now 256 files) that hit every failure mode first: an index that silently truncated at 43KB on disk (≈31K characters, well past a limit nobody had measured), a bytes-vs-characters miscalibration that re-broke it a month later, groups past 20 entries with routine recall misses.

Then two cleanups. In July, the index came down from 27,972 to 22.7K characters, and a 483-line CLAUDE.md was split to 176 lines with every displaced fact verified findable afterwards. That still left the index within 10% of the cap. In September, a full audit of 243 files (200 kept as-is, 40 trimmed, 3 superseded or merged, none deleted) and the hub-first restructure took the index from 181 lines / 22,994 characters to 83 lines / 9,408 characters, with 18 groups merged into 9. The project CLAUDE.md is now 66 lines.

Today's audit of that library:

Memory audit · 2026-10-05 · 256 files

Hard checks (must be zero):
  missing frontmatter          0
  frontmatter fields           0
  feedback missing Why         1
  naming violations            0
  broken index links           0

Soft signals:
  not indexed (MEMORY+hubs)    0
  oversized files             21
  groups over 15 entries       1
  retired, no tombstone        0
  missing modified field       3
  untouched 120+ days         48
  MEMORY.md size             10529 chars / 87 lines  OK (target ≤16000 / ≤120)
  index lines >200 chars       2

  ... (per-item detail listings omitted) ...

Hard-rule compliance: 99.6%  (hard violations: 1, files: 256, target ≥ 95%)

The one hard violation is real, and the previous audit version missed it: recent Claude Code versions nest frontmatter under metadata: next to a node_type: field, and the old script read node_type: memory as the file's type and skipped its feedback checks.

Install

Tell Claude

Paste this into any Claude Code session:

Install the claude-memory-manager skill from
https://github.com/jau123/claude-memory-manager

Claude handles the rest. To verify, say "audit memory" in a new session.

Or install manually
git clone https://github.com/jau123/claude-memory-manager.git && \
  mkdir -p ~/.claude/skills/memory-management/templates && \
  cp claude-memory-manager/SKILL.md ~/.claude/skills/memory-management/ && \
  cp claude-memory-manager/templates/* ~/.claude/skills/memory-management/templates/

Per-project audit script, CLAUDE.md memory protocol, upgrading from the July version → INSTALL.md

First Use

The skill activates from natural language. No slash command.

You: "Record today's wildcard bug fix"
→ Claude writes one feedback_*.md entry: filename, frontmatter,
  Why section, How-to-apply, and a line in the right hub.

You: "Review the session"
→ Claude walks recent session, surfaces 3–5 candidates, asks
  which to keep.

You: "Audit memory"
→ Runs scripts/audit-memory.sh, reports compliance, lists files
  that need splitting.

You: "Set up memory for this project"
→ Follows templates/bootstrap.md: index skeleton, group thresholds,
  CLAUDE.md pointer.

Full trigger reference → SKILL.md (written in Chinese; Claude follows it regardless of the language you work in)

Limits

  • Single-project scope. One memory directory per audit run; no cross-project consolidation.
  • No semantic ranking. The audit is pattern matching (grep + filename + frontmatter); it won't catch "two files describe the same concept in different words."
  • Native behavior moves. Facts about Claude Code (limits, frontmatter shape, rules injection) were last checked against the official docs in October 2026 (Claude Code v2.1.286). Re-check after major upgrades.
  • Bash + standard Unix tools. Tested on macOS bash 3.2 and Linux bash 5.x; Windows / git-bash untested.
  • No concurrency safety. Don't run the audit while another session is mid-write.
  • Overkill for small libraries. Below ~10 entries or a month of project age, the built-in auto-memory is sufficient and the schema overhead doesn't pay off.

License

MIT · Issues and PRs welcome at jau123/claude-memory-manager.

About

A Claude Code skill that keeps your project's memory library auditable, named consistently, and free of drift — for months, not days.

Topics

Resources

Stars

4 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages