Skip to main content
Glama
README.md
<!-- mcp-name: io.github.mordechaipotash/brain-mcp -->

# brain-mcp — the recorder for your AI conversations

**Your AI history is being deleted right now.** Claude Code deletes session files older
than `cleanupPeriodDays` (default **30**) at startup. Run this and see your own cliff edge:

```bash
# macOS
find ~/.claude/projects -name '*.jsonl' -exec stat -f '%Sm  %N' -t '%Y-%m-%d' {} + | sort | head -3
# Linux
find ~/.claude/projects -name '*.jsonl' -printf '%TY-%Tm-%Td %p\n' | sort | head -3
```

The oldest date you see is where your history ends. brain-mcp records it before it goes —
the whole session, subagent transcripts and saved tool output included, byte-exact,
content-hashed, locally — makes it queryable with citations you can verify with `sed` and
`shasum`, tells you what was deleted, and puts it back.

## If Claude Code deleted it

```bash
brain-mcp health          # the receipt: "3 session(s) and 41 file(s) are gone from where the
                          #   agent kept them; the floor holds every one" — each re-hashed
                          #   against the manifest when the recorder first noticed it
brain-mcp restore --list  # what can be put back
brain-mcp restore <id>    # writes the session (and its folder) back, byte-exact, then:
                          #   cd <its working directory> && claude --resume <id>
```

`restore` never overwrites different bytes (identical bytes are a no-op), is all-or-nothing,
and takes `--dry-run` and `--to <dir>`. It is a CLI verb only — no MCP tool writes outside
the floor.

## Install

```bash
pipx install brain-mcp           # or: uvx brain-mcp
brain-mcp install cc             # CC hooks + 60-second scheduler
brain-mcp serve                  # the MCP server (stdio) — add to your client config
```

Or as a Claude Code plugin (hooks + server in one step):

```
/plugin marketplace add mordechaipotash/brain-marketplace
/plugin install brain
```

## What it does

- **Captures at source.** Claude Code via Stop/SessionEnd hooks (line-deltas + a final
  snapshot); Codex, Pi, and everything inside a Claude Code session's own folder (subagent
  and workflow transcripts, `.meta.json`, `tool-results/`) via a 60-second poll-scan. One
  spool, one floor.
- **Keeps the bytes.** The floor is `~/.brain/lake/<lane>/<session>.jsonl` — append-only,
  byte-identical to the original, with an append-only sha256 manifest. Nothing is parsed
  and discarded; the DuckDB index is a cache, fully re-derivable from the lake.
- **Cites or abstains.** Every search hit carries `{file, line span, sha256}` — checkable
  by anyone with `sed -n 'A,Bp' file | shasum -a 256`, no database required. Zero hits
  return an explicit abstention naming the lanes and dates actually searched.
- **Reports health honestly.** `fresh` = the floor holds everything the agent's files show;
  `stale` = the agent has content the recorder missed; **`unknown` = unmeasured, not
  healthy** — never folded into "looks fine".
- **Backs up verifiably.** `brain-mcp backup <dest>` syncs lake+manifest and re-hashes
  sampled files at the destination. The verify can fail; that is the point.
- **One network fetch, ever, and it is not about you.** No telemetry, no cloud, no
  accounts, and no HTTP client in this package. The exception: DuckDB downloads its
  full-text-search extension (`fts`) from DuckDB's own extension repository the first time
  the index is built, and caches it under `~/.duckdb`. `brain-mcp install` does that fetch
  up front and says so; `brain-mcp doctor` reports whether it is cached.

## The 7 MCP tools

| tool | what |
|---|---|
| `brain_search` | BM25 over everything recorded; cited hits or an explicit abstention |
| `brain_get` | the raw lines behind a citation, with sha verification |
| `brain_recent` | time-ordered recent activity, every row cited |
| `brain_sessions` | session cards per day/agent |
| `brain_health` | per-lane origin-vs-floor freshness (unknown ≠ healthy), plus the receipt of what the agents deleted |
| `brain_capture_status` | is the machinery itself moving (spool, heartbeats, floor) |
| `brain_backup` | verified backup; writes only outside the floor |

## 🤖 For AI Assistants

*You're reading this because your human runs THE RECORDER and gave you access to their
AI history. This is the honesty contract.*

