System Overview
Engram is built as an agent-agnostic Go binary with thin adapter plugins per-agent. The Go binary is the brain — plugins just translate agent-specific events into Engram API calls.Core Components
1. Store (internal/store/store.go)
The heart of Engram — all data operations go through this.
- Responsibilities
- Key Types
- Configuration
- SQLite connection management (WAL mode, busy timeout, foreign keys)
- Schema creation and migration
- FTS5 index management (synced via triggers)
- Session CRUD (create, end, list)
- Observation CRUD (add, update, delete, soft-delete)
- Full-text search with query sanitization
- Timeline generation (before/after an observation)
- Deduplication (normalized hash + rolling window)
- Topic upserts (same
project + scope + topic_keyupdates existing) - Privacy tag stripping (
<private>→[REDACTED]) - Export/import (JSON dump of all data)
- Git sync chunk tracking
The store uses pure Go SQLite (
modernc.org/sqlite) — no CGO, no external dependencies. This enables true cross-platform single binary distribution.2. HTTP Server (internal/server/server.go)
REST API on port 7437 for plugins and integrations.
Endpoints
Health & Stats
Health & Stats
GET /health— Health check ({"status": "ok", "service": "engram", "version": "0.1.0"})GET /stats— Memory statistics (sessions, observations, prompts, projects)
Sessions
Sessions
POST /sessions— Create session ({id, project, directory})POST /sessions/{id}/end— End session ({summary})GET /sessions/recent— Recent sessions (?project=X&limit=N)
Observations
Observations
POST /observations— Add observationGET /observations/recent— Recent observations (?project=X&scope=project|personal&limit=N)GET /observations/{id}— Get single observationPATCH /observations/{id}— Update fields (partial updates)DELETE /observations/{id}— Delete (?hard=truefor permanent)
Search & Timeline
Search & Timeline
GET /search— FTS5 search (?q=QUERY&type=TYPE&project=PROJECT&scope=SCOPE&limit=N)GET /timeline— Chronological context (?observation_id=N&before=5&after=5)
Prompts
Prompts
POST /prompts— Save user promptGET /prompts/recent— Recent promptsGET /prompts/search— Search prompts
Context & Export
Context & Export
GET /context— Formatted context from previous sessions (?project=X&scope=project|personal)GET /export— Export all data as JSONPOST /import— Import data from JSON
The HTTP server listens on
127.0.0.1:7437 (localhost only). Override with ENGRAM_PORT environment variable.3. MCP Server (internal/mcp/mcp.go)
Model Context Protocol server (stdio transport) that exposes 13 memory tools to any MCP-compatible agent.
Tool Profiles
Engram supports tool profiles to reduce context usage:Server Instructions
The MCP server includes instructions for Claude Code’s Tool Search:4. Sync (internal/sync/sync.go)
Git-based memory sharing using compressed chunks.
Architecture
Workflow
Why chunks? Each
engram sync creates a NEW file — old chunks are never modified. No merge conflicts, just append-only git history.5. TUI (internal/tui/)
Interactive terminal UI built with Bubbletea.
Structure (Gentleman Bubbletea Patterns)
- model.go
- styles.go
- update.go
- view.go
- Screen constants (
Screen intiota) - Single
Modelstruct holds ALL state Init()function- Custom messages for async operations
Screens
- Dashboard: Stats overview + menu
- Search: FTS5 text search with text input
- Search Results: Browsable results list
- Recent Observations: All observations, newest first
- Observation Detail: Full content, scrollable
- Timeline: Chronological context (before/after)
- Sessions: All sessions list
- Session Detail: Observations within a session
TUI uses dedicated store methods (
AllSessions, AllObservations) that don’t filter by session status, unlike MCP context methods which only show completed sessions.Data Flow
Observation Creation
Search Flow
Plugin Architecture
OpenCode Plugin
TypeScript adapter in~/.config/opencode/plugins/engram.ts:
Auto-start server
Checks if
http://127.0.0.1:7437/health responds. If not, spawns engram serve in background.Auto-import git chunks
Detects
.engram/manifest.json in project directory, runs engram sync --import.Session management
ensureSession() creates session on-demand via HTTP API (idempotent, survives plugin reloads).Memory Protocol injection
chat.system.transform hook concatenates Memory Protocol into system prompt (compatible with single-system-message models like Qwen, Ministral).Compaction recovery
experimental.session.compacting hook injects previous context + instructs compressor to call mem_session_summary.Claude Code Plugin
Bash scripts + skill system in~/.claude/plugins/engram/:
- Hooks
- Skill
- MCP Config
- startup (
session-start.sh): Ensures server, creates session, imports chunks, injects context - compact (
post-compaction.sh): Injects context + recovery instructions - stop (
session-stop.sh): Logs session end
Design Decisions
Why Go over TypeScript?
Why Go over TypeScript?
- Single binary: No Node.js, no Bun, no runtime dependencies
- Cross-platform: Works natively on macOS, Linux, Windows (x86_64 and ARM64)
- Pure Go SQLite:
modernc.org/sqlitehas no CGO — true single binary distribution - Fast startup: Go binary starts in milliseconds vs Node.js ~100ms
Why SQLite + FTS5 over vector DB?
Why SQLite + FTS5 over vector DB?
- FTS5 covers 95% of use cases: Full-text search with BM25 ranking is sufficient for code memory
- No separate process: No ChromaDB, no Pinecone, no vector service to manage
- Single file:
~/.engram/engram.dbis portable, backupable, debuggable withsqlite3CLI - Simpler: Zero configuration, zero network calls
Why agent-driven compression?
Why agent-driven compression?
- Agent already has the LLM: No need for separate API calls
- Agent has context: It knows what just happened better than a background service
- No extra cost: No additional API usage beyond the agent’s work
- No latency: Compression happens inline during the agent’s response
Why no raw auto-capture?
Why no raw auto-capture?
- Raw tool calls are noisy:
edit: {file: "foo.go"}pollutes search results - Low signal-to-noise ratio: Shell history and git already provide the audit trail
- Bloats database: Thousands of low-value observations vs dozens of curated summaries
- Agent curates better: Structured
mem_savesummaries are higher quality and more searchable
Project Structure
Dependencies
Go Dependencies
modernc.org/sqlite— Pure Go SQLite (no CGO)github.com/mark3labs/mcp-go— MCP protocol implementationgithub.com/charmbracelet/bubbletea— Terminal UI frameworkgithub.com/charmbracelet/lipgloss— Terminal stylinggithub.com/charmbracelet/bubbles— TUI components
Plugin Dependencies
@opencode-ai/plugin— OpenCode plugin types- Runtime: Bun (built into OpenCode)
- Claude Code plugin: bash (for hooks)
Next Steps
How It Works
Memory system, session lifecycle, and 3-layer pattern
Memory Protocol
When to save, when to search, and session close protocol