hive-memory
Officialby hivemem-dev
README.md
# hive-memory
MCP server for personal + shared memory that works with any MCP-compatible agent (Claude Code, Cursor, Codex CLI, ...). Personal entries are visible only to the agent that wrote them; shared entries are visible to every agent connected to the same project. Search is hybrid — SQLite FTS5 keyword matching fused with local, offline semantic search (see below) — ranked by past outcome (`success`/`failure`) and recall count.
Sixteen MCP tools: `memory_remember`, `memory_recall`, `memory_mark_outcome`, `memory_stats`, `memory_recall_recent`, `memory_correct`, `memory_touch`, `memory_link`, `memory_convention`, `memory_session_start`, `memory_session_end`, `memory_replay`, `memory_skill_save`, `memory_skill_match`, `memory_skill_score`, `memory_premortem`.
## Correcting, confirming, linking, conventions
- **`memory_correct`** fixes an existing entry's text in place (id from a prior recall) instead of leaving the wrong fact around and remembering a corrected duplicate next to it.
- **`memory_touch`** confirms an entry is still true/relevant right now without changing its text - resets its recall-ranking freshness.
- **`memory_link`** connects two entries with an optional relation label (e.g. `caused-by`, `supersedes`). Linked entries show up as indented `-> `/`<- ` lines under either entry whenever it's recalled.
- **`memory_convention`** stores a project rule/standard (`type=convention`) instead of a one-off fact. Conventions always sort first in `memory_recall` and `memory_recall_recent`, regardless of recency or decay - they don't stop being true just because nobody hit them last week.
## Session replay, skills, premortem
- **`memory_session_start` / `memory_session_end` / `memory_replay`.** The Claude Code adapter calls `memory_session_start` on `SessionStart` and `memory_session_end` (with a summary of the last assistant message) on `Stop`, keyed by Claude Code's own `session_id`. `memory_replay` returns a recap of the most recently *finished* session - the in-progress one is naturally excluded since it has no end time yet. `context-inject.js` calls this automatically and prepends the recap to the session-start context, ahead of the usual recent-memories bullet list.
- **`memory_skill_save` / `memory_skill_match` / `memory_skill_score`.** Skills are named, reusable task recipes (a "how to do X" procedure) stored separately from one-off facts, with a running success rate. Saving under an existing name updates that recipe instead of creating a near-duplicate. Matching ranks by success rate (`times_succeeded / times_used`) first.
- **`memory_premortem`.** Given a short description of an action about to be taken, searches memory the same way `memory_recall` does but returns only the two kinds of rows that represent real risk: past `outcome=failure` entries and `type=convention` rules relevant to that action. General facts (successes, unknowns) are filtered out - this tool is specifically "what could bite me here," not "what do I know about this."
## Semantic recall
`memory_recall` combines two search methods and merges them with reciprocal rank fusion, so a fact surfaces whether the query shares its exact words or just its meaning:
- **Keyword (FTS5)** — exact/prefix word matches, same as before.
- **Semantic (local embeddings)** — [@huggingface/transformers](https://www.npmjs.com/package/@huggingface/transformers) running `onnx-community/embeddinggemma-300m-ONNX` fully on-CPU/offline. No API key, no per-call cost — only a one-time ~1.2GB model download on first use (cached under `node_modules/@huggingface/transformers/.cache`). Chosen over the smaller `Xenova/all-MiniLM-L6-v2` (previously used) specifically for Russian: measured 70% vs 30% top-5 hit rate on a clean benchmark - see CHANGELOG 0.6.0. Switching `EMBEDDING_MODEL` in `db.js` auto-invalidates old stored vectors on next start (see `meta` table), so mixing models never silently corrupts similarity scores.
This only runs in the long-lived MCP server session (the one wired into the agent's `mcpServers` config) — the hook-capture path (`adapters/*/capture.js`) spawns a fresh process per event and sets `HIVE_MEMORY_LIGHTWEIGHT=1` to skip embedding there, so hook latency is unaffected. Any backlog of un-embedded rows (legacy entries, or ones written through the lightweight path) gets embedded lazily the next time `memory_recall` runs.
If the model can't load (e.g. no internet on first run), recall falls back to keyword-only search instead of failing.
**Reranking.** After keyword+semantic fusion produces a rough top pool, a second model (`RERANKER_MODEL` in `db.js`, `tss-deposium/bge-reranker-v2-m3-onnx-int8`, ~560MB) scores the query against each candidate directly and re-sorts before the pool is cut down to the requested `limit`. This is slower per call than the fusion step alone but meaningfully more accurate - measured on this installation's real data, it scored the correct past answer at 0.999 vs -9.5 to -10.6 for unrelated candidates. Falls back to the fusion order unchanged if the reranker can't load.
## Quick start
```bash
# 1. install
./install.sh
# 2. connect to your agent — install.sh prints the exact JSON block to paste
# into ~/.claude.json under "mcpServers" (or the equivalent config for
# Cursor / Codex CLI, see adapters/)
# 3. verify: from Claude Code, ask it to call memory_stats — should return
# { "total": 0, "byScope": [], "latest": undefined } on first run
```
The database file is created automatically on first run of `server.js` (see `db.js`), at the path given by `HIVE_MEMORY_DB` (default `./hive-memory.db`).
## Adapters
`adapters/` wires the server into specific agents. Each adapter is a thin capture layer — no storage/search logic lives there, it only calls this server's existing MCP tools.
- `adapters/claude-code/` — hooks.json + capture.js (SessionStart, UserPromptSubmit, PostToolUse, Stop)
- `adapters/cursor/` — hooks.json + capture.js (beforeSubmitPrompt, afterShellExecution, afterFileEdit, stop)
- `adapters/codex/` — README only; MCP-compatible, connects to `server.js` directly, no hooks needed
## CLI
`cli.js` is the only thing that writes to an agent's config. It's explicit and human-triggered — no automatic edits happen anywhere in this project.
```bash
node cli.js status
# Agent Installed Attached
# Claude Code found attached
# Cursor found not attached
# Codex not found -
node cli.js attach cursor # writes ~/.cursor/hooks.json for real
node cli.js attach all # attaches every installed agent, skips the rest
```
## Auto-attach watcher
`watcher.js` detects installed agents and tells you what to run — it does not silently edit your config files. Event-driven via `fs.watch` (no polling, near-zero idle CPU): it wakes up when an agent's config dir/file appears or changes, checks (read-only) whether hive-memory is already attached, and if not, prints a one-line notice pointing at the `cli.js attach` command to run.
```bash
node --max-old-space-size=64 watcher.js
# [hive-memory] Found Cursor at ~/.cursor/hooks.json - not yet attached. Run: node cli.js attach cursor
# or in the background, this server's usual pattern:
screen -dmS hive-memory-watcher node --max-old-space-size=64 watcher.js
```
## Environment variables
See `.env.example`: `HIVE_MEMORY_AGENT`, `HIVE_MEMORY_PROJECT`, `HIVE_MEMORY_DB`.
**Set `HIVE_MEMORY_PROJECT` explicitly if you want one stable memory scope.** If unset, the Claude Code/Cursor hook adapters fall back to the hook event's current working directory - fine if each of your projects is its own repo/cwd, but if a session ever `cd`s elsewhere (a subprocess, a temp folder, a nested app dir), that becomes a brand-new, disconnected memory bucket. Pin `HIVE_MEMORY_PROJECT` in your hook commands and in your MCP server's `env` (must match) to keep everything under one project regardless of cwd drift.
## Objective verify (with hive-memory vs without)
```bash
node cli.js verify [--project X] [--agent X] [--sample N] [--k N]
```
Builds a ground-truth test set automatically from real history - every captured `UserPromptSubmit` that's a real question, paired with whichever `Stop` row answered it before the next question was asked - then re-asks each question as a `memory_recall` query and checks whether the real past answer comes back in the top-K. Reports the hybrid-search hit rate as shipped, the same search restricted to `key='Stop'` rows only (a diagnostic ceiling), and a bare chronological recent-N dump (the closest thing to "no real retrieval"). No memory at all is 0% by construction. See CHANGELOG for the measured history: 3% → 33% after switching embedding models, excluding raw prompt/tool-call rows from being recall results, fixing the benchmark's own fixture pairing, and adding a reranker.
## Tests
```bash
npm test
```
Runs `node --test --test-concurrency=1 tests/*.test.js`. Concurrency is pinned to 1 on purpose - the embedding model (~1.2GB) and reranker (~560MB) both get loaded fresh per spawned `server.js` process, and running many test files in parallel (Node's default) can exceed available RAM on a modest VPS and get processes OOM-killed mid-test. Slower (~90s vs ~45s), but reliable.
This server cannot be deployed
Maintenance
ActivitySlowing
ResponsivenessNo issues