Persistent memory for AI coding agents
Agent-agnostic. Single binary. Zero dependencies.
Quick Start • How It Works • Agent Setup • Why Not claude-mem? • Terminal UI • Full Docs
engram
/ˈen.ɡræm/— neuroscience: the physical trace of a memory in the brain.
Your AI coding agent forgets everything when the session ends. Engram gives it a brain.
A Go binary with SQLite + FTS5 full-text search, exposed via CLI, HTTP API, MCP server, and an interactive TUI. Works with any agent that supports MCP — OpenCode, Claude Code, Cursor, Windsurf, or anything else.
Agent (OpenCode / Claude Code / Cursor / Windsurf / ...)
↓ MCP stdio
Engram (single Go binary)
↓
SQLite + FTS5 (~/.engram/engram.db)
brew install gentleman-programming/tap/engramgit clone https://github.com/Gentleman-Programming/engram.git
cd engram
go install ./cmd/engramGrab the latest release for your platform from GitHub Releases.
Then set up your agent's plugin:
# Claude Code — via marketplace
claude plugin marketplace add Gentleman-Programming/engram
claude plugin install engram
# OpenCode — via engram setup
engram setup opencode
# Or interactive (asks which agent)
engram setupSee Agent Setup for manual configuration or other agents (Cursor, Windsurf, Gemini).
That's it. No Node.js, no Python, no Bun, no Docker, no ChromaDB, no vector database, no worker processes. One binary, one SQLite file.
The agent proactively calls mem_save after significant work — structured, searchable, no noise.
Engram trusts the agent to decide what's worth remembering — not a firehose of raw tool calls.
1. Agent completes significant work (bugfix, architecture decision, etc.)
2. Agent calls mem_save with a structured summary:
- title: "Fixed N+1 query in user list"
- type: "bugfix"
- content: What/Why/Where/Learned format
3. Engram persists to SQLite with FTS5 indexing
4. Next session: agent searches memory, gets relevant context
Session starts → Agent works → Agent saves memories proactively
↓
Session ends → Agent writes session summary (Goal/Discoveries/Accomplished/Files)
↓
Next session starts → Previous session context is injected automatically
| Tool | Purpose |
|---|---|
mem_save |
Save a structured observation (decision, bugfix, pattern, etc.) |
mem_search |
Full-text search across all memories |
mem_session_summary |
Save end-of-session summary |
mem_context |
Get recent context from previous sessions |
mem_timeline |
Chronological context around a specific observation |
mem_get_observation |
Get full content of a specific memory |
mem_save_prompt |
Save a user prompt for future context |
mem_stats |
Memory system statistics |
mem_session_start |
Register a session start |
mem_session_end |
Mark a session as completed |
Token-efficient memory retrieval — don't dump everything, drill in:
1. mem_search "auth middleware" → compact results with IDs (~100 tokens each)
2. mem_timeline observation_id=42 → what happened before/after in that session
3. mem_get_observation id=42 → full untruncated content
Engram works with any MCP-compatible agent. Add it to your agent's MCP config:
Prerequisite: Install the
engrambinary first (via Homebrew, binary download, or source). The plugin needs it for the MCP server and session tracking.
Add to your opencode.json (global: ~/.config/opencode/opencode.json or project-level):
{
"mcp": {
"engram": {
"type": "local",
"command": ["engram", "mcp"],
"enabled": true
}
}
}Optional: OpenCode plugin for enhanced session management (auto-session tracking, compaction memory persistence, system prompt injection):
engram setup opencode
# or manually: cp plugin/opencode/engram.ts ~/.config/opencode/plugins/The plugin is auto-loaded from ~/.config/opencode/plugins/ — no config changes needed. It also needs the HTTP server running for session tracking:
engram serve &See OpenCode Plugin for details.
Prerequisite: Install the
engrambinary first (via Homebrew, binary download, or source). The plugin needs it for the MCP server and session tracking scripts.
Option A: Plugin via marketplace (recommended) — full session management, auto-import, compaction recovery, and Memory Protocol skill:
claude plugin marketplace add Gentleman-Programming/engram
claude plugin install engramThat's it. The plugin registers the MCP server, hooks, and Memory Protocol skill automatically.
Option B: Plugin via engram setup — same plugin, installed from the embedded binary:
engram setup claude-codeOption C: Bare MCP — just the 10 memory tools, no session management:
Add to your .claude/settings.json (project) or ~/.claude/settings.json (global):
{
"mcpServers": {
"engram": {
"command": "engram",
"args": ["mcp"]
}
}
}With bare MCP, add a Surviving Compaction prompt to your CLAUDE.md so the agent remembers to use Engram after context resets.
See Claude Code Plugin for details on what the plugin provides.
Add to your ~/.gemini/settings.json (global) or .gemini/settings.json (project):
{
"mcpServers": {
"engram": {
"command": "engram",
"args": ["mcp"]
}
}
}Or via the CLI:
gemini mcp add engram engram mcpAdd to your .cursor/mcp.json:
{
"mcpServers": {
"engram": {
"command": "engram",
"args": ["mcp"]
}
}
}Add to your ~/.windsurf/mcp.json:
{
"mcpServers": {
"engram": {
"command": "engram",
"args": ["mcp"]
}
}
}The pattern is always the same — point your agent's MCP config to engram mcp via stdio transport.
When your agent compacts (summarizes long conversations to free context), it starts fresh — and might forget about Engram. To make memory truly resilient, add this to your agent's system prompt or config file:
For Claude Code (CLAUDE.md):
## Memory
You have access to Engram persistent memory via MCP tools (mem_save, mem_search, mem_session_summary, etc.).
- Save proactively after significant work — don't wait to be asked.
- After any compaction or context reset, call `mem_context` to recover session state before continuing.For OpenCode (agent prompt in opencode.json):
After any compaction or context reset, call mem_context to recover session state before continuing.
Save memories proactively with mem_save after significant work.
For Gemini CLI (GEMINI.md):
## Memory
You have access to Engram persistent memory via MCP tools (mem_save, mem_search, mem_session_summary, etc.).
- Save proactively after significant work — don't wait to be asked.
- After any compaction or context reset, call `mem_context` to recover session state before continuing.For Cursor/Windsurf (.cursorrules or .windsurfrules):
You have access to Engram persistent memory (mem_save, mem_search, mem_context).
Save proactively after significant work. After context resets, call mem_context to recover state.
This is the nuclear option — system prompts survive everything, including compaction.
claude-mem is a great project (28K+ stars!) that inspired Engram. But we made fundamentally different design decisions:
| Engram | claude-mem | |
|---|---|---|
| Language | Go (single binary, zero runtime deps) | TypeScript + Python (needs Node.js, Bun, uv) |
| Agent lock-in | None. Works with any MCP agent | Claude Code only (uses Claude plugin hooks) |
| Search | SQLite FTS5 (built-in, zero setup) | ChromaDB vector database (separate process) |
| What gets stored | Agent-curated summaries only | Raw tool calls + AI compression |
| Compression | Agent does it inline (it already has the LLM) | Separate Claude API calls via agent-sdk |
| Dependencies | go install and done |
Node.js 18+, Bun, uv, Python, ChromaDB |
| Processes | One binary (or none — MCP stdio) | Worker service on port 37777 + ChromaDB |
| Database | Single ~/.engram/engram.db file |
SQLite + ChromaDB (two storage systems) |
| Web UI | Terminal TUI (engram tui) |
Web viewer on localhost:37777 |
| Privacy | <private> tags stripped at 2 layers |
<private> tags stripped |
| Auto-capture | No. Agent decides what matters | Yes. Captures all tool calls then compresses |
| License | MIT | AGPL-3.0 |
claude-mem captures everything and then compresses it with AI. This means:
- Extra API calls for compression (costs money, adds latency)
- Raw tool calls pollute search results until compressed
- Requires a worker process, ChromaDB, and multiple runtimes
- Locked to Claude Code's plugin system
Engram lets the agent decide what's worth remembering. The agent already has the LLM, the context, and understands what just happened. Why run a separate compression pipeline?
mem_saveafter a bugfix: "Fixed N+1 query — added eager loading in UserList"mem_session_summaryat session end: structured Goal/Discoveries/Accomplished/Files- No noise, no compression step, no extra API calls
- Works with ANY agent via standard MCP
The result: cleaner data, faster search, no infrastructure overhead, agent-agnostic.
Interactive terminal UI for browsing your memory. Built with Bubbletea.
engram tuiScreens: Dashboard, Search, Recent Observations, Observation Detail, Timeline, Sessions, Session Detail
Navigation: j/k vim keys, Enter to drill in, t for timeline, / to search, Esc to go back
Features:
- Catppuccin Mocha color palette
- Scroll indicators for long lists
- Full FTS5 search from the TUI
- Live data refresh on back-navigation
Share memories across machines and team members by committing them to your repo. Uses compressed chunks with a manifest index — no merge conflicts, no huge files.
# Export new memories as a compressed chunk
# (automatically filters by current directory name as project)
engram sync
# Commit to git
git add .engram/ && git commit -m "sync engram memories"
# On another machine / clone: import new chunks
engram sync --import
# Check sync status
engram sync --status
# Override project detection if needed
engram sync --project other-nameHow it works:
.engram/
├── manifest.json ← small index (git diffs this)
├── chunks/
│ ├── a3f8c1d2.jsonl.gz ← chunk by Alan (compressed, ~2KB)
│ ├── b7d2e4f1.jsonl.gz ← chunk by Juan
│ └── c9f1a2b3.jsonl.gz ← chunk by Alan (next day)
└── engram.db ← gitignored (local working DB)
- Each
engram synccreates a new chunk — never modifies old ones - Chunks are gzipped JSONL — small files, git treats as binary (no diff noise)
- The manifest is the only file git diffs — it's small and append-only
- Each chunk has a content hash ID — imported only once, no duplicates
- No merge conflicts on data — each dev creates independent chunks
Auto-import: The OpenCode plugin automatically runs engram sync --import when it detects .engram/manifest.json in the project directory. Clone a repo, open OpenCode, and the team's memories are loaded.
engram setup [agent] Install agent plugin (interactive or: engram setup opencode)
engram serve [port] Start HTTP API server (default: 7437)
engram mcp Start MCP server (stdio transport)
engram tui Launch interactive terminal UI
engram search <query> Search memories
engram save <title> <msg> Save a memory
engram timeline <obs_id> Chronological context around an observation
engram context [project] Recent context from previous sessions
engram stats Memory statistics
engram export [file] Export all memories to JSON
engram import <file> Import memories from JSON
engram sync Export new memories as compressed chunk to .engram/
engram version Show version
For OpenCode users, a thin TypeScript plugin adds enhanced session management on top of the MCP tools:
# Install via engram (recommended — works from Homebrew or binary install)
engram setup opencode
# Or manually: cp plugin/opencode/engram.ts ~/.config/opencode/plugins/The plugin auto-starts the HTTP server if it's not already running — no manual engram serve needed.
The plugin:
- Auto-starts the engram server if not running
- Auto-imports git-synced memories from
.engram/manifest.jsonif present in the project - Creates sessions on-demand via
ensureSession()(resilient to restarts/reconnects) - Injects the Memory Protocol into the agent's system prompt via
chat.system.transform— strict rules for when to save, when to search, and a mandatory session close protocol - Injects previous session context into the compaction prompt
- Instructs the compressor to tell the new agent to persist the compacted summary via
mem_session_summary - Strips
<private>tags before sending data
No raw tool call recording — the agent handles all memory via mem_save and mem_session_summary.
The plugin injects a strict protocol into every agent message:
- WHEN TO SAVE: Mandatory after bugfixes, decisions, discoveries, config changes, patterns, preferences
- WHEN TO SEARCH: Reactive (user says "remember"/"recordar") + proactive (starting work that might overlap past sessions)
- SESSION CLOSE: Mandatory
mem_session_summarybefore ending — "This is NOT optional. If you skip this, the next session starts blind." - AFTER COMPACTION: Immediately call
mem_contextto recover state
The OpenCode plugin uses a defense-in-depth strategy to ensure memories survive compaction:
| Layer | Mechanism | Survives Compaction? |
|---|---|---|
| System Prompt | MEMORY_INSTRUCTIONS injected via chat.system.transform |
Always present |
| Compaction Hook | Auto-saves checkpoint + injects context + reminds compressor | Fires during compaction |
| Agent Config | "After compaction, call mem_context" in agent prompt |
Always present |
For Claude Code users, a plugin adds enhanced session management using Claude's native hook and skill system:
# Install via Claude Code marketplace (recommended)
claude plugin marketplace add Gentleman-Programming/engram
claude plugin install engram
# Or via engram binary (works from Homebrew or binary install)
engram setup claude-code
# Or for local development/testing from the repo
claude --plugin-dir ./plugin/claude-code| Feature | Bare MCP | Plugin |
|---|---|---|
| 10 memory tools | ✓ | ✓ |
| Session tracking (auto-start) | ✗ | ✓ |
| Auto-import git-synced memories | ✗ | ✓ |
| Compaction recovery | ✗ | ✓ |
| Memory Protocol skill | ✗ | ✓ |
| Previous session context injection | ✗ | ✓ |
plugin/claude-code/
├── .claude-plugin/plugin.json # Plugin manifest
├── .mcp.json # Registers engram MCP server
├── hooks/hooks.json # SessionStart + Stop lifecycle hooks
├── scripts/
│ ├── session-start.sh # Ensures server, creates session, imports chunks, injects context
│ ├── post-compaction.sh # Injects previous context + recovery instructions
│ └── session-stop.sh # Placeholder for future heartbeat
└── skills/memory/SKILL.md # Memory Protocol (when to save, search, close, recover)
On session start (startup):
- Ensures the engram HTTP server is running
- Creates a new session via the API
- Auto-imports git-synced chunks from
.engram/manifest.json(if present) - Injects previous session context into Claude's initial context
On compaction (compact):
- Injects the previous session context + compacted summary
- Tells the agent: "FIRST ACTION REQUIRED — call
mem_session_summarywith this content before doing anything else" - This ensures no work is lost when context is compressed
Memory Protocol skill (always available):
- Strict rules for when to save (mandatory after bugfixes, decisions, discoveries)
- When to search memory (reactive + proactive)
- Session close protocol — mandatory
mem_session_summarybefore ending - After compaction — 3-step recovery: persist summary → load context → continue
Wrap sensitive content in <private> tags — it gets stripped at TWO levels:
Set up API with <private>sk-abc123</private> key
→ Set up API with [REDACTED] key
- Plugin layer — stripped before data leaves the process
- Store layer —
stripPrivateTags()in Go before any DB write
engram/
├── cmd/engram/main.go # CLI entrypoint
├── internal/
│ ├── store/store.go # Core: SQLite + FTS5 + all data ops
│ ├── server/server.go # HTTP REST API (port 7437)
│ ├── mcp/mcp.go # MCP stdio server (10 tools)
│ ├── setup/setup.go # Agent plugin installer (go:embed)
│ ├── sync/sync.go # Git sync: manifest + compressed chunks
│ └── tui/ # Bubbletea terminal UI
│ ├── model.go # Screen constants, Model, Init()
│ ├── styles.go # Lipgloss styles (Catppuccin Mocha)
│ ├── update.go # Input handling, per-screen handlers
│ └── view.go # Rendering, per-screen views
├── plugin/
│ ├── opencode/engram.ts # OpenCode adapter plugin
│ └── claude-code/ # Claude Code plugin (hooks + skill)
│ ├── .claude-plugin/plugin.json
│ ├── .mcp.json
│ ├── hooks/hooks.json
│ ├── scripts/ # session-start, post-compaction, session-stop
│ └── skills/memory/SKILL.md
├── assets/ # Screenshots and media
├── DOCS.md # Full technical documentation
├── go.mod
└── go.sum
- Go 1.25+ to build from source (not needed if installing via Homebrew or downloading a binary)
- That's it. No runtime dependencies.
The binary includes SQLite (via modernc.org/sqlite — pure Go, no CGO).
| Variable | Description | Default |
|---|---|---|
ENGRAM_DATA_DIR |
Data directory | ~/.engram |
ENGRAM_PORT |
HTTP server port | 7437 |
MIT
Inspired by claude-mem — but agent-agnostic, simpler, and built different.



