A persistent memory system for Claude Code that gives it real continuity across sessions, machines, and conversations.
This isn't a library you install. It's a system design — a collection of tools, scripts, hooks, and conventions that work together to make Claude Code remember who you are, what you're working on, and what it learned last time. Adapt it to your setup.
Out of the box, Claude Code starts every session with amnesia. It doesn't know your name, your preferences, your project history, or what you did yesterday. This framework fixes that.
- Session continuity —
/catchuploads full context at session start,/wrapupsaves everything at the end - Hybrid associative recall — Synapse combines FTS5 keyword search, graph spreading activation, and local semantic embeddings (fused with Reciprocal Rank Fusion) — not just keyword matching
- Auto-capture — Hooks automatically save failures and important info as you work, without you asking
- Multi-machine sync — Git-backed memory repo works across any machine with Claude Code
- Memory consolidation —
/dreamfinds duplicates, contradictions, and stale info, then fixes them - Bi-temporal truth — facts that change are superseded, not overwritten; you can ask "what was true as of date X"
- Verification trust signals — facts carry a "last checked against reality" stamp, so a cold-start session knows what to trust vs. re-verify
- Project board — project status lives in each project file's frontmatter; the ranked priority board is generated, never hand-maintained
- Observability — a health tool + daily timers watch memory freshness, embedding coverage, and backup integrity
- Decay and relevance — memories that aren't accessed fade naturally, keeping retrieval sharp
You type a prompt
|
v
[UserPromptSubmit hook] --> Synapse auto-recall (pulls related memories)
|
v
[Claude Code responds] --> uses memory context + your instruction
|
v
[PostToolUseFailure hook] --> auto-captures failed commands as lessons-learned
|
v
[/wrapup at end] --> saves session state, pushes to git, syncs Synapse
|
v
[Next session /catchup] --> pulls latest, reads context, health checks
| Layer | What | Where |
|---|---|---|
| Auto-memory | YAML-frontmatter markdown files Claude creates automatically | ~/.claude/projects/*/memory/ |
| Claude-Memory repo | Git repo with machine files, project context, knowledge base | ~/claude-memory/ |
| Synapse | MCP server with SQLite + FTS5 + graph relationships | ~/claude-memory/synapse/ |
| STATUS.md | Session log — what happened, what's pending | ~/claude-memory/STATUS.md |
| CLAUDE.md | Global instructions loaded every session | ~/.claude/CLAUDE.md |
Every auto-memory file has YAML frontmatter with a type field:
| Type | Purpose | Example |
|---|---|---|
user |
Who you are, your role, your skills | "Senior dev, prefers Python, uses Neovim" |
feedback |
How Claude should behave | "Don't use snap. Explain commands." |
project |
Active work context (carries status: / last_worked:) |
"Building an Android app, Phase 2" |
reference |
Things to look up | "Server IP, API keys, equipment defaults" |
fact |
A durable fact worth keeping | "The prod DB is Postgres 16 on the LAN host" |
decision |
A choice and its reasoning | "Chose authentik over Auth0 — self-hosted, no per-MAU cost" |
error |
A failure and its lesson (auto-captured) | "tailscale up re-run invalidates the pending auth URL" |
The current file format uses name + description + a metadata: block (holding
type and, for projects, status: / last_worked:). See
templates/memory-example.md for the exact schema and the [[wiki-link]] convention
that ties related memories together.
The brain. A Python MCP server that provides graph-enhanced memory to Claude Code and (optionally) claude.ai web.
How it works:
- Stores memories in SQLite with FTS5 full-text search
- Builds a relationship graph between memories (
related_to,depends_on,part_of, etc.) - Hybrid retrieval fuses three arms with Reciprocal Rank Fusion: FTS5 keyword match, graph spreading activation, and semantic similarity from local embeddings (
nomic-embed-textvia Ollama — CPU, fully private, no API calls), then blends recency + importance + verification signals on top - Spreading activation walks the graph from seed nodes, finding related memories that keyword search would miss
- Bi-temporal: superseding a fact retires the old value (hidden from normal recall) but keeps it answerable via
as_oftime-travel queries - Memories decay based on type — facts decay slower than project notes
- Idempotent + guarded writes: a write ledger dedups re-saves; a write-time secret scanner refuses to store credentials
The algorithm is based on Collins & Loftus (1975) spreading activation, adapted for LLM memory following Park et al. (2023) Generative Agents scoring, with a semantic-embedding arm fused by Reciprocal Rank Fusion (Cormack et al. 2009).
Tools exposed (13):
| Tool | What it does |
|---|---|
synapse_remember |
Store a memory |
synapse_recall |
Hybrid search (keyword + graph + semantic + recency); supports as_of time-travel |
synapse_connect |
Create/strengthen a relationship between two memories |
synapse_verify |
Stamp a fact as just-confirmed-true against reality (trust signal) |
synapse_supersede |
Replace a changed fact, keeping the old value as history |
synapse_forget |
Delete a memory (destructive — confirm first) |
synapse_neighbors |
Traverse the graph from a node |
synapse_import |
Bulk-import markdown memory files |
synapse_stats |
Database statistics |
synapse_projects |
The ranked project board (from project_*.md frontmatter) |
synapse_health |
Brain health snapshot — counts, embedding coverage, freshness, backups |
synapse_catchup |
Full session-start briefing (stats + STATUS.md + board + recent) |
synapse_wrapup |
Persist an end-of-session summary to the brain |
Plus 4 MCP prompts (surface as slash commands in claude.ai web): Catchup, Recall Now, Checkpoint, Wrapup. The Catchup prompt and synapse_catchup tool share one canonical briefing function, so every interface returns identical output.
Setup:
cd synapse/
python -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
# Optional but recommended — the semantic recall arm (local, private):
# install Ollama, then: ollama pull nomic-embed-text
# Without it, recall gracefully falls back to keyword + graph only.
# Register with Claude Code
claude mcp add --scope user synapse -- \
/path/to/synapse/.venv/bin/python -m synapse.synapse_mcpHooks that fire at key moments in a Claude Code session:
| Hook | Event | What It Does |
|---|---|---|
| SessionStart | Session begins | Injects context (machine, date, alerts) |
| UserPromptSubmit | Every prompt | Synapse auto-recall — searches for related memories |
| PreToolUse | Before tool runs | Notifications (optional) |
| PostToolUse | After a successful Bash/Write/Edit | Logs; file-change breadcrumbs are suppressed by design (they were ~47% noise) |
| PostToolUseFailure | After a failed tool call | Captures failed Bash commands as error memories — the real auto-capture signal |
| PreCompact | Before context compression | Saves work, sends notification |
| PostCompact | After compression | Re-injects critical context |
| Stop | Session ends | Checks for uncommitted work |
See hooks/settings-template.json for the full configuration. The key hooks are UserPromptSubmit (makes every prompt memory-aware) and PostToolUseFailure (captures failures as lessons-learned). A note on the latter: PostToolUse does not fire on failure and does not carry an exit code — so failure capture requires the separate PostToolUseFailure event. Getting this wrong silently disables auto-capture; the hook logs every invocation to ~/.synapse-hook.log so a breakage is visible within a day.
Three slash commands that manage the session lifecycle:
/catchup— Start of session. Pulls latest from git, reads context files, health-checks configs, summarizes what happened last time./wrapup— End of session. Audits the entire conversation for unsaved info, updates STATUS.md with session notes, commits and pushes everything./dream— Memory consolidation. Scans all memory files for duplicates, contradictions, stale dates, missing frontmatter. Fixes issues and syncs to Synapse.
/catchup also pulls the ranked project board from synapse_projects (generated from each project file's status: / last_worked: frontmatter) instead of reciting a hand-maintained priority list — so the priorities never drift from the source of truth.
These are in skills/ as templates. They're designed to be customized for your infrastructure — add your server checks, your repo list, your health checks.
auto-memory-backup.sh— Commits and pushes auto-memory files to a private backup server. Skips gracefully if the server is unreachable.statusline-command.sh— Custom Claude Code status line showing hostname, model, context usage, git branch, cost, and duration.
Research and reference material that informed the system design:
research-foundations.md— 20+ academic papers on memory, retrieval, and LLM agentsanti-patterns.md— What NOT to do (stuffing CLAUDE.md, unbounded accumulation, etc.)lessons-learned.md— Real incidents and what they taught ushooks-reference.md— Complete reference for all 26 Claude Code hook eventsmemory-tools-landscape.md— Evaluation of every Claude Code memory tool we foundcommunity-insights.md— Best practices from the Claude Code community
Out of the box this framework is local-first: Synapse runs on one machine over stdio, hooks talk to the local SQLite DB, and everything works with zero network setup. That's the right starting point and covers most use.
If you want the same brain reachable from multiple machines — a laptop, a phone, and claude.ai web all reading and writing one memory DB — you run Synapse as a long-lived service on one host (a "memory host") and reach it two ways:
- Local / tailnet writes — a lightweight HTTP endpoint (
/hook/*) that the hooks POST to. Fast, on your private network, gated by a shared secret. No OAuth. - Public reads/writes — an OAuth-gated MCP endpoint (
/mcp) that claude.ai's custom-connector feature can authenticate against.
This repo ships the local-first code only. The remote serving layer
(serve.py, an OIDC middleware, the /hook/* API) is intentionally not
included — it's tightly coupled to a specific auth provider and reverse-proxy
setup, and shipping half-generic infra code does more harm than good. Instead,
here is the pattern, which is the part worth having; build your own from it
with any OIDC provider and reverse proxy.
The architecture:
(public internet)
claude.ai web ──────────────► reverse proxy (TLS) ──► Synapse /mcp
│ OAuth: /authorize + /token
▼
OIDC provider (self-hosted or SaaS)
laptop / phone hooks ──► tailnet / VPN ──► Synapse /hook/* (shared secret)
The hard-won details (these are what cost real debugging time):
-
Behind CGNAT, port-forwarding is dead. Many home ISPs (especially 5G/LTE home internet) put you behind carrier-grade NAT — you have no forwardable public port. A tunnel that originates outbound from the host (e.g. Tailscale Funnel, Cloudflare Tunnel,
ngrok) is how you expose the service anyway. This is often the difference between "connector works" and "connector times out." -
claude.ai does the full OAuth 2.1 authorization-code + PKCE dance. Its custom-connector hits
GET /authorizeandPOST /tokenon your origin, plus reads/.well-known/oauth-authorization-server. If your reverse proxy doesn't explicitly front those paths and bridge them to your OIDC provider, the connector shows a "connected" badge but never actually authenticates — every real request fails, silently. Make sure the proxy maps/authorize,/token, and the authorization-server metadata to the provider, and log them so you can confirm a real login happened (look for the token exchange returning200, not the badge). -
Verify from evidence, not the UI. A connector "connected" state is not proof. Confirm with the provider's own login/authorize events and a live tool call that returns real DB data (e.g.
synapse_statsreturning your actual memory count). -
Keep the hardening; decouple the writes. If the public service is sandboxed (read-only filesystem except its own dir), don't loosen it to let a tool write your
STATUS.md+git push. Instead have the tool drop a JSONL line in its one writable dir, and run a separate, unsandboxed drain (a file-watch → shell script as your user) that appends + pushes. Thesynapse_wrapuptool in this repo already writes that JSONL queue; the drain unit is yours to add. This keeps the internet-facing surface locked down while still getting server-side session logging.
git clone https://github.com/YOUR_USERNAME/claude-brain-framework.git ~/claude-memorycd ~/claude-memory/synapse
python -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
# Register with Claude Code
claude mcp add --scope user synapse -- \
~/claude-memory/synapse/.venv/bin/python -m synapse.synapse_mcpClaude Code's auto-memory lives at ~/.claude/projects/*/memory/. Create a MEMORY.md index file there — see templates/MEMORY-template.md for the format.
Copy hooks/settings-template.json to ~/.claude/settings.json. Search-replace the placeholder paths with your actual paths:
CLAUDE_MEMORY_DIR-> your claude-memory repo pathSYNAPSE_VENV-> your Synapse venv path
Copy templates/CLAUDE-template.md to ~/.claude/CLAUDE.md. Fill in your details — name, role, preferences, key directories, credentials (this file is local-only, never pushed to GitHub).
Copy the files from skills/ to ~/.claude/commands/:
cp skills/catchup.md ~/.claude/commands/
cp skills/wrapup.md ~/.claude/commands/
cp skills/dream.md ~/.claude/commands/Customize them for your setup — add your servers, repos, and health checks.
/catchup
This system was built iteratively over 180+ sessions of daily Claude Code use, starting from zero in January 2026. It wasn't designed upfront — it evolved from solving real problems: losing context between sessions, forgetting decisions, repeating mistakes, not knowing what machine we were on. Nearly every capability in it (semantic recall, bi-temporal supersession, verification stamps, the generated project board, failure auto-capture) exists because the simpler version broke in a way worth fixing for good.
The research that shaped this system:
Core Design Principles:
- Park et al. (2023) — Generative Agents (Stanford, UIST 2023). The retrieval scoring formula (recency + importance + relevance) directly inspired Synapse's hybrid search. The reflection/consolidation cycle inspired
/dream. - Collins & Loftus (1975) — "A Spreading-Activation Theory of Semantic Processing" (DOI). The spreading activation algorithm in
activation.pyis a direct implementation of this model. - Ebbinghaus (1885) — "On Memory." The forgetting curve. Synapse's time-based decay is Ebbinghaus applied to LLM memory.
- Anderson (1983) — ACT-R cognitive architecture. The idea that memory strength = base-level activation + associative activation.
- Cormack et al. (2009) — "Reciprocal Rank Fusion Outperforms Condorcet and Individual Rank Learning Methods" (SIGIR 2009). How Synapse fuses the keyword, graph, and semantic-embedding result lists into one ranking without tuning per-arm score weights.
LLM Memory Systems:
- Shinn et al. (2023) — Reflexion (NeurIPS 2023). Verbal self-reflection as memory. The lessons-learned pattern in this framework comes from Reflexion's insight that agents learn better from their own verbal failure analysis.
- Zhong et al. (2023) — MemoryBank. First to apply Ebbinghaus-style decay to LLM memory with timestamps and access counts.
- Packer et al. (2023) — MemGPT/Letta. Self-managed memory with the LLM as its own memory controller.
- Sumers et al. (2023) — CoALA. Cognitive architecture framework that maps episodic/semantic/procedural memory to LLM agents.
- Lewis et al. (2020) — RAG (NeurIPS 2020). The paper that named Retrieval-Augmented Generation.
Tools and Community:
- Claude Code by Anthropic — the CLI that makes all of this possible
- MCP (Model Context Protocol) — the protocol Synapse uses to talk to Claude Code
- Claude Code community on Reddit (r/ClaudeAI) — patterns like block-on-compact, progressive disclosure, and confidence decay came from community discussions
- FastMCP — the Python MCP SDK that Synapse is built on
This is a real system built by a real person (fire alarm tech, self-taught developer) using Claude Code daily for work and personal projects. It was vibe-coded — built iteratively by describing what I wanted and working with Claude to make it happen. The code works, the architecture is sound, and it's been battle-tested across 180+ sessions on multiple machines and interfaces (Claude Code CLI, mobile, and claude.ai web).
It's not a polished product. It's a framework you adapt. The value isn't in running it as-is — it's in understanding the patterns and building your own version.
claude-brain-framework/
|-- synapse/ # MCP memory server
| |-- synapse_mcp.py # FastMCP entry point (13 tools + 4 prompts)
| |-- db.py # SQLite + FTS5 storage, bi-temporal, verification
| |-- activation.py # Spreading activation algorithm
| |-- search.py # Hybrid retrieval (keyword + graph + semantic, RRF)
| |-- embeddings.py # Local semantic embeddings (Ollama, private)
| |-- reranker.py # Optional cross-encoder re-rank (off by default)
| |-- quality.py # Per-type importance / decay weighting
| |-- sync.py # Markdown import + graph building
| +-- requirements.txt
| # NOT shipped: serve.py / oauth_middleware / hook_api / client — the remote
| # serving layer. See "Advanced: Remote / Multi-Device Access" for the pattern.
|-- hooks/ # Claude Code hook scripts (local-mode)
| |-- settings-template.json
| |-- post_tool_capture.py # PostToolUse + PostToolUseFailure
| +-- auto_recall.py
|-- scripts/ # Utility scripts
| |-- auto-memory-backup.sh
| +-- statusline-command.sh
|-- skills/ # Slash command templates
| |-- catchup.md
| |-- wrapup.md
| +-- dream.md
|-- templates/ # Starter files
| |-- CLAUDE-template.md
| |-- MEMORY-template.md
| |-- machine-template.md
| +-- memory-example.md
+-- knowledge/ # Research and reference
|-- research-foundations.md
|-- anti-patterns.md
|-- lessons-learned.md
|-- hooks-reference.md
|-- memory-tools-landscape.md
+-- community-insights.md
MIT License. Use it, fork it, adapt it. Credit appreciated but not required.
If you build something cool with it, open an issue and tell me about it.