An engram is the hypothetical physical trace of memory in neural tissue — the biochemical change that encodes what we've learned.
Local-first cognitive memory system that transforms raw LLM conversation history into structured, consolidated knowledge. Unlike traditional conversation search (which treats sessions as documents to retrieve), Engram mimics human memory architecture: episodic memories are captured, consolidated into semantic knowledge during "dream state" processing, and emergent connections surface through graph analysis — much like how a Zettelkasten's backlinks reveal Maps of Content that no individual note anticipated.
Designed as an MCP server for Claude Code and other LLM agents, with CLI and web visualization interfaces.
Prerequisites
- Node.js 22 or newer (
node --version) - macOS or Linux (the optional launchd daemon is macOS-only; everything else is portable)
- Claude Code if you want
engram syncto ingest your conversation history from~/.claude/projects - At least one LLM provider for extraction and dream consolidation (see Configuration). Search,
remember, and the web visualizer work without one.
git clone https://github.com/devinmlowe/engram.git
cd engram
npm install # also runs the TypeScript build via the "prepare" script
npm link # puts `engram` on your PATH (or run `node dist/interfaces/cli/index.js` directly)
engram init # creates ~/.local/share/engram/engram.db and downloads the embedding model
engram sync # index conversations from ~/.claude/projects (optional)
engram search "what did I decide about caching"Heads up: first run downloads models.
engram init, the first search, and the test suite pullnomic-ai/nomic-embed-text-v1.5(embeddings) andXenova/bge-reranker-base(reranker) from Hugging Face — several hundred MB in total — into the@xenova/transformerscache undernode_modules/. This happens once; later runs are offline. SetENGRAM_RERANK_ENABLED=falseto skip the reranker model.
Use it from Claude Code (MCP)
Add the server to your Claude Code MCP config (~/.claude.json, or a project-level .mcp.json),
pointing at the compiled server with an absolute path:
{
"mcpServers": {
"engram": {
"command": "node",
"args": ["/absolute/path/to/engram/dist/interfaces/mcp/server.js"],
"env": {}
}
}
}The .mcp.json shipped in this repo does the same thing with a repo-relative path and is picked
up automatically when you open the engram checkout itself in Claude Code.
Optional: background consolidation (macOS)
./scripts/install-daemon.sh install # nightly `engram dream` at 02:00 via launchd
./scripts/install-visualizer.sh install # keep the web visualizer running on http://127.0.0.1:3001Engram is a cognitive system — it extracts meaning, consolidates patterns, detects contradictions, and surfaces emergent connections. Raw conversations are the input, not the output.
Memory injection must be surgical. Retrieved memories are capped within caller-specified token budgets, formatted for primacy placement, and delivered via progressive disclosure — pointers first, full content only on request.
Like a Zettelkasten, the value is in the connections. Opportunistic bidirectional linking, Maps of Content emerging from graph density, and the dream state daemon acting as the librarian who notices patterns across the collection.
All processing runs locally. No cloud dependencies except optional API calls for extraction/summarization (replaceable with local models via Ollama for true offline operation).
Four domains with shared core infrastructure:
episodic/— Conversation archive ingestion, indexing, and episodic searchsemantic/— Knowledge extraction, consolidation, adaptive chunking, and semantic searchgraph/— Entity/relationship graph, topic clusters, file structure indexing, and graph traversaldream/— Autonomous consolidation pipeline (ingest → extract → consolidate → reflect → prune)interfaces/— CLI, MCP server, and web visualization_core/— Shared infrastructure (config, db, types, embeddings, search, llm, cache)decisions/— Architecture Decision Records
14 tools for LLM agent memory operations:
| Tool | Purpose |
|---|---|
recall |
Hybrid search (vector + FTS5 + graph) with token budget |
remember |
Store a single memory (fact, decision, pattern, etc.) |
show |
Retrieve full conversation or memory context |
explore |
Fixed-depth graph traversal from an entity |
reflect |
Graph analysis — communities, bridges, temporal patterns |
recall_session |
Stateful iterative search with session tracking and budget |
recall_drill |
Deep drill into a specific search result with budget deduction |
explore_selective |
Model-directed selective graph traversal with relevance filtering |
remember_batch |
Batch memory ingest with entity linking and adaptive chunking |
fetch_snippets |
Multi-range file snippet fetching (up to 20 ranges) |
index_file_structure |
Parse file structure into graph entities (multi-language) |
scan_file |
Regex-based file scanning with function context detection |
commitments |
List tracked commitments (promises, intentions, follow-ups owed by others) — overdue first |
commitments_update |
Mark a commitment done, dropped, or superseded |
dist/interfaces/mcp/server.js speaks stdio by default, which is what the
.mcp.json example in "Install & first run" uses. Start it with --http to
serve Streamable HTTP instead:
node dist/interfaces/mcp/server.js --http # http://127.0.0.1:9907/mcp
node dist/interfaces/mcp/server.js --http --port 9910HTTP mode exposes POST /mcp (one MCP session per client, routed by the
Mcp-Session-Id header) plus GET /health, which returns JSON. It binds to
127.0.0.1 only. Point any Streamable-HTTP-capable client at it:
{ "mcpServers": { "engram": { "type": "http", "url": "http://127.0.0.1:9907/mcp" } } }In HTTP mode every tool call runs on a node:worker_threads pool, so a
multi-second recall never blocks /health, the handshake, or other clients.
Each worker owns its own SQLite connection and embedding model. Stdio mode
never spawns workers.
| Variable | Default | Purpose |
|---|---|---|
ENGRAM_HTTP_WORKERS |
2 |
Worker count in HTTP mode (0 = run tool calls inline on the main thread) |
ENGRAM_WORKER_TIMEOUT_MS |
8000 |
Per-call timeout; remember, remember_batch, index_file_structure and reflect --refresh use higher floors. A worker still silent at 2x the timeout is killed and respawned |
See the "MCP Server Transports" section of CLAUDE.md for the
worker-pool internals (worker-pool.ts, dispatch.ts, worker.ts).
docs/integrate-your-agent.md is written to be
handed to an AI agent running in the host you want to connect. It states the
public contract (endpoints, handshake, tools, scoping) and the three behaviors
to implement (auto-recall before each turn, explicit MCP tools, capture via
remember), with a verify ladder and a worked Codex CLI example. The Hermes
Agent provider in interfaces/hermes-plugin/ is the reference implementation.
engram init # Initialize database + download embedding model
engram sync # Ingest conversations from Claude Code projects
engram search <query> # Hybrid search across all memory layers
engram remember <text> # Store a memory
engram extract # LLM-based fact extraction from a conversation
engram dream # Run autonomous consolidation pipeline
engram reflect # Show emergent graph patterns
engram explore <name> # Explore entity connections
engram entities # List/search entities
engram relationships # Show relationships for an entity
engram stats # Database statistics
engram health # System health check
engram migrate # Migrate data from legacy superpowers DB
engram validate # Validate migration integrity
engram backfill-event-ts # Backfill event-time timestamps (temporal recall)
engram commitments [status] # List tracked commitments (same XML as the MCP tool)
engram commitment-done <id> # Mark a commitment done (--status dropped|superseded)
engram commitments-extract <conv> # Re-scan one conversation (no checkpoint; proves dedupe)
engram mcp # Start the MCP server (stdio; see Transports section)
Interactive knowledge graph visualization at localhost:3001:
- Dream Control — Live pipeline phase tracking with progress bars via SSE
- Real-time Updates — SSE watching SQLite WAL for instant graph changes
Start: npx tsx src/interfaces/web/server.ts
Hybrid search combining three sources with Reciprocal Rank Fusion:
- Vector — Semantic similarity via nomic-embed-text (384 dims) with MiniLM fallback
- FTS5 — SQLite full-text search across exchanges, memories, and entities
- Graph — Entity traversal and relationship-aware context expansion
All search responses respect caller-specified token budgets. Stateful sessions allow iterative refinement with budget tracking.
Autonomous consolidation mimicking human memory synthesis:
flowchart LR
subgraph dream["Dream Daemon"]
direction LR
I[Ingest] --> E[Extract] --> C[Consolidate] --> R[Reflect] --> P[Prune]
end
subgraph episodic["Episodic"]
sync[sync]
store[store]
end
subgraph semantic["Semantic"]
extractor[extractor]
consolidator[consolidator]
decay[decay]
end
subgraph graph["Graph"]
gextractor[extractor]
reflection[reflection]
end
subgraph core["_core"]
llm[llm]
db[db]
embeddings[embeddings]
end
I -- "discover & index\nconversations" --> sync
sync -- "persist\nexchanges" --> store
E -- "extract facts" --> extractor
E -- "extract entities\n& relationships" --> gextractor
C -- "dedup, merge,\nconflict detect" --> consolidator
R -- "communities, bridges,\ntemporal patterns" --> reflection
P -- "FSRS decay,\nlow-value removal" --> decay
extractor --> llm
gextractor --> llm
reflection --> llm
store --> db
consolidator --> embeddings
extractor --> embeddings
- Ingest — Sync new conversation archives via the episodic layer
- Extract — LLM-based fact extraction (semantic) and entity/relationship extraction (graph)
- Consolidate — Deduplicate, merge, and resolve conflicts via semantic consolidator with embedding similarity
- Reflect — Detect communities, bridge entities, and temporal patterns via graph reflection
- Prune — Decay and remove low-value memories using FSRS-inspired retrievability scoring (semantic decay)
All phases use _core infrastructure: llm for LLM calls, db for persistence, embeddings for similarity.
Run via engram dream, web UI dream button, or scheduled via launchd.
| Component | Technology |
|---|---|
| Runtime | Node.js ≥ 22 (TypeScript) |
| Database | SQLite + WAL mode (single-file, local-first) |
| Vector Search | sqlite-vec |
| Full-Text Search | SQLite FTS5 (Porter stemming) |
| Embeddings | nomic-embed-text via @xenova/transformers |
| Graph Analysis | graphology (Louvain communities, betweenness centrality) |
| LLM Providers | Anthropic, OpenRouter, Ollama (tiered cascade) |
| MCP Server | @modelcontextprotocol/sdk |
| Daemon | macOS launchd |
npm run build # TypeScript compilation
npm run test:run # Run tests (vitest, 56 test files)
npm run mcp # Start MCP server
npm run dev # Dev CLI via tsx
npm run dream # Run dream consolidation
npm run lint # Type-check without emitAll settings are environment variables; nothing is read from a config file.
| Variable | Default | Purpose |
|---|---|---|
ANTHROPIC_API_KEY |
— | Enables the Anthropic provider (final tier of the LLM cascade) |
OPENROUTER_API_KEY |
— | Enables the OpenRouter provider (middle tier) |
OLLAMA_HOST |
http://localhost:11434 |
Ollama endpoint; used first if reachable |
ENGRAM_LOCAL_MODEL |
qwen2.5:7b |
Ollama model name |
ENGRAM_OPENROUTER_MODEL |
google/gemini-2.5-flash-lite |
OpenRouter model name |
ENGRAM_DATA_DIR |
~/.local/share/engram |
Root for database, archive, and logs |
ENGRAM_DB_PATH |
$ENGRAM_DATA_DIR/engram.db |
SQLite database location |
ENGRAM_ARCHIVE_DIR |
$ENGRAM_DATA_DIR/archive |
Conversation archive directory |
ENGRAM_LOGS_DIR |
$ENGRAM_DATA_DIR/logs |
Log directory |
ENGRAM_CLAUDE_PROJECTS_DIR |
~/.claude/projects |
Where engram sync looks for Claude Code conversations |
ENGRAM_EMBEDDING_DIMS |
256 |
Matryoshka embedding dimensions (must match the existing DB) |
ENGRAM_RERANK_ENABLED |
true |
Set to false or 0 to disable the cross-encoder reranker |
ENGRAM_CHUNKING_STRATEGY |
fixed |
fixed or adaptive (content-aware boundaries) |
ENGRAM_BIND |
127.0.0.1 |
Web visualizer bind address (0.0.0.0 to expose on the network) |
PORT |
3001 |
Web visualizer port |
LLM providers. Extraction and the dream pipeline try Ollama first (if OLLAMA_HOST answers),
then OpenRouter (if OPENROUTER_API_KEY is set), then Anthropic (if ANTHROPIC_API_KEY is set).
At least one must be configured for engram extract and engram dream; search, remember,
remember_batch, and the web visualizer do not need an LLM.
- SPEC.md — Full system specification with requirements and interface contract
- SPEC-legacy.md — Original vision document with detailed design rationale
- plans/ — Implementation plans (phases 1–4, phase 6 RLM, phase 7 extensions)
- decisions/ — Architecture Decision Records




