Local-first persistent temporal memory for Claude. A Model Context Protocol (MCP) server that gives Claude long-term memory across conversations with automatic tiering, semantic search, and self-maintenance.
Claude forgets everything between conversations. Ember fixes that with:
- 5-tier temporal memory — working, session, relational, knowledge, glacier — each with different decay rates and promotion thresholds
- Shadow-decay scoring (HESTIA) — contradicted or stale memories fade instead of being deleted, preventing retrieval of outdated context
- Knowledge layer — canonical facts that never decay (API keys, project conventions, business rules)
- Self-maintenance — automated health checks, healing, and quality scorecards
- Semantic search — vector similarity with FTS5 keyword fallback
- Knowledge graph — directed edges between memories for relationship traversal
- Fully local — single SQLite file at
~/.ember-v3/ember.db, no cloud dependency
┌─────────────────────────────────────────┐
│ MCP Interface │
│ 27 tools + 5 aliases │
├─────────────────────────────────────────┤
│ Analytics Layer │
│ Usage insights · Adaptive importance │
├─────────────────────────────────────────┤
│ Self-Maintenance Layer │
│ Scorecard · Heal · Delta │
├─────────────────────────────────────────┤
│ Knowledge Layer │
│ Canonical facts · Gap detection │
├─────────────────────────────────────────┤
│ Core Memory │
│ HESTIA scoring · Shadow-decay · KG │
├─────────────────────────────────────────┤
│ SQLite + Embeddings (MiniLM-L6) │
└─────────────────────────────────────────┘
Inspired by HOPE/Nested Learning (NeurIPS 2025). Memories promote upward based on access patterns and importance.
| Tier | TTL | Decay/Day | Promotes To | Promotion Threshold |
|---|---|---|---|---|
| working | None | 0.0 | session | importance >= 0.7 |
| session | 30 days | 0.033 | relational | access_count >= 3 |
| relational | 180 days | 0.006 | glacier | 90 days + stable + 5+ accesses |
| knowledge | None | 0.0 | — | Canonical facts, no decay |
| glacier | None | 0.0 | — | Permanent archive |
Hierarchical Ember Scoring for Temporal Information Access. Used for all recall operations.
score = similarity * shadow_penalty * (0.6 + 0.3 * importance + 0.1 * recency)
where:
similarity = cosine similarity between query and memory embedding (0-1)
shadow_penalty = (1.0 - shadow_load) ^ 2.0
importance = user-assigned or auto-adjusted importance (0-1)
recency = max(0, 1 - age_seconds / 7776000) # decays over 90 days
The 0.6 baseline ensures low-importance memories still surface when highly similar. Shadow load quadratically penalizes contradicted memories.
| Tool | Description |
|---|---|
ember_store |
Store a memory with optional tier, importance, tags, and status |
ember_recall |
Semantic search with tier/status/importance filters |
ember_read |
Read full content of a specific memory by ID |
ember_learn |
Auto-capture facts, decisions, preferences from conversation |
ember_update |
Update content, tier, importance, tags, or status of a memory |
ember_remove |
Shadow (soft) or delete (hard) a memory, with optional replacement |
ember_list |
List memories with filtering and pagination |
| Tool | Description |
|---|---|
ember_auto |
Auto-retrieve relevant memories at conversation start (knowledge-first) |
ember_deep_recall |
Recall memories AND read their source files for full context |
ember_actionable |
List all memories with active status (open/in_progress/done) |
ember_checkpoint |
Save or resume task state (CORAL checkpointing) |
ember_session |
Save session summary or close session with tier promotion |
| Tool | Description |
|---|---|
ember_knowledge |
Store/list canonical facts, detect knowledge gaps |
ember_graph_search |
Vector search followed by BFS traversal of knowledge graph |
ember_consolidate |
Merge 2+ related memories into a single consolidated memory |
| Tool | Description |
|---|---|
ember_health |
Memory health metrics — counts per tier, shadow load, health score |
ember_scorecard |
Self-assessment of recall accuracy, staleness %, quality metrics |
ember_heal |
Auto-detect and fix issues — shadow, TTL, orphans, missing embeddings |
ember_delta |
Track memory evolution over 7d/30d/90d periods |
| Tool | Description |
|---|---|
ember_insights |
Usage patterns — tag effectiveness, shadow dynamics, access patterns |
ember_set_status |
Update memory status (open/in_progress/done) |
ember_contradict |
Correct outdated info — shadow old, store corrected, create edge, flag related |
ember_inspect |
Detailed system inspection — per-tier stats, embedding coverage, top tags, DB size |
ember_drift_check |
Voronoi-based drift detection across memory cells (flags only, no auto-shadow) |
ember_compact |
Two-step compaction — analyze candidates, then apply with merged content |
ember_recompute_shadows |
Recompute shadow_load from near-duplicate density per tier |
ember_explain |
Full memory metadata + HESTIA score breakdown for a query |
These still work but will be removed in a future version:
| Alias | Use Instead |
|---|---|
ember_discard |
ember_remove(permanently=False) |
ember_delete |
ember_remove(permanently=True) |
ember_resume |
ember_checkpoint(action="load") |
ember_session_close |
ember_session(action="close") |
ember_save_session |
ember_session(action="save") |
Memories can be connected via directed edges for relationship traversal.
edges(source_id, target_id, edge_type, created_at)
Edge types are free-form strings (e.g., "contradicts", "depends_on", "child_of"). There is no validated enum — any string is accepted.
ember_graph_search performs vector similarity first, then BFS traversal up to configurable depth with optional edge type filtering.
Edges can be created:
- Via
ember_store(edges="target_id:edge_type,target_id:edge_type") - Via
ember_contradict(automatically creates "contradicts" edges) - Programmatically by internal operations (consolidation, knowledge linking)
Canonical, never-decay facts organized by category:
| Category | Examples |
|---|---|
infrastructure |
API endpoints, database schemas, system configs |
domain |
Business rules, domain terminology, product specs |
disambiguation |
Clarifications of ambiguous terms/names |
convention |
Code style, naming patterns, workflow preferences |
lesson |
Debugging insights, performance lessons |
Stored at tier="knowledge" with importance=1.0. No TTL, no decay.
When storing a memory with default importance (0.5) and non-empty tags, Ember auto-adjusts based on tag history:
adjusted = avg_importance_for_tag - (shadow_rate * 0.3)
clamped to [0.1, 1.0]
Tags with high shadow rates get lower importance. Tags with consistently durable memories get higher importance. Requires 3+ existing memories with the same tag to activate.
- Python 3.11+
sentence-transformers(for semantic search; falls back to FTS5 keyword search if unavailable)
cd ember-v3
pip install -r requirements.txtAdd to your MCP client configuration (e.g., Claude Desktop, Cursor):
{
"mcpServers": {
"ember": {
"command": "python",
"args": ["/path/to/ember-v3/ember/ember_server.py"]
}
}
}The server runs in stdio mode for MCP clients:
python ember/ember_server.pyRecommended conversation workflow:
- Start: call
ember_autoto load relevant context - During: use
ember_learnfor auto-capture,ember_storefor explicit saves - End: call
ember_session(action="save")to persist session summary
Ember registers 3 MCP prompts that MCP clients can surface to users:
| Prompt | Description |
|---|---|
start_session |
Instruction to call ember_auto at conversation start |
end_session |
Instruction to call ember_session to save state |
remember |
Instruction to call ember_store with tier guidance |
The server doubles as a CLI for administrative tasks:
python ember/ember_server.py status # System status (tier counts, DB size)
python ember/ember_server.py migrate # Migrate from v1 database
python ember/ember_server.py migrate --dry-run # Preview migration
python ember/ember_server.py migrate --embed # Migrate + embed all memoriesSingle SQLite file at ~/.ember-v3/ember.db. Core tables:
memories— main store with embeddings, tiers, shadow loadsessions— lifecycle tracking with checkpointsedges— knowledge graph (source, target, type)knowledge_facts— canonical facts by categoryconsolidation_log— promotion/merge audit trailmetrics_log— analytics event logworkflow_runs— self-maintenance audit trailmemories_fts— FTS5 full-text search index
- Model:
all-MiniLM-L6-v2(384 dimensions, ~90MB) - Library:
sentence-transformers - Similarity: Cosine (L2-normalized vectors)
- Fallback: FTS5 keyword search when sentence-transformers is not installed
Shadow-decay prevents retrieval of outdated information without destroying it:
- When information is contradicted, the old memory's
shadow_loadincreases - HESTIA scoring quadratically penalizes shadowed memories:
(1 - shadow_load)^2 - Heavily shadowed memories effectively disappear from recall results
- The data remains in the database for audit/recovery
This is more nuanced than hard deletion — partially outdated memories fade gradually rather than vanishing.
MIT