Give Claude a memory that survives everything.
Compacts, crashes, restarts, weekends — works in Claude Code AND Claude Cowork.
# Add the marketplace
/plugin marketplace add hlsitechio/claude-memory
# Install the plugin
/plugin install claude-memory@hlsitechioThat's it. Restart Claude Code and memory is active. Claude will never lose context again.
💡 Works in Claude Cowork too! Same state.md, same memory. Start a task in Code, review it in Cowork — seamless cross-platform memory.
🚨 The problem: Claude starts every session blank. When the context window fills up, auto-compact fires and your conversation history is compressed. Terminal crash? Switch from Code to Cowork? Complete amnesia.
✅ The fix:
claude-memory— a hook-based system that automatically saves and restores your working state across sessions, compacts, crashes, platform switches, and restarts.
Claude Code (terminal) Claude Cowork (desktop)
┌────────────────────┐ ┌────────────────────┐
│ Build feature │ │ Review progress │
│ state.md updated │───disk────→ │ Reads state.md │
│ Goal: Auth system │ │ "You're 3/7 done │
│ Progress: 3/7 done │ │ on auth system, │
│ Findings: bypass! │ │ found a bypass..." │
└────────────────────┘ └────────────────────┘
Same state.md on disk
- Hunt in Code → findings saved to state.md
- Review in Cowork →
/claude-memory:recallloads your full state - Set goals in Cowork → Code picks them up on next session start
- Crash Code? → open Cowork, your memory is on disk, nothing lost
Session 1: You build something complex over 2 hours
↓ context fills up
↓ auto-compact fires 💥
Session 1 (continued): Claude forgot everything 🤷
↓ terminal crashes
Session 2: Total amnesia. "What were we working on?" 😶
v2 introduces state.md — a living document that Claude actively maintains:
# Session State
> Last updated: 14:30
## Goal
Build the user authentication system with JWT tokens
## Progress
- [x] Set up database schema
- [x] Implement login endpoint
- [ ] Add token refresh logic
- [ ] Write integration tests
## Findings
- Auth middleware needs to handle expired tokens gracefully
- Rate limiting should be per-user, not per-IPWhy this works: state.md lives on disk, not in context. When auto-compact fires, state.md is untouched. Claude reads it back and picks up exactly where it left off.
Every piece of state is also backed up as a state snapshot in .mci:
| Component | What it captures |
|---|---|
| 📝 Memory | Goal — what you're working on |
| 🔗 Context | Progress — what's done, what's next |
| 🎯 Intent | Findings — discoveries and important data |
┌─────────────────────────────────────────────────────────┐
│ 🟢 SessionStart │
│ → Creates/resumes session + state.md template │
│ → Loads last .mci (cascades up to 7 days back) │
│ → Detects crashes & recovers automatically │
│ → First-run: copies templates, onboards Claude │
├─────────────────────────────────────────────────────────┤
│ 🔵 UserPromptSubmit (every prompt) │
│ → Checks state.md health (exists? updated?) │
│ → Auto-checkpoints state.md every ~10 prompts │
│ → Estimates context usage & warns before compact ⚠️ │
│ → Captures legacy markers as backup │
├─────────────────────────────────────────────────────────┤
│ 🟠 PreCompact (before auto-compact) │
│ → Snapshots FULL state.md content to .mci │
│ → 3-tier fallback: state.md → markers → JSONL │
│ → Creates conversation backup 💾 │
├─────────────────────────────────────────────────────────┤
│ 🔴 Stop (session end) │
│ → Snapshots state.md to .mci │
│ → Generates session summary 📊 │
└─────────────────────────────────────────────────────────┘
- 📂 Creates
.claude-memory/sessions/directory - 📝 Creates
state.md— your living state file (Claude's external brain) - 🎭 Copies
IDENTITY.mdandPREFERENCES.mdtemplates to your project - 🧠 Injects v2 rules so Claude understands state.md immediately
- 💬 Guides Claude through a first-run welcome message
| Command | What it does |
|---|---|
/claude-memory:save |
Manual checkpoint — save state to .mci right now |
/claude-memory:recall |
Load and display last saved state |
/claude-memory:status |
Dashboard — state.md health, .mci entries, session info |
/plugin marketplace update hlsitechio
/plugin update claude-memory@hlsitechioFor full control or if you want to customize the hooks:
git clone https://github.com/hlsitechio/claude-memory.git
cd claude-memory
./install.sh /path/to/your/projectThe installer will:
- 📂 Copy 4 hook scripts to your project's
.claude/hooks/ - 📄 Install
CLAUDE.mdwith v2 rules - ⚙️ Generate
.claude/settings.local.jsonwith hook configuration - 🗂️ Create the
.claude-memory/sessions/directory - 🎭 Optionally install identity templates (
IDENTITY.md,PREFERENCES.md)
| Requirement | Plugin | Manual |
|---|---|---|
| 🤖 Claude Code | v2.1+ | v2.1+ |
| 📦 Node.js | ✅ (bundled with Claude Code) | Not needed |
| 🔧 jq + bash | Not needed | Required |
state.md is your primary recovery mechanism. It lives on disk, completely outside the context window. When compact fires:
- Pre-compact hook snapshots state.md → .mci (automatic)
- Anthropic's black box compact compresses the conversation
- SessionStart fires, tells Claude: "Read state.md"
- Claude reads Goal/Progress/Findings and resumes work
No data loss. No "what were we doing?" No amnesia.
If the terminal crashes (Stop hook never fires):
- On next startup, SessionStart detects the crash (no end marker)
- Loads the .mci from the crashed session
- state.md is still on disk — full state preserved
- Injects a CRASH RECOVERY block telling Claude what happened
- Claude resumes — no questions asked
Every ~10 prompts, the hook auto-snapshots state.md to .mci. Even if Claude never manually saved and the terminal crashes, there's recent state.
When loading memory, SessionStart searches:
current session .mci
→ previous session (timed out)
→ earlier sessions today
→ yesterday → ... → up to 7 days back
| Tier | Source | When |
|---|---|---|
| 🥇 Best | state.md snapshot | state.md exists and has content (>200 bytes) |
| 🥈 Good | Assembled from marker files | Legacy markers captured, no state.md |
| 🥉 Emergency | Extracted from JSONL transcript | Nothing else available |
In v2, markers are primarily display formatting. The real memory lives in state.md.
| Marker | Display | state.md Action |
|---|---|---|
✅ [+] |
Success | (display only) |
❌ [-] |
Failed | (display only) |
🔴 [!] |
Critical | → Edit Findings section |
🟢 [>] |
Next step | → Edit Progress section |
🟡 [*] |
Context | → Edit Goal section |
🔵 [i] |
Info | → Append to memory.md |
The prompt-capture hook still watches for markers in Claude's responses and auto-saves them to facts.md/context.md/intent.md. This is backward compatibility — state.md is primary.
When Claude writes:
[!] Found that the API rate limit can be bypassed by rotating User-Agent headers
v2 behavior: Claude should also Edit the Findings section of state.md. Legacy backup: The hook auto-captures it to facts.md.
The .mci file is auto-generated by hooks as a safety net:
--- [PC] state.md Snapshot @ 14:30:00 ---
Memory: GOAL: Build the user filtering API with pagination support
Context: PROGRESS: - [x] Database schema designed\n- [x] GET endpoint working\n- [ ] Add filters
Intent: FINDINGS: Auth bypass found in middleware — blocks release until fixed
🛡️ In v2, you rarely need to think about .mci. The hooks handle it automatically by snapshotting state.md.
.claude-memory/
├── current-session ← pointer to active session
└── 📂 sessions/
└── 📂 2026-02-20/
├── 📂 session-1/
│ ├── 📝 state.md ← YOUR EXTERNAL BRAIN (v2 primary)
│ ├── 📄 facts.md ← 🔴 [!] legacy backup
│ ├── 📄 context.md ← 🟡 [*] legacy backup
│ ├── 📄 intent.md ← 🟢 [>] legacy backup
│ ├── 📄 memory.md ← 🔵 [i] entries + session log
│ ├── 🛡️ memory.mci ← auto-generated safety net
│ ├── 💾 compact-*.md ← conversation backups
│ └── 📊 session-summary.md ← tool stats, files modified
└── 📂 session-2/
└── ...
Plugin hooks are configured automatically via hooks.json. No manual setup needed.
📋 Click to see plugin hooks.json
{
"hooks": {
"SessionStart": [
{
"matcher": "startup|clear|compact",
"hooks": [{ "type": "command", "command": "node \"${CLAUDE_PLUGIN_ROOT}/scripts/session-start.js\"", "timeout": 30 }]
}
],
"UserPromptSubmit": [
{
"matcher": "",
"hooks": [{ "type": "command", "command": "node \"${CLAUDE_PLUGIN_ROOT}/scripts/prompt-capture.js\"", "timeout": 5 }]
}
],
"PreCompact": [
{
"matcher": "",
"hooks": [{ "type": "command", "command": "node \"${CLAUDE_PLUGIN_ROOT}/scripts/pre-compact.js\"", "timeout": 30 }]
}
],
"Stop": [
{
"matcher": "",
"hooks": [{ "type": "command", "command": "node \"${CLAUDE_PLUGIN_ROOT}/scripts/session-stop.js\"", "timeout": 30 }]
}
]
}
}For git-clone installs, the installer generates .claude/settings.local.json:
📋 Click to expand manual hook configuration
{
"hooks": {
"SessionStart": [
{ "matcher": "", "hooks": [{ "type": "command", "command": "bash \"$CLAUDE_PROJECT_DIR/.claude/hooks/session-start.sh\"" }] }
],
"UserPromptSubmit": [
{ "matcher": "", "hooks": [{ "type": "command", "command": "bash \"$CLAUDE_PROJECT_DIR/.claude/hooks/prompt-capture.sh\"", "timeout": 5 }] }
],
"PreCompact": [
{ "matcher": "", "hooks": [{ "type": "command", "command": "bash \"$CLAUDE_PROJECT_DIR/.claude/hooks/pre-compact.sh\"" }] }
],
"Stop": [
{ "matcher": "", "hooks": [{ "type": "command", "command": "bash \"$CLAUDE_PROJECT_DIR/.claude/hooks/session-stop.sh\"", "timeout": 30 }] }
]
}
}| Constant | Default | Purpose |
|---|---|---|
RESUME_TIMEOUT |
14400 (4 hours) |
Seconds before creating a new session |
SNAPSHOT_LOOKBACK_DAYS |
7 |
Days to search back for .mci recovery |
AUTO_CHECKPOINT_INTERVAL |
10 |
Prompts between auto-checkpoints |
CONTEXT_LIMIT |
1000000 |
Estimated JSONL bytes at compact |
WARN_BYTES |
700000 |
~70% — gentle checkpoint reminder |
CRITICAL_BYTES |
850000 |
~85% — strong save warning |
EMERGENCY_BYTES |
950000 |
~95% — save NOW |
| Template | Purpose |
|---|---|
📝 IDENTITY.md |
Personality and principles (system prompt addition) |
⚡ PREFERENCES.md |
Output style and communication preferences |
🆕 What changed in v2?
v1 used 4 append-only marker files (facts.md, context.md, intent.md, memory.md). The pre-compact hook only grabbed the LAST line from each file — losing everything else. Marker compliance was 3 entries in 45 sessions because the contract was too complex.
v2 replaces this with a single state.md file that Claude actively maintains using the Edit tool. Pre-compact snapshots the FULL content. No data loss. No complex marker contracts. Just keep one file current.
🤖 Does this work with Claude Code subagents?
The hooks run on the main session. Subagents don't trigger hooks directly, but the main session's state.md captures the overall flow.
📊 How much context does this use?
SessionStart injects ~500-800 tokens (identity + .mci + rules). This is a small fraction of the ~200K token context window.
💥 What if my terminal crashes?
state.md is on disk — it survives crashes. On next startup, SessionStart detects the crash, loads the .mci + state.md, and injects a CRASH RECOVERY block. Auto-checkpoints every ~10 prompts ensure .mci is also recent.
📅 What if I come back after the weekend?
The .mci cascade searches up to 7 days back. state.md from your last session is still on disk too.
🪟 Does this work on Windows?
Yes! Plugin hooks use Node.js (bundled with Claude Code) for full cross-platform support.
🔄 Is v2 backward compatible?
Yes! Legacy marker files (facts.md, context.md, intent.md) are still created and auto-populated. The fallback chain checks state.md first, then marker files, then JSONL. Users upgrading from v1 lose nothing.
Battle-tested over 100+ sessions spanning 2 months.
| Lesson | Detail |
|---|---|
| 📝 state.md > markers | v1's marker-to-file contract failed 97% of the time. v2's "just maintain one file" works naturally. |
| 🛡️ Multi-layer fallbacks | state.md → marker files → JSONL. Every layer catches what the previous one missed. |
| 🪶 Lightweight startup | Loading too much wastes context. The "drawer model" — load on demand — maximizes useful space. |
| 💎 state.md is sacred | It's the single most important file. Everything else is backup. |
| 🔄 Node.js over bash | Bash hooks failed on Windows. Node.js is cross-platform and bundled with Claude Code. |
| ⚡ Auto-checkpoint | Relying on Claude to save was unreliable. Auto-snapshotting state.md every ~10 prompts is the safety net. |
MIT — see LICENSE
- Breaking: Replaced append-only marker files with single
state.mdliving document - New:
state.mdwith Goal/Progress/Findings sections — Claude's external brain - New: Cross-platform support — Claude Code + Claude Cowork share the same state.md
- New: Pre-compact snapshots FULL state.md content (not just last line)
- New: 3-tier fallback: state.md → marker files → JSONL transcript
- New: Auto-checkpoint every ~10 prompts snapshots state.md to .mci
- New: state.md health monitoring in prompt-capture hook
- Improved: Post-compact recovery reads state.md directly — no data loss
- Improved: Markers simplified to display formatting + legacy auto-capture
- Backward Compatible: Legacy marker files still created and populated
- Plugin marketplace support
- 7-day .mci cascade for session recovery
- Crash detection and auto-recovery
- Cross-platform Node.js hooks
- Persistent state memory system
- 4 lifecycle hooks (SessionStart, UserPromptSubmit, PreCompact, Stop)
- Marker-to-file contract
- Session management with date-based directories
Issues and pull requests welcome!
🐛 Report Bug • 💡 Request Feature • ⭐ Star the Repo
Built with 🧠 by hlsitechio — giving Claude a memory it deserves.