**The one rule: everything you state from these tools is either CITED or ABSTAINED —
there is no third state.** A cited claim carries a checkable pointer (file + line span +
sha256); verify it with `brain_get(expect_sha256=...)` before building on it. An
abstention means "not found above threshold in the lanes and dates the tool measured" —
it does NOT mean "it never happened". Never fill an abstention with your own guess.

- Present recall as their words, dated: *"On 2026-08-19 you wrote: '…' (sess-7f2a.jsonl:412)"* —
  never as your own knowledge. One claim, one citation.
- `verified: false` from brain_get means the floor changed since indexing. Say so plainly.
- A health response containing any `unknown` lane is never "everything looks fine".
  The honest sentence is: "2 lanes fresh, 1 stale, 1 unmeasured."
- "What do I think about X" → `brain_search(query, role="user")`. That returns what the
  PERSON wrote: text the harness injected under the user role (skill bodies, reminders,
  slash-command wrappers, compaction summaries, Codex context blocks — a quarter to two
  thirds of "user" rows, measured) is excluded unless you pass `include_machine=True`, and
  subagent transcripts unless `include_subagents=True`. "How did my thinking evolve" → add
  `order="time_asc"`; bound it with `since` / `until`. The server has no opinion about your
  human's mind; it has their words, with receipts.

## The floor format

```
~/.brain/
  spool/<lane>/                 hooks + scanner write here (atomic, dot-tmp invisible)
  lake/<lane>/<session>.jsonl   THE FLOOR: append-only, byte-identical to the origin;
                                a rewrite opens <session>.g2.jsonl — old kept, never deleted
  lake/cc_sessiondir/<project>/<session>/...   a CC session's folder, mirrored at the
                                same relative paths (subagents/, tool-results/, *.meta.json)
  manifest/manifest.jsonl       one versioned line per chunk: byte range, line range, sha256
  offsets/<lane>/<session>      hook fast-path line counters
  health/*.last_run             side-effect heartbeats (mtimes are the proof, never a report)
  brain.duckdb                  the index — a cache, re-derivable from lake/ + manifest/
```

Where your agents keep their transcripts: Claude Code `~/.claude/projects/**/*.jsonl`
(rolling window!), Codex `~/.codex/sessions/YYYY/MM/DD/rollout-*.jsonl`, Pi
`~/.pi/agent/sessions/**/*.jsonl`.

## Other verbs

```bash
brain-mcp record                  # one capture tick (the scheduler runs this every 60s)
brain-mcp health [--exit-nonzero-on-stale]   # cron-able
brain-mcp doctor                  # capture status, health, fts cache, the receipt, runaway generations
brain-mcp restore [<id>] [--list] [--to DIR] [--dry-run]   # put a deleted session back
brain-mcp redact <file> --lines A B --reason "..."   # tombstone a secret; audited in manifest
brain-mcp migrate-v1 <all_conversations.parquet>     # import v1 data (marked v1_derived)
brain-mcp uninstall               # removes hooks + scheduler; your floor is KEPT
```

## v1 → v2

v2 is a rebuild around one principle: **capture the bytes first; derive everything else.**
v1 parsed conversations into a parquet and discarded the originals — v2's floor makes that
structurally impossible. v1's 25 tools became 7: the synthesis tools ("cognitive patterns",
"switching cost") are gone because a claim that can't carry a line-span citation isn't one
this server makes. Migration: `brain-mcp migrate-v1` — v1 rows are kept, marked as derived,
and floor-backed rows win wherever the source still exists.

Windows: out of scope for v2.0. Scheduling is LaunchAgent (macOS) / systemd user timer (Linux).

MIT.

TDQS

A3.5/5.0

Scored across 25 tools

Disambiguation4/5

Tools are largely distinct, with clear descriptions differentiating similar ones (e.g., search tools target different sources). Some potential confusion between 'open_threads' and 'unfinished_threads' but descriptions clarify.

Naming Consistency4/5

All tool names use snake_case and follow a verb_noun or noun phrase pattern consistently. Minor variation in style (e.g., 'brain_stats' vs 'get_conversation') but still very readable.

Tool Count4/5

25 tools is on the high side but appropriate for the broad scope of personal knowledge management (search, stats, analytics, principles, threads, etc.). Each tool earns its place.

Completeness5/5

Coverage is comprehensive for the stated purpose: searching, retrieving, analyzing, and introspecting on a personal knowledge base. No obvious gaps given the read-heavy, analysis-oriented domain.

Maintenance

ActivityMaintained
ResponsivenessUnresponsive