Content
# claude-memory-3tier
**Stop re-explaining your project to your coding agent every session.**
A small, auto-activating memory system for Claude Code (and any harness with
session hooks) that survives new sessions **and `/compact`**. No daemon, no
vector DB, no cloud — just a SessionStart hook plus markdown files your agent
reads on startup and rehydrates after compaction.
It composes three independent layers, each solving a *different* failure mode:
| Tier | What it remembers | Where it lives | Automatic? |
|------|-------------------|----------------|------------|
| **0 — Per-repo bank** | "What am I doing, what's decided, why" for THIS repo | `<repo>/.claude/memory/*.md` | ✅ load + bootstrap via hook |
| **1 — Cross-project** | Reusable insights/patterns across repos | [basic-memory](https://github.com/basicmachines-co/basic-memory) → your Obsidian vault | ✅ via MCP (optional) |
| **2 — Code structure** | What-calls-what, impact, callers/callees | [CodeGraph](https://github.com/) index (`.codegraph/`) | ✅ auto-init via hook (optional) |
Only **Tier 0** is required and dependency-free. Tiers 1 and 2 are optional add-ons.
---
## The problem
Context windows are finite. Even at 1M tokens, long sessions get summarized by
`/compact` — which is *lossy*. Open a new session in the same repo and the agent
has forgotten the architecture, the decisions, and what you were mid-way through.
You cannot "prevent" compaction loss. The only fix is to **externalize state**
(to files) and **re-inject it** at session start. That's all this does — but
automatically, for every git repo, including right after a compaction.
## How Tier 0 works
A single `SessionStart` hook fires on `startup`, `resume`, `clear`, **and
`compact`**. On each fire it:
1. Resolves the git repo root (skips non-projects and `$HOME`).
2. Bootstraps `.claude/memory/` with four skeleton files if missing:
`activeContext.md`, `progress.md`, `decisions.md`, `architecture.md`.
3. Injects their contents back into the agent's context.
Because it also fires with `source == "compact"`, your externalized state is
**rehydrated immediately after every compaction**. The hook only *loads*; your
agent *writes* the files as work progresses (see [SKILL.md](SKILL.md)).
The hook is **fail-open**: any error exits 0 and never blocks a session.
## Install
```bash
git clone https://github.com/<you>/claude-memory-3tier.git
cd claude-memory-3tier
./install.sh
```
`install.sh` copies the hook to `~/.claude/hooks/` and merges a `SessionStart`
entry into `~/.claude/settings.json` (idempotent, backs up first). Restart
Claude Code. From then on, every git repo you open gets a memory bank
automatically.
### Optional — Tier 2 (CodeGraph)
If the `codegraph` CLI is on your `PATH`, the hook auto-runs `codegraph init -i`
in the background for any git repo lacking an index. Skip it and Tier 0 still
works.
### Optional — Tier 1 (basic-memory → Obsidian)
```bash
uv tool install basic-memory
basic-memory project add ai-memory /path/to/your/ObsidianVault/AI-Memory
```
Then register it as an MCP server in `~/.claude.json`:
```json
"basic-memory": { "command": "basic-memory", "args": ["mcp"] }
```
## Opt out of one repo
```bash
touch <repo>/.claude/memory/.disabled
```
## Should I commit `.claude/memory/`?
Yes — committing the bank versions your project state and syncs it across
machines. The repo's `.gitignore` should ignore the transient marker and index:
```gitignore
.claude/memory/.codegraph-init-started
.codegraph/
```
## Prior art / credits
- Per-repo markdown convention is inspired by **Cline's Memory Bank**.
- Tier 1 uses **basic-memory** by Basic Machines.
- Tier 2 uses a **CodeGraph**-style AST index.
This project just wires them into one auto-activating, compaction-surviving
system. MIT licensed.