Project memory for AI coding agents.
Engram is a local-first memory system that gives AI agents persistent context across sessions. It stores structured events (decisions, discoveries, warnings, mutations, outcomes) in a lightweight SQLite database and generates briefings that catch agents up on project state.
I built this because I kept losing context. Every session starts from zero — no memory of what was tried, what failed, what was decided, or what to avoid. Engram fixes that. Post events as you work, and the next agent (or the next session of you) gets a briefing instead of starting blind.
AI coding agents have four problems that compound in real projects:
- Amnesia — Each session starts with zero memory of prior work
- Isolation — No awareness of what other agents did or are doing
- No learning — Outcomes of past decisions are lost; mistakes repeat
- Blindness — No way to know what changed since your last session
These aren't theoretical. If you've ever re-investigated a bug that was already fixed, made a decision that contradicts one from yesterday, or modified a file another agent was working on — that's what Engram prevents.
The project started as "AgentBus" (an inter-agent message bus), but after consulting with three AI models (GPT-4o, Gemini 2.5 Flash, Claude Sonnet), we agreed the "bus" framing was wrong. This isn't middleware. It's a project memory log with a briefing interface. The briefing is the product — everything else serves it.
If Engram is configured in your environment — either via the Claude Code plugin (one-step install, see Setup below) or manually as an MCP server / CLI — you have sixteen tools available.
If Claude Code hooks are present (shipped with the plugin, or installed manually via engram hooks install), file mutations and bash command outcomes are captured automatically — you rarely need to post mutation or outcome events by hand.
engram briefing
Returns a structured summary of recent project activity: active warnings, recent decisions, file changes, discoveries, and outcomes. This is the single most important call. Run it first.
engram post_event(event_type="decision", content="Using bcrypt over argon2 — existing infra uses bcrypt", scope=["src/auth/hash.py"])
engram post_event(event_type="warning", content="Don't modify user_sessions — migration pending", priority="critical")
engram post_event(event_type="outcome", content="JWT fix worked", related_ids=["evt-abc123"])
Event types and when to use them:
| Type | When to post |
|---|---|
discovery |
You found something important about the codebase that others should know |
decision |
You chose an approach — record the rationale so future agents understand why |
warning |
Something should NOT be done — record what and why to prevent repeat mistakes |
mutation |
You changed files — auto-captured by hooks, rarely needs manual posting |
outcome |
A previous action worked or failed — auto-captured for bash commands |
Use related_ids to link events (e.g., link an outcome to the decision it validates). Linked events appear in queries via related_to.
Guidelines:
- Post decisions with rationale, not just "I did X" — the why matters most
- Warnings are high-value: they prevent future agents from making known mistakes
- Keep content under 2000 characters. Be concise. You're writing for other agents with limited context windows.
- Include
scope(file paths) when the event relates to specific files — this enables scoped queries and staleness detection
engram query(text="authentication")
engram query(event_type="warning", scope="src/auth")
engram query(since="24h", event_type="mutation")
engram query(related_to="evt-abc123")
Full-text search plus structured filters. Filters combine with AND logic. Use this when you need specific context beyond what the briefing provides.
Every event can carry an optional area — a conceptual component tag
(billing, email-change) independent of the file scope. It makes a
feature that spans many files across sessions recallable in one query:
engram post -t decision -c "cooldown on resend" -s src/lib/rate-limit.ts -A email-change
engram query --area email-changeTo auto-populate area without setting it by hand, add .engram/areas.json:
{
"rules": [
{ "prefix": "src/http/routes/me/", "area": "account" },
{ "prefix": "src/billing/", "area": "billing" }
]
}The longest matching prefix wins. The file is optional; without it, area
is simply whatever you pass explicitly (or empty).
engram resolve_event(event_id="evt-abc123", reason="Fixed in PR #42")
engram supersede_event(event_id="evt-abc123", superseded_by="evt-def456")
engram reopen_event(event_id="evt-abc123")
Events are not just append-only. When a warning is addressed, resolve_event it so it stops surfacing as live. When a decision is replaced, post the new one, then supersede_event the old with the new id. reopen_event if a resolved issue resurfaces. Keeping status current is what keeps briefings showing only the live state instead of accreting stale-but-live-looking entries.
engram status
Returns event count, last activity timestamp, database size. Useful for sanity-checking that Engram is populated.
engram session_start(focus="Implementing auth middleware", scope=["src/auth/"])
engram session_end(session_id="ses-abc123")
Sessions let other agents (and future sessions of you) know what's being worked on. Events are automatically tagged with your active session. Briefings auto-focus to your session's scope. Only one session per agent — starting a new one ends the previous.
Good: decision: Using FTS5 instead of embeddings for search — covers 95% of queries at <10k events with zero dependencies
Bad: decision: Changed search
Good: warning: Do NOT modify the user_sessions table — migration to new schema is pending in PR #47, any changes will be overwritten
Bad: warning: be careful with sessions
The content should be self-contained. Future agents reading it won't have your current context.
- Python 3.12+
- A project directory (preferably a git repository — Engram mines git history on init)
Engram ships in two forms. Pick the one that matches your environment:
- Option 1: Claude Code plugin — single-install bundle that auto-wires the MCP server, hooks, and slash-command skills. Recommended for Claude Code users.
- Option 2: Python package — install from source (see below), CLI-only or configured as an MCP server for other clients (Cline, Cursor, Continue, custom LLM apps). Use for headless automation or any environment that isn't Claude Code. (Not yet on PyPI — the
engramname there is an unrelated placeholder package; don'tpip install engram.)
Both paths share the same Python package underneath; the plugin is packaging + wiring on top. You can switch between them per project.
Install the Python package so engram and engram-mcp are on PATH:
# Once Engram ships on PyPI:
pip install engram[mcp]
# Until then, from a repo checkout:
git clone https://github.com/coinstax/engram
cd engram
pip install -e ".[mcp]"Load the plugin in Claude Code (dev mode, until a marketplace listing is published):
cd /path/to/your/project
claude --plugin-dir /path/to/engram/pluginWhat the plugin wires up:
mcp__engram__*MCP tools in every session- PostToolUse hooks that capture Write/Edit mutations and bash outcomes
- SessionStart hook that auto-initializes
.engram/on first launch, seeds from git history, and emits a briefing (no manualengram initneeded) - Slash commands — currently
/engram:briefing; more in v1.7.0 (/engram:post-decision,/engram:query,/engram:checkpoint-save,/engram:checkpoint-restore)
The plugin does NOT modify your CLAUDE.md — agent-facing guidance is delivered through the MCP server's built-in instructions field and the plugin's SKILL.md files. See plugin/README.md for details including migrating from CLI-installed hooks (run engram hooks uninstall first to avoid duplicate event capture).
Add .engram/ to your .gitignore — the database is machine-local.
# From source
git clone https://github.com/coinstax/engram
cd engram
pip install -e ".[mcp]"
# Or just the CLI (no MCP server)
pip install -e .Consultations need extra SDKs. The multi-model consult feature (engram consult, start_consultation) depends on the provider SDKs, which are optional so the base install and MCP server stay lean. Install them with the consult extra (or all for MCP + consult together):
pip install -e ".[consult]" # openai, google-genai, httpx, python-dotenv
pip install -e ".[all]" # mcp + consultThen set the API key(s) for the provider(s) you want to use, in the environment or a project .env. You only need keys for the providers you actually consult:
| Model keys | Provider | Env var | Get an API key | SDK |
|---|---|---|---|---|
gpt, gpt-4o, o3 |
OpenAI | OPENAI_API_KEY |
platform.openai.com/api-keys | openai |
claude-opus, claude-sonnet |
Anthropic | ANTHROPIC_API_KEY |
console.anthropic.com | via httpx (no SDK) |
gemini-pro, gemini-flash |
GOOGLE_API_KEY |
aistudio.google.com/apikey | google-genai | |
grok |
xAI | XAI_API_KEY |
console.x.ai | via openai (OpenAI-compatible) |
# example .env in your project root
OPENAI_API_KEY=sk-...
ANTHROPIC_API_KEY=sk-ant-...
GOOGLE_API_KEY=...
XAI_API_KEY=xai-...Run engram consult models to see which keys are detected (it loads .env). Without the SDKs installed, a consult fails with a message telling you to install engram[consult].
Initialize in your project:
cd /path/to/your/project
engram initThis does four things:
- Creates
.engram/events.db(SQLite database with WAL mode + FTS5) - Mines your git history to seed the event store (solves the cold-start problem)
- Writes a
CLAUDE.mdwith agent instructions (or appends to existing one) - Suggests running
engram hooks installfor passive observation
Add .engram/ to your .gitignore — the database is local to each machine.
Enable passive observation (Claude Code hooks, manual install):
engram hooks installWrites hooks to .claude/settings.json that automatically:
- Record file mutations when Claude Code uses Write or Edit tools
- Record bash command outcomes (skips trivial commands like
ls,cat,pwd) - Inject a project briefing at the start of each session
With hooks installed, agents get context automatically without manual posting. Check status or remove with engram hooks show / engram hooks uninstall. (If you're using Option 1, skip this — the plugin already ships these hooks.)
Configure as MCP server (for clients other than the plugin):
Add to your agent's MCP configuration:
{
"mcpServers": {
"engram": {
"command": "/path/to/your/venv/bin/engram-mcp",
"env": {
"ENGRAM_PROJECT_DIR": "/path/to/your/project"
}
}
}
}The MCP server exposes seventeen tools: post_event, query, resolve_event, supersede_event, reopen_event, briefing, status, session_start, session_end, list_sessions, save_checkpoint, list_models, start_consultation, start_consultation_file, consult_say, consult_show, consult_done.
Safe mode (memory without external LLM access):
To give an agent project memory but no ability to call external LLM providers or read API keys from the environment, run the server in safe mode. This drops the six consultation tools (list_models, start_consultation, start_consultation_file, consult_say, consult_show, consult_done), leaving the eleven deterministic local project-memory tools. Two equivalent ways:
- Use the
engram-mcp-safeconsole script instead ofengram-mcp, or - Set
ENGRAM_SAFE_MODE=1in the server's environment.
{
"mcpServers": {
"engram": {
"command": "/path/to/your/venv/bin/engram-mcp-safe",
"env": {
"ENGRAM_PROJECT_DIR": "/path/to/your/project"
}
}
}
}status reports "external_llm_tools": false when safe mode is active. For non-Claude integrations, engram init --no-claude-md seeds the project without creating or modifying CLAUDE.md.
Agent instructions (if your framework doesn't auto-load CLAUDE.md):
engram init writes this block to your project's CLAUDE.md. If your agent framework reads instructions from a different file, copy it there:
## Project Memory (Engram)
This project uses Engram for persistent memory across agent sessions.
### Every session
- **Start of every session**: Call `engram briefing` to understand project context
- Use `briefing --focus src/path` for scope-aware context on a specific area
### Recording events
- After important decisions: `post_event` with type "decision" and your rationale
- To leave warnings for future agents: `post_event` with type "warning"
- After discovering something about the codebase: `post_event` with type "discovery"
- Set `priority` to "critical" or "high" for urgent warnings that all agents must see
- Include `scope` (file paths) so events appear in focused briefings
### Event lifecycle
- When an issue is fixed: resolve the event with `engram resolve <id> --reason "..."`
- When a decision is replaced: supersede it with `engram supersede <id> --by <new-id>`
- If a resolved issue resurfaces: reopen with `engram reopen <id>`
### Searching
- To search past context: `engram query` with search terms
- Filter by type, scope, time range, or related event IDs
### Sessions (focus tracking)
- Use `session_start` with `focus` and `scope` to declare what you're working on
- Events are auto-tagged with your session; briefings auto-scope to your session's focus
- One session per agent — starting a new one ends the previous
### Consultations (design validation)
- Call `list_models` (or `engram consult models`) to see available model keys and which API keys are set
- Use `start_consultation` to get feedback from external AI models (`gpt`, `claude-opus`, `gemini-pro`, `grok`, etc.)
- Continue with `consult_say`, review with `consult_show`, close with `consult_done`
- Extend or override the model set per project in `.engram/models.json`
### Context checkpoints
- After writing a context file: `save_checkpoint` to record it and enrich with Engram events
- Use `briefing` with `full=True` to restore: combines checkpoint context + recent activityEngram also works as a standalone CLI for non-MCP agents or manual use:
# Post events
engram post -t decision -c "Using Redis for session cache — latency requirements" -s src/cache.py
engram post -t warning -c "Don't touch migration files — pending deploy" -s db/migrations --priority critical
engram post -t outcome -c "Cache fix worked" -r evt-abc123 # link to related event
# Query
engram query "authentication"
engram query -t warning --since 7d
engram query -t mutation -s src/api --since 24h
engram query --related-to evt-abc123
# Briefing
engram briefing
engram briefing --since 24h -s src/auth
engram briefing --focus src/auth # scope-aware: highlights auth-related events
engram briefing --resolved-window 24 # show events resolved in last 24h
# Lifecycle management
engram resolve evt-abc123 --reason "Fixed in PR #42"
engram supersede evt-abc123 --by evt-def456
engram reopen evt-abc123
# Sessions
engram session start --focus "Implementing auth" --scope src/auth
engram session ls # list active sessions
engram session show ses-abc123 # show session details
engram session end # end current session
# Context checkpoints
engram checkpoint .claude/context/session.md # record + enrich with Engram data
engram checkpoint context.md --no-enrich # record without enrichment
engram briefing --full # restore: checkpoint + recent activity
# Garbage collection
engram gc --dry-run # preview what would be archived
engram gc --max-age 90 # archive mutations/outcomes older than 90 days
# Status
engram statussrc/engram/
models.py — Event, Session, Checkpoint, QueryFilter, BriefingResult dataclasses
store.py — EventStore: SQLite + WAL + FTS5, schema migration (v1→v5), session + checkpoint CRUD
query.py — QueryEngine: relative time parsing, structured + FTS queries
bootstrap.py — GitBootstrapper: mines git log + README/CLAUDE.md into seed events
briefing.py — BriefingGenerator: 4-section briefings, focus ranking, dedup, staleness
formatting.py — Compact/JSON formatters for events and sessions, relative timestamps
context.py — ContextAssembler: auto-context for consultation system prompts
hooks.py — Claude Code hooks: rich mutation/outcome capture, structural extraction, session auto-registration
gc.py — GarbageCollector: archives old events, preserves warnings/decisions
checkpoint.py — CheckpointEngine: context save/restore integration, file enrichment
cli.py — Click CLI: init, post, query, briefing, checkpoint, session, resolve, supersede, reopen, gc, hooks
providers.py — Multi-model provider dispatch (OpenAI, Google, Anthropic, xAI)
consult.py — Multi-turn consultation engine with persistent conversations
mcp_server.py — FastMCP server: 17 tools (events, sessions, checkpoints, briefing, consultations)
Storage: .engram/events.db — SQLite with WAL mode for concurrent access, FTS5 virtual table with auto-indexing triggers. Schema v6 with automatic migration from any prior version on connection.
Event schema: 13 fields: id, timestamp, event_type, agent_id, content, scope, area, related_ids, status, priority, resolved_reason, superseded_by, session_id. Core 7 fields are always populated; area is optional (set explicitly or inferred from .engram/areas.json); lifecycle fields default to sensible values; session_id is auto-linked to the active session.
Design decisions:
- FTS5 only, no embeddings — covers 95% of queries at <10k events with zero additional dependencies
- 5 event types (down from 9 in original spec) — discovery, decision, warning, mutation, outcome
- Content capped at 2000 chars — prevents agents from dumping entire files
- Git bootstrap on init — the cold-start problem was identified as the #1 adoption barrier
- Zero-config, local-first — SQLite only, no cloud, no servers for core functionality
- Single runtime dependency (click) — MCP support is optional
- Passive-first — hooks capture activity automatically; manual posting is for high-signal events only
- Rich mutation capture — Edit diffs and Write structural extraction produce informative summaries, not just file paths
- Warnings and decisions are never garbage-collected — they represent permanent project knowledge
- Dual-channel distribution (v1.7+) —
pip install engramfor the CLI/MCP binary, Claude Code plugin for wiring. Skills and MCP tools coexist: skills for user-invoked workflows, MCP for programmatic/autonomous use.
Engram was designed through structured consultation with three AI models, each given a different review lens:
- OpenAI GPT-4o: Reviewed as an AI agent that would use the system. Flagged the manual-posting compliance problem and pushed for minimal required fields.
- Google Gemini 2.5 Flash: Reviewed with focus on large-context LLMs. Advocated for semantic search (deferred to v2) and hierarchical summarization. Strongest voice for token-efficient output.
- Claude Sonnet 4.6: Self-reviewed as a critic. Identified the cold-start problem as fatal, argued FTS5 is sufficient for v1, and proposed the name "Engram."
The synthesis of all three consultations is in docs/CONSULTATION_SYNTHESIS.md. The v1.1 roadmap went through the same process — see docs/V1_1_SPEC.md.
v1.0 — Event store, CLI, MCP server, git bootstrap, briefing, FTS5 search
v1.1 — Passive observation via Claude Code hooks, event linking, CLAUDE.md auto-write, smarter briefings with dedup/staleness detection, garbage collection
v1.2 — Multi-turn AI consultation system with external models (GPT-4o, Gemini Flash, Claude Sonnet), persistent conversation storage, CLI + MCP tools
v1.3 — Event lifecycle (resolve/supersede/reopen), event priority (critical/high/normal/low), scope-aware briefings with --focus, 4-section briefing structure, auto-context for consultations, thinking model support
v1.4 — Session intent (engram session start/end/ls/show), event-session linking, auto-scoped briefings from active session, stale session cleanup, hook auto-registration, consult file feature
v1.5 — Context save/restore integration (engram checkpoint, engram briefing --full), file enrichment with Engram events, save_checkpoint MCP tool
v1.6 — Richer mutation capture: Edit tool diffs ('old' -> 'new' or unified diff), Write tool structural extraction (class/def names for .py, .js, .ts, .rs, .go), line counts, created/wrote distinction
v1.6.1 — Maintenance: consistent agent_id on hook-captured events, atomic settings.json writes, engram hooks uninstall / show commands, mcp<2.0 upper pin, relative-timestamp test fixtures
v1.8.0 (current release, 2026-07-07) — Consultation models refreshed to current frontier flagships (gpt-5.5, claude-opus-4-8, claude-sonnet-5, gemini-3.1-pro-preview, gemini-3.5-flash, grok-4.3) with version-agnostic keys. Model set is now extensible per project via .engram/models.json, and engram consult models / the list_models MCP tool make the available keys discoverable. Fixes a latent 400: the Anthropic provider now uses adaptive thinking ({"type": "adaptive"}) instead of the removed budget_tokens, which current Claude models reject.
v1.7.0 (2026-07-06) — Claude Code plugin packaging. Ships Engram as a single-install plugin bundle (plugin/ directory) that auto-wires the MCP server, hooks, and slash-command skills. First launch in an uninitialized project auto-creates .engram/ and seeds from git history without modifying the user's tracked CLAUDE.md (agent guidance rides on the MCP server's instructions field and plugin SKILL.md files instead). Python CLI stays first-class for headless/automation use. Currently ships /engram:briefing; /engram:post-decision, /engram:query, /engram:checkpoint-save, /engram:checkpoint-restore land next. Also in this cycle: the event-lifecycle tools (resolve/supersede/reopen) are now exposed over MCP, not just the CLI, and events gain an optional area tag (schema v6) for grouping work by concept independent of file scope. See plugin/README.md and docs/ROADMAP.md for scope.
Next after v1.7 — Hierarchical summarization, conflict detection, outcome tracking
See docs/ROADMAP.md for the full prioritized roadmap with 15 planned features.
MIT — see LICENSE.