ember-4
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@ember-4what do you remember about our last conversation on the API design?"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
ember-4
Persistent memory for Claude instances — graph-aware retrieval over a single SQLite database, using Nomic-Embed-Text-v1.5 for semantic embedding and BM25 (via SQLite FTS5) for lexical retrieval. Designed as the successor to ember-3 (the HESTIA/MiniLM-based memory system).
What changed from ember-3
Nomic-Embed-Text-v1.5 with task-prefix discipline — separate vector spaces for clustering (
clustering:) and retrieval (search_document:/search_query:). Same text in different roles produces different vectors; this is a feature, not a footgun.Graph recall — dense (Nomic) and lexical (BM25) seeds, fused with RRF, teleport into personalized PageRank over the memory graph. PPR widens the candidate set; the final score blends dense, BM25, engagement (cond_activity) and a small PPR term, then applies recency demotion. Memories superseded by
ember_contradictare left out unless you ask for historical recall (include_stale=True).Update-activity importance signal — replaces ember-3's
cell_vitality/shadow_load. Has a strict contribution filter:(event_type, origin)distinguishes substantive engagement from system- initiated bookkeeping, preventing the basin-pathology feedback loop the old system silently relied on.Tag-cohort edges — pseudo-tags extracted from ember names by regex (project / type / version patterns) create explicit project-cohort adjacency that the kNN graph alone under-samples.
Query preparation — proper English + corpus-specific stop-word filtering, OR-with-BM25-ranking instead of implicit AND. Applies to both ember recall and archive full-text search.
See MIGRATION.md for the in-place ember-3 → ember-4 cutover procedure.
Related MCP server: NEXIA Consciousness Engine
Fresh install on a new machine
# Clone
git clone https://github.com/anomalous3/ember-4-memory.git ~/.ember4-src
cd ~/.ember4-src
# Venv (uv recommended; pip works too)
uv venv .venv --python 3.12
uv pip install --python .venv/bin/python3 -e .
# Data directory — by default ~/.ember4/, overridable via EMBER4_DATA_DIR.
# Models cached here too; ~140MB Nomic int8 ONNX downloaded on first use.
mkdir -p ~/.ember4
# Option A: start fresh (empty memory)
.venv/bin/python3 -c "
import asyncio
from ember4.db import Database
async def init():
db = Database()
await db.connect()
await db.close()
asyncio.run(init())
"
# Option B: migrate from an existing ember-3 database (online backup;
# safe to run while ember-3 is still serving requests)
EMBER3_DB=$HOME/.ember/ember3.db # adjust if your ember-3 lives elsewhere
.venv/bin/python3 -c "
import sqlite3
src = sqlite3.connect('$EMBER3_DB')
dst = sqlite3.connect('$HOME/.ember4/ember4.db')
with dst: src.backup(dst)
src.close(); dst.close()
print('ember-3 → ember-4 data copy complete')
"
# Run the post-install migrations (idempotent; --dry-run available)
.venv/bin/python3 ember4_migrate_update_log.py # schema additions
.venv/bin/python3 ember4_migrate.py --force # Nomic vectors
.venv/bin/python3 ember4_build_fts.py # BM25 index
.venv/bin/python3 ember4_build_graph.py # kNN + temporal
.venv/bin/python3 ember4_build_tag_edges.py # project-cohort (patterns: tag_patterns.example.json)
.venv/bin/python3 ember4_rebuild_stopwords.py # corpus stop words
# Smoke test
.venv/bin/python3 ember4_test_wireup.py
# Expected: ✓ Wire-up smoke test PASSED
# Inspect baseline state
.venv/bin/python3 ember4_cli.py countMCP server registration
Claude Code: edit ~/.claude.json (or ~/Library/Application Support/Claude/
on macOS) to register the ember-4 MCP server:
{
"mcpServers": {
"ember": {
"command": "/absolute/path/to/.ember4-src/.venv/bin/python3",
"args": ["-m", "ember4"],
"env": {
"EMBER4_READ_ONLY": "0"
}
}
}
}EMBER4_READ_ONLY=0 is critical — the freeze flag exists for development
and would block all writes if left set at production.
If you want multiple ember instances (e.g., separate memory for
different agents on the same machine), use distinct EMBER4_DATA_DIR
values and register them under different MCP server names:
{
"mcpServers": {
"ember-primary": {
"command": "...",
"args": ["-m", "ember4"],
"env": {"EMBER4_DATA_DIR": "/home/me/.ember4-primary"}
},
"ember-scratch": {
"command": "...",
"args": ["-m", "ember4"],
"env": {"EMBER4_DATA_DIR": "/home/me/.ember4-scratch"}
}
}
}Each instance gets its own DB, its own model dir, its own update_log.
Claude Code hooks (optional)
ember4/hooks/ keeps full session transcripts in the archive, so
archive_search / archive_read can reach back past a compaction or into an
earlier session. Register them in ~/.claude/settings.json with absolute paths
($SRC below is your clone):
Event | Command | What it does |
|
| Archives the transcript before compaction; prints one status line |
|
| Archives the transcript on exit (forks, so exit isn't delayed) |
|
| Records when the turn ended |
|
| Adds |
{
"hooks": {
"PreCompact": [{"hooks": [{"type": "command", "timeout": 30,
"command": "/abs/path/.ember4-src/.venv/bin/python3 /abs/path/.ember4-src/ember4/hooks/pre_compact_export.py"}]}]
}
}Raw JSONL copies go to <data dir>/archive/exports/. Transcripts land in the
same database the MCP server reads; a session run from a directory listed in
<data dir>/persona_stores.json ({"<home dir>": "<data dir>"}) is archived
to that store instead.
Configuration knobs
Env var control:
Variable | Default | Purpose |
|
| Override data directory (DB + models) |
| unset (read-write) | Set to |
Recency in ember4/config.py: RECENCY_STRENGTH (0.75) and RECENCY_TAU_DAYS
(21) demote embers whose last creation or content edit is old, so a superseded
approach doesn't rank as if current. Embers tagged foundation or principle
are exempt. A per-project override lives in the DB config table under
recency_strength:<project>; deep_recall and wonder reach back with strength 0.
Code-side weights in ember4/recall_v4.py:
FEATURE_WEIGHTS: relative contribution of dense / BM25 / cond_activity / PPREDGE_TYPE_WEIGHTS: per-type stochastic-matrix mix for the graph traversalPPR_ALPHA: restart probability (0.25)RRF_K: rank-normalization damping constant (60; standard from Cormack et al.)
See recall_v4.py for the empirical rationale behind each.
Directory layout
~/.ember4-src/ ← this repo
ember4/ ← package
__init__.py
__main__.py ← MCP entry point (python -m ember4)
config.py
db.py ← schema, queries, log_update
embedder.py ← Nomic + MiniLM-L6 specs
query_prep.py ← BM25 stop-word handling
recall_v4.py ← graph-based retrieval pipeline
server.py ← MCP tools
utils.py
hooks/ ← optional Claude Code hooks (see above)
ember4_*.py ← migration / build / test scripts
tag_patterns.example.json
pyproject.toml
README.md ← this file
MIGRATION.md ← ember-3 → ember-4 cutover plan
~/.ember4/ ← per-machine data (NOT in git)
ember4.db ← SQLite DB
tag_patterns.json ← your project pseudo-tag regexes (optional)
archive/exports/ ← raw JSONL transcript copies (from the hooks)
models/
nomic-embed-text-v1.5/ ← downloaded on first embedder use
all-MiniLM-L6-v2/ ← legacy, kept for back-compatStatus
ember-4 is the live memory system on our machines (cut over 2026-05-25).
Live recall (ember_recall) runs the graph engine in recall_v4.py:
dense + BM25 + conditioned activity, rank-fused, with recency demotion.
An ablation on our corpus confirmed
dense + BM25 + cond_activitymatches the ember-3 baseline on a diagnostic benchmarkCold start: an empty update_log contributes nothing and the remaining weights redistribute proportionally
Write paths log to update_log with
(event_type, origin, content_changed)so bookkeeping never counts as engagementArchive full-text search and v4 BM25 share one stop-word + OR-with-BM25-ranking pipeline
The smoke tests create and delete their own test embers, so they run on any store.
License
MIT. See LICENSE.
This server cannot be deployed
Maintenance
Related MCP Connectors
Persistent, outcome-grounded episodic memory for Claude. 14ms CPU retrieval, no GPU, no vector DB.
Persistent memory for AI assistants: store, search, and connect knowledge across conversations.
Persistent memory for AI agents to retain, retrieve, and recall conversation context through MCP.
Portable AI memory you own. Keep memories and notes across Claude, ChatGPT, and other AI tools.
Related MCP Servers
- AlicenseBqualityFmaintenanceA persistent memory implementation using a local knowledge graph that lets Claude remember information about users across conversations.96MIT
- -licenseNot gradedqualityNot gradedmaintenanceProvides Claude Desktop with persistent memory across sessions, storing up to 10,000 memories with semantic search and automatic context bridging. Features temporal versioning and anti-degradation protocols to maintain conversation continuity.-
- AlicenseNot gradedqualityCmaintenanceA persistent memory system using a local knowledge graph that enables Claude to remember information about users across chats, with advanced search, graph traversal, and filtering capabilities for entities, relations, and observations.MIT
- FlicenseAqualityDmaintenanceEnables Claude to maintain persistent memory across conversations using a local knowledge graph with fuzzy search capabilities, allowing it to remember and recall information about users, relationships, and context.9-