perseus vault

Perseus Vault는 AI 에이전트가 세션 간에 지속적인 메모리를 유지할 수 있게 해주는 단일 Rust 바이너리입니다. 하나의 바이너리, 하나의 파일. Docker도, Postgres도, 클라우드도 필요 없습니다. 모든 MCP 호스트와 호환되는 지속적인 메모리만 제공합니다.

문서

Perseus Vault — Persistent Memory. Encrypted, local-first, one portable file.

Perseus Vault

Persistent, encrypted memory for AI agents. One Rust binary, one file, no cloud.

License: MIT Rust Version LangGraph CrewAI AutoGen MCP Tools Listed on mcpservers.org

Give your agents memory that survives the session, so they stop re-deriving what they already learned and stop repeating past mistakes. Hybrid recall (BM25 + dense + RRF), bi-temporal history, and AES-256-GCM at rest, exposed as 55+ MCP tools that work with any host. 73.8% on LongMemEval's official harness (vs Zep 63.8%, Mem0 49.0%). One binary. One file. No Docker. No Postgres. No cloud. Local-first, air-gap ready, MIT.

One-Line Install

curl -sSf https://raw.githubusercontent.com/Perseus-Computing-LLC/perseus-vault/main/scripts/install.sh | sh

That's it. Perseus Vault is installed to ~/.local/bin/perseus-vault. Start it:

perseus-vault serve --db ~/.mimir/data/perseus-vault.db

macOS note (Apple Silicon). A freshly built or copied binary is SIGKILLed on first run (Killed: 9, no other output) by the OS binary policy — even with no quarantine attribute. The one-line installer and the bootstrap.sh build-from-source installer ad-hoc code-sign Perseus Vault for you. If you build the binary yourself, sign it once after each rebuild:

cargo build --release
cp target/release/perseus-vault ~/.local/bin/perseus-vault
codesign --force --sign - ~/.local/bin/perseus-vault   # required on Apple Silicon; fixes "Killed: 9"

--force re-signs an already-signed binary (needed after every rebuild); the step is harmless on Intel macOS and unnecessary on Linux/Windows.

Then wire your MCP client(s) — and the full recall/capture loop — in one command:

perseus-vault install-client --hooks --rules

This autodetects Claude Code / Codex / Cursor (pass --client <name> for claude-desktop, hermes, windsurf, vscode, zed, or generic; --all-detected wires every detected client), merges the MCP server registration into the client's config without clobbering anything (a .bak-perseus backup is written first), points every client at one shared memory database, registers the session lifecycle hooks (recall injection on SessionStart, hygiene on session end — the docs/lifecycle-hooks.md contract), and appends the memory usage rules to CLAUDE.md/AGENTS.md. Re-running is a no-op; add --dry-run to preview every file it would touch.

Or connect any MCP host by hand (Claude Desktop, Cursor, Hermes Agent, Perseus, etc.):

{
  "mcpServers": {
    "perseus-vault": {
      "command": "perseus-vault",
      "args": ["serve", "--db", "~/.mimir/data/perseus-vault.db"]
    }
  }
}

30-Second Quickstart

# Start Perseus Vault
perseus-vault serve --db memory.db &
sleep 1

# Remember a fact (via MCP JSON-RPC on stdio)
echo '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"mimir_remember","arguments":{"category":"demo","key":"hello","body_json":"{\"text\":\"Hello from Perseus Vault!\"}"}}}' | perseus-vault serve --db memory.db

# Search for it
echo '{"jsonrpc":"2.0","id":2,"method":"tools/call","params":{"name":"mimir_recall","arguments":{"query":"Hello"}}}' | perseus-vault serve --db memory.db

Works With Every MCP Client

Perseus Vault is a standard MCP stdio server — the same perseus-vault serve command works everywhere. Run perseus-vault doctor to validate your install and print this matrix locally.

ClientStatusConfig
Claude Desktopclaude_desktop_config.json
Claude Code / Hermes.mcp.json / config.yaml
Cursor.cursor/mcp.json
Windsurfmcp_config.json
VS Code + Continue.devconfig.json
Zedsettings.json
Codex CLI~/.codex/config.toml

Copy-paste config snippets for each: docs/clients/.

Then wire the recall → work → capture → consolidate loop to your client's session events (SessionStart/Stop hooks for Claude Code, Codex, and Cursor, plus a portable AGENTS.md fallback): docs/lifecycle-hooks.md.

Composing with a memory washer (CoalWash) and a runtime output compactor (Noisegate) for end-to-end context-budget control: docs/integration/context-budget-stack.md.

Why Perseus Vault

Perseus Vault is the only memory engine that is simultaneously MCP-native, local-first, zero-dependency, AND agent-first.

LongMemEval QA (official harness)

Recall quality measured on LongMemEval's official harness, not a home-grown script:

Memory engineQA accuracy
Perseus Vault73.8%
Zep63.8% (published)
Mem049.0% (published)

longmemeval_s (500 questions), gpt-4o-2024-08-06 answerer + LongMemEval's official judge; competitor numbers are their published values. Perseus Vault's 73.8% is the plain mean of 3 runs; 79.0% with official CoT. Methodology & content-hashed (sha256) results →

Bi-temporal time-travel (three-axis)

Our strongest structural differentiator — full SQL:2011 bi-temporal history (transaction-time and valid-time) — measured against a reproducible, fully offline gauntlet. It drives the real shipped binary over MCP stdio through the hard cases single-axis competitors get wrong (retroactive corrections, proactive future-dated facts, out-of-order arrival, belief-vs-truth divergence, closed periods):

AxisQuestion it answersChecksPass
valid-time (valid_at)"what was true in the world at T"1010
transaction-time (as_of)"what did we believe at T"11
bi-temporal (bitemporal)"as of belief at T, what was true at V"22
Total1313 (100%)

Reproduce with a single command (no API key, no network, no LLM):

cargo build --release
python benchmark/temporal/gauntlet.py --bin target/release/perseus-vault

The PASS/FAIL verdicts are deterministic (wall-clock timestamps vary, verdicts do not), so a correct build re-runs to an identical signature_sha256. The committed gauntlet_report.json is the reference. Methodology & dataset →

Comparison Matrix

Perseus VaultMem0LettaZep
DeploymentSingle binaryCloud + self-hostDocker/PostgresDocker/Neo4j
DependenciesNone (SQLite embedded)Python + vector DBPostgres + PythonNeo4j + Go (Graphiti)
MCP-Native✅ 55+ tools❌ Not MCP-native❌ Not MCP-native❌ Not MCP-native
Offline/Local✅ Fully localCloud-dependentDocker neededDocker needed
EncryptionAES-256-GCM ✅
Hybrid SearchBM25 + Dense + RRFVector onlyVector onlyVector + Graph
Entity LifecycleDecay + Promote + Archive
Entity GraphLink + Traverse
Journal Audit Trail✅ Immutable
State Management✅ Key-value + TTL
MCP Tools55+580
LicenseMITApache 2.0Apache 2.0Apache 2.0

Full comparison: Perseus Vault vs Mem0 → vs Letta → vs Zep →

Stress Test: 100K Entities

Perseus Vault handles production workloads on modest hardware. The numbers below are from the committed artifact benchmark/scale/report.json: the real release binary driven over MCP stdio (one persistent process per corpus size), AMD64 16-core, Windows 11, every write durable before the next is sent.

Metric10K100K
Write throughput, sustained (MCP stdio)479 docs/s40 docs/s
Hybrid recall p5019.03 ms79.73 ms
FTS5 recall p503.14 ms15.67 ms

Full percentiles, as_of point lookups, temporal recall, and cold-start numbers are in benchmark/scale/.

Run it yourself: python benchmark/scale/run.py

Recall Accuracy at Scale: Keyword Collapses, Hybrid Holds

Speed is table stakes — the question that matters for agent memory is does the right memory actually surface? Measured on distinct-content corpora (first-party, reproducible; see benchmark/lambda/), recall@k by mode:

100,000 entities (1×H100, nomic-embed-text on Ollama):

recall@kkeyword (BM25/FTS5)densehybrid (RRF)
@10.0030.6800.785
@50.0150.8591.000
@100.0290.8991.000

At 100K entities, hybrid recall is perfect @5 while keyword search lands ~1.5% of the time — a ~66× gap. And it widens with scale: at 10K entities keyword recall@5 was 0.008 while hybrid was already 1.000; keyword-only memory silently degrades as an agent accumulates history, hybrid (BM25 + dense + reciprocal-rank fusion) does not. This is the core argument for Perseus Vault's hybrid retrieval.

Head-to-head, same box, same corpus, all fully local (1×H100, Ollama — identical fact set, queries, and substring judge for every system):

SystemRecall accuracyp50 latencyNotes
Perseus Vault (hybrid)1.0035.6 mssingle self-contained binary, in-process
Letta (archival / pgvector)1.00135.5 msserver + Postgres/pgvector
Mem0 (vector)0.6037.9 msPython + vector DB
Zep (Graphiti temporal KG)0.2049.7 msserver + Neo4j; graph extracted by local model

Every competitor was stood up and run live on the same box against the same local Ollama (qwen2.5:14b-instruct + nomic-embed-text) — no cloud, no fabricated numbers. Letta ran as the letta/letta server (bundled Postgres/pgvector) and matched Perseus Vault at 1.00. Zep's self-hosted Community Edition server is deprecated and its zep_python memory API is now Zep Cloud-only, so we measured Zep's actual OSS engine — Graphiti temporal KG on Neo4j — with entity/edge extraction and embeddings on the same local Ollama. Its 0.20 reflects the honest cost of building a knowledge graph with a local model (structured extraction is lossy: 5 entities / 2 edges from 6 facts) — not Zep Cloud, which uses frontier models. Full artifact + methodology: benchmark/lambda/results/competitors.json.

Cold-start: a bare GPU box reaches its first grounded RAG answer in 3.3s (models staged on disk).

Reproduce: benchmark/lambda/scale_bench.py and competitors_bench.py.

Deploying beside a model server on a GPU host (vLLM on MI300X/H100)? See the AMD MI300X deployment reference — measured co-residency numbers plus the /dev/shm, PID-1, and version-pinning gotchas that break these stacks in practice.

Framework Integrations

Ready-to-use adapters that make Perseus Vault the default memory backend for popular AI agent frameworks:

FrameworkIntegrationType
LangGraphMimirStoreBaseStore implementation
CrewAIMimirMemoryToolAgent tool
AutoGenMimirMemoryMemory implementation

Each adapter:

  • Connects via MCP stdio subprocess (persistent session)
  • Maps the framework's memory interface to Perseus Vault tools
  • Comes with a README quickstart (5 minutes to working)
  • Has passing tests with mocked MCP transport

Any MCP-compatible framework works with Perseus Vault directly. See Awesome Mimir for the full list.

55+ MCP Tools

Tool names & the perseus_vault_ prefix. The tables below use the historical mimir_* names, but by default the server now advertises each tool once, under its canonical perseus_vault_* name (e.g. perseus_vault_remember). The legacy mimir_* and mneme_* names remain fully callable — every prefix dispatches to the same handler — they are just no longer advertised in tools/list. This keeps the advertised manifest to one name per tool instead of tripling it (3× alias bloat), so connected clients don't reload a tripled tool-schema payload on every request. To restore the historical behaviour of advertising all three prefixes, set PERSEUS_VAULT_TOOL_ALIASES=all (the legacy env MIMIR_TOOL_ALIASES is also honoured; PERSEUS_VAULT_ takes precedence).

Client compatibility (#633). Clients that gate on the advertised list — they check tools/list before calling and skip tools they don't see — will silently skip legacy mimir_* calls against a 2.x vault even though the call itself would succeed. Known case: the perseus CLI ≤ 1.0.22 hard-codes mimir_recall and degrades to empty local-only recall. Fix either side: upgrade the CLI to ≥ 1.0.23 (calls canonical names, with dynamic fallback), or set PERSEUS_VAULT_TOOL_ALIASES=all on the vault as a bridge while older clients remain deployed.

Entity CRUD

ToolDescription
mimir_rememberStore/update entity. Idempotent by (category, key); a content change snapshots the prior version into history.
mimir_recallSearch with FTS5/dense/hybrid modes, filters, stemming expansion. Query contract (#562): query="" is match-all enumeration (the "list all" path); "*" and other wildcards are literal FTS5 terms, not globs — "*" matches nothing.
mimir_scanDeterministic paginated enumeration of a category or the whole store (#562): immutable id ASC keyset pages with a next_cursor/has_more contract, so export/sync/reset callers can walk every entity exactly once. Read-only — no retrieval-count/decay side-effects, no offset cap.
mimir_hygieneRead-only startup-memory hygiene report (#675): scores active memories by "actionability" (concrete anchors — issue keys, #refs, paths, URLs, decisions — vs vague/date-only/short) and lists the worst offenders with reasons, for archive/consolidate curation.
mimir_recall_layerRecall from a specific biomimetic layer (world, episodic, semantic).
mimir_recall_whenProactive just-in-time recall: surface entities whose recall_when triggers match.
mimir_get_entityFetch one entity by ID with full body_json.
mimir_as_ofTransaction-time time-travel: the version of a fact (category + key) that was believed at a past instant.
mimir_valid_atValid-time lookup: the version that was actually true in the world at an instant, per current knowledge (SQL:2011 APPLICATION_TIME).
mimir_bitemporalFull 2-axis bi-temporal query: "as of transaction time T, what did we believe was true at valid time V" — the exact rectangle cell.
mimir_historyList superseded versions of a fact (category + key), newest first — paginated (limit default 20, plus offset); total reports the full trail size (companion to mimir_as_of).
mimir_forgetSoft-delete (archived=1).

Search & RAG

ToolDescription
mimir_askRAG: recall context, query LLM, return grounded answer with sources.
mimir_embedGenerate dense vectors via the bundled model, Ollama, or OpenAI-compatible endpoint.
mimir_semantic_searchDense-only semantic search shortcut — find entities by meaning, ranked purely by embedding similarity (no keyword fallback).
mimir_contextPre-formatted markdown block for session injection. Recall-first by default: pass query (the current task/message) and only topically relevant entities are injected, clamped to a per-model budget; the legacy unconditional dump requires mode: "always_inject".
mimir_ingestTrigger connector syncs (GitHub, file watcher).
mimir_ingest_fileLocally extract a document's text (plaintext/markdown always; DOCX/PDF with the multimodal feature) and store it as a recallable entity.
mimir_extractLocal, deterministic, rule-based knowledge extraction (facts / preferences / temporal events / episodes) from text or a stored entity. Read-only.
mimir_captureOpt-in in-session capture (#520): distill a transcript/insight payload (text, markdown, or JSONL) into durable entities (root-cause / pitfall / decision / pattern / takeaway) the moment a problem is solved. Local rule-based distiller by default, optional llm: true with graceful fallback; near-dup merging stays ON plus a per-invocation cap (anti-flood). Also a CLI verb: perseus-vault capture.
mimir_memoriesAnthropic memory-tool compatible file interface (view/create/str_replace/insert/delete/rename under /memories), backed by vault entities.

📖 docs/retrieval-modes.md — one enumerated reference for every retrieval mode (keyword · dense · hybrid · graph · GraphRAG · proactive recall_when · temporal as_of): mechanism, when to use, invocation, and examples.

Graph

ToolDescription
mimir_linkCreate typed relationship links between entities.
mimir_unlinkRemove entity links.
mimir_traverseWalk entity link graph up to configurable depth.
mimir_communitiesGraphRAG community detection over the link graph (deterministic label propagation or greedy-modularity "louvain"; pure Rust, offline).
mimir_community_summaryExtractive (optionally LLM-polished) summary of one community, materialized as an entity with evidence_for links to members.
mimir_global_recallGraphRAG global search: breadth over community summaries, then depth into the best communities' members — holistic answers across clusters.

Journal

ToolDescription
mimir_journalAppend structured event with actor attribution.
mimir_check_failure_patternDeja-vu guard: check an action against previously recorded failures (journal + failure/pitfall entities) before retrying it. Read-only.
mimir_timelineQuery journal by time range with filters.

State

ToolDescription
mimir_state_setSet key-value state with optional TTL.
mimir_state_getGet state value. Returns null if expired.
mimir_state_deleteDelete state entry.
mimir_state_listList state keys, optionally filtered by prefix.

Lifecycle

ToolDescription
mimir_decayRecalculate Ebbinghaus decay scores (batched 1000-entity transactions).
mimir_pruneBulk archive by category, decay threshold, or age.
mimir_purgePermanently delete archived entities + VACUUM. Destructive.
mimir_cohereAutonomous coherence grooming pass — promote, decay, link, archive.
mimir_autocohereFull atomic grooming: cohere → decay → compact in one pass (supports dry-run).
mimir_compactArchive entities below decay threshold.
mimir_reindexRebuild FTS5 search index from entities table.
mimir_consolidateMerge overlapping/duplicative entities in a category into durable, evidence-tracked observations (mirror image of mimir_conflicts).
mimir_dreamSleep-time LLM consolidation: reflect over clusters of related episodic memories via the configured LLM and write back durable semantic insights, provenance-linked to every source. Idempotent (evidence-set hash), contradiction-aware, bounded; requires --llm-endpoint.

Quality

ToolDescription
mimir_scoreAssign quality score (0.0-1.0).
mimir_conflictsDetect conflicting entities via trigram similarity; opt-in resolve=true invalidates the lower-certainty side into history (reversible, dry-run by default).
mimir_correctStructured correction capture for learning from errors.
mimir_supersedeMark a new fact as superseding an old one (sets the old entity to deprecated).
mimir_followRecord whether an entity was actually FOLLOWED or MISSED — follow-rate efficacy signal that feeds both decay scoring and outcome-weighted recall ranking (#681).

Keystones (policy rules)

ToolDescription
mimir_keystone_setAuthor a Keystone — a mandatory policy rule that survives context compaction (#683). Scoped (tenant/fleet/agent), weight-ranked, crypto-chained on every mutation; authoring is trust-tier-gated.
mimir_keystone_getFetch the merged Keystones for a scope, ordered by weight (highest first) then scope specificity — the deterministic session-start counterpart to recall. A renderer injects these ahead of all other context.
mimir_agentRegister/update or look up an agent in the multi-agent registry (#684): identity + trust tier (0-3) + fleet. Trust tier gates sensitive ops (e.g. authoring keystones needs tier ≥ 2) and drives visibility enforcement on recall.

Vault & Federation

ToolDescription
mimir_vault_exportExport entities to .md files with YAML frontmatter.
mimir_vault_importImport from .md vault directory (idempotent).
mimir_federateCopy entities between workspaces. This is a local export / workspace-rename / re-import (file based, no network peers); the Windows-safe default path is tracked in #704.
mimir_shareShare one entity (by category + key) into another workspace, preserving content.
mimir_workspace_listList all distinct entity categories.

Metrics & Ops

ToolDescription
mimir_statsFull DB statistics across all tables.
mimir_healthServer and DB health check.
mimir_benchPerformance benchmark tracking.
mimir_maintenanceDB maintenance: dedup, orphan detection, VACUUM, FTS5 reindex (supports dry-run).
mimir_synthesizeLLM session synthesis — extract lessons from transcripts.
mimir_migrateMigrate v0.1.x DB to current schema.

CLI

# Server
perseus-vault serve --db /data/perseus-vault.db
perseus-vault serve --web --port 8767 --encryption-key ~/.mimir/secret.key
perseus-vault serve --llm-endpoint http://localhost:11434/api/generate --llm-model llama3
perseus-vault serve --transport sse --port 8787 --mcp-token my-secret-token

# Maintenance (operate directly on DB, no server needed)
perseus-vault stats          --db /data/perseus-vault.db
perseus-vault forget         --db /data/perseus-vault.db --category decision --key stale-choice --reason "superseded"
perseus-vault prune          --db /data/perseus-vault.db --category junk --min-decay 0.1 --dry-run
perseus-vault purge          --db /data/perseus-vault.db --dry-run
perseus-vault decay          --db /data/perseus-vault.db
perseus-vault reindex        --db /data/perseus-vault.db
perseus-vault vault-export   --db /data/perseus-vault.db --vault-dir ./export/
perseus-vault vault-import   --db /data/perseus-vault.db --vault-dir ./export/
perseus-vault obsidian-sync  ~/obsidian-vault/Perseus Vault/          # one-shot export to an Obsidian vault
perseus-vault obsidian-sync  ~/obsidian-vault/Perseus Vault/ --watch  # continuous sync on every memory change

# Key management
perseus-vault keygen --key-file ~/.mimir/secret.key

Manual DB edits. The maintenance verbs above and the normal MCP write path keep the FTS5 index in sync automatically. Editing the entities table directly with sqlite3 (a manual DELETE/UPDATE) bypasses that sync and can leave orphaned index rows — "ghost" recall hits for content that is already gone. After any direct SQL edit, run perseus-vault maintain --db <path> (or perseus-vault reindex) to reconcile the FTS index.

Flags

FlagDescription
--dbSQLite database path (default: ~/.mimir/data/perseus-vault.db)
--webStart web dashboard
--portDashboard port (default: 8767)
--web-bindDashboard bind address (default: 127.0.0.1)
--transportMCP transport: stdio (default), sse, or http
--mcp-tokenBearer token for SSE/HTTP transport auth
--encryption-keyAES-256-GCM key file path
--llm-endpointLLM API endpoint for mimir_ask and embeddings
--llm-modelLLM model name (default: llama3)
--llm-api-keyAPI key for LLM endpoints (OpenAI, Azure, etc.)
--embedding-endpointOpenAI-compatible embedding endpoint
--connectors-configPath to connectors.yaml

Database location

The canonical database path is:

~/.mimir/data/perseus-vault.db

Always pass --db (or set $MIMIR_DB_PATH) in scripts, MCP host configs, and cron/harvest jobs so every invocation targets the same file. When neither is set, Perseus Vault resolves the default in this order and uses the first that already exists (so upgraders and legacy single-user installs are picked up instead of silently starting empty):

  1. ~/.mimir/data/perseus-vault.db — canonical (current name)
  2. ~/.mimir/data/mneme.db — pre-rename
  3. ~/.mimir/data/mimir.db — pre-rename
  4. ~/mimir.db — legacy single-user install location

If none exist, it creates ~/.mimir/data/perseus-vault.db. If more than one of these exists and you did not pass --db/$MIMIR_DB_PATH, Perseus Vault prints a stderr warning naming the chosen file and the others it ignored, so an ambiguous multi-database state is visible rather than silent. Setting --db or $MIMIR_DB_PATH explicitly always wins and suppresses the warning.

Your AI Memory in Obsidian

Perseus Vault is your AI agent's long-term memory — and it doubles as your second brain. Every entity your agent remembers exports to a plain Markdown note with YAML frontmatter, so your AI's memory becomes a navigable personal knowledge base inside the tools you already use: Obsidian, Logseq, or Notion.

# Export your entire memory to an Obsidian vault as linked Markdown notes
perseus-vault obsidian-sync ~/obsidian-vault/Perseus Vault/

# Keep it live — re-export automatically on every memory change
perseus-vault obsidian-sync ~/obsidian-vault/Perseus Vault/ --watch

Open the vault in Obsidian and you get a graph of your agent's knowledge.

WikiLink backlinks. When one entity links to another (via mimir_link or a depends_on / implements / references relationship), the exported note gets a ## Links section with [[WikiLink]] backlinks that resolve natively in Obsidian's graph view:

---
id: cli-de8dfb8364b6
category: architecture
key: api
type: insight
decay_score: 0.5000
---

{"content":"axum service"}

## Links

- [[cli-99756b494c7d|database]] (depends_on)

Links resolve by entity id (notes are written as <id>.md) so they never break, and Obsidian shows the human-readable key as the link label. Open the graph view and your agent's architecture, decisions, and insights become a clickable knowledge map.

--watch polls Perseus Vault's cheap, deterministic state digest on an interval and re-exports only when memory actually changes. It naturally catches every mimir_remember write with no filesystem-watcher dependency and no coupling to the server. Tune the interval with MIMIR_SYNC_INTERVAL_SECS (default: 2s).

Other PKM tools

ToolHow
Obsidianperseus-vault obsidian-sync <vault> — WikiLinks resolve in the graph view out of the box.
LogseqPoint obsidian-sync at your Logseq graph directory. Logseq reads the same [[WikiLink]] syntax and Markdown frontmatter.
NotionRun perseus-vault vault-export, then use Notion's Import → Markdown & CSV to pull the notes in.

Unlike cloud-only "second brain" tools, Perseus Vault runs 100% local, is written in Rust, encrypts at rest with AES-256-GCM, and applies decay scoring so stale memories fade — your knowledge base stays yours and stays fresh.

Features

Semantic Search (on by default)

  • Bundled, in-process embeddings — a quantized all-MiniLM-L6-v2 model (384-dim) is compiled into the binary, so dense/semantic search works with zero config and zero network: no Ollama, no API key, no model download. This is the default build (bundled-embeddings feature).
  • Auto-embed on write (#271)mimir_remember embeds each new (or content-changed) entity synchronously as it is written, using the bundled model. Single-entity embedding is deterministic and LRU-cached, so it is cheap and adds no background tasks. Embedding failures are non-fatal (logged to stderr); the write always succeeds.
  • Hybrid is the default recall mode (#271)mimir_recall(query=...) with no mode flag automatically selects hybrid (dense + keyword fused via RRF) whenever embeddings exist, and transparently falls back to fts5 keyword search when none do. No manual mimir_embed step, no flags to remember.
  • mimir_semantic_search(query, limit) — a one-tool shortcut for pure dense, meaning-based search (no keyword fallback) when you just want "find things like this".
  • Optional alternate embedder — to use Ollama or any OpenAI-compatible /v1/embeddings endpoint instead of the bundled model, set --llm-endpoint (and --embedding-endpoint / --llm-api-key as needed). This is entirely optional; the bundled model is used by default.
  • Build a lean binary without bundled embeddings via cargo build --no-default-features — recall then defaults to keyword search unless a remote embedder is configured.

Hybrid Search internals

  • FTS5 keyword search with LIKE fallback and Porter stemming expansion
  • Dense vector search via cosine similarity on stored embeddings
  • Reciprocal Rank Fusion (RRF) — combine keyword + vector results
  • Query expansion — automatic stemming variants for broader recall

Memory Lifecycle

Perseus Vault models memory using three biomimetic layers, inspired by human memory pathways:

  • World (Core): Slow-decaying, global facts about the environment.
  • Episodic (Buffer): Fast-decaying, session-specific interaction history.
  • Semantic (Working): Medium-decaying, general knowledge and learned concepts.

You can interact with these layers directly using the mimir_recall_layer tool or by specifying the layer parameter in mimir_remember.

  • Ebbinghaus decay — memories naturally fade unless retrieved (refresh on access)
  • Layer promotion — buffer → working → core based on access frequency
  • Automatic archival — stale entities archive; purge to permanently delete + VACUUM
  • Always-on entities — pin identity-critical memories for session injection (hard-capped under recall-first; prefer recall_when triggers)

Recall-First Context Injection

The vault is the query layer — it retrieves the few facts a turn needs instead of handing the host a standing blob to staple into every system prompt. mimir_context and perseus-vault prepare are recall-first by default:

  • Relevance gating — pass query (the current task/message) and only entities whose recall_when triggers or indexed content match it are injected. No query, no topical injection: the block is a compact retrieval pointer, byte-stable across unrelated vault writes (prefix-cache friendly).
  • Per-model recall budget — output is clamped to a character budget resolved from the host model: default/lean profile 1500 chars; large-window ("opus") profile 6000 chars; max_context_chars overrides both.
  • Capped always-onalways_on: true still works for identity-critical facts, but the recall-first set is hard-capped (top 5) and overflow emits a warning steering you to recall_when triggers.
  • Legacy opt-in — the old unconditional top-N dump is still available with mode: "always_inject" (--legacy-context for prepare), unclamped unless you pass a budget.
perseus-vault prepare --task "deploying the payments service" --model claude-sonnet-4-6
perseus-vault prepare --task "..." --max-context-chars 800     # explicit budget
perseus-vault prepare --task "..." --legacy-context            # old dump, opt-in

RAG & Embeddings

  • mimir_ask — natural language Q&A over stored memories via any LLM (Ollama, OpenAI, etc.)
  • mimir_embed — generate and store dense vectors via Ollama or OpenAI-compatible /v1/embeddings
  • Supports single-entity and batch-category embedding

Encryption

  • AES-256-GCM transparent encryption for entity body_json
  • Opt-in via --encryption-key flag
  • perseus-vault keygen subcommand for key generation
  • FTS5 index stays plaintext for search

Web Dashboard

  • Built-in Axum HTTP server (perseus-vault serve --web --port 8767)
  • Dark-themed dashboard with search, entity table, vis.js graph, timeline
  • Default bind: 127.0.0.1 (use --web-bind 0.0.0.0 to expose)
  • Separate SQLite connection in WAL mode for concurrent reads

External Connectors

  • GitHub issues connector — ingest issues/PRs by repo, rate-limit aware
  • File watcher — scan directories for .md/.txt/.json files with content-hash dedup
  • YAML-based connector config via --connectors-config

Multi-Transport

  • stdio (default) — zero-config, works with any MCP host
  • SSE — Server-Sent Events for HTTP-based MCP clients
  • HTTP — REST-style MCP endpoint
  • Bearer token auth — for SSE/HTTP transports

Perseus Integration

Perseus Vault is the default memory backend for Perseus:

mimir:
  enabled: true
  transport: "stdio"
  command: ["perseus-vault", "serve", "--db", "~/.mimir/data/perseus-vault.db"]
  timeout_s: 30.0
  merge_strategy: "local_first"
  fallback_to_local: true
  context_categories: ["decision", "architecture", "convention"]
  context_limit: 10

Government & Federal Procurement

Perseus Vault is built for government deployment from the ground up.

CapabilityStatus
LicenseMIT — no copyleft, no GPL/AGPL
SBOMPublished — NTIA minimum elements
Air-gappedFully offline — no telemetry, no API calls, no network by default
Encryption at restAES-256-GCM, transparent, opt-in
Audit trailImmutable journal with chain-of-custody
Supply chainSLSA attestation in progress

For federal buyers: See docs/federal-buyers.md for procurement information, compliance status, and deployment models (air-gapped, on-premises, classified environments).

Perseus Computing LLC is a US-owned small business. SAM.gov registration in progress. NAICS: 541715, 541511, 541512.

Privacy Policy

Perseus Vault is a local-first MCP server — it runs entirely on your machine.

Data Collection

  • No data collection. Perseus Vault does not collect, transmit, or phone home any user data, usage statistics, or telemetry.
  • All data remains in your local SQLite database file.

Data Usage & Storage

  • All memory entities, journal entries, and state are stored locally in a SQLite database at the path you specify via --db.
  • Optional AES-256-GCM encryption at rest is available — when enabled, entity bodies are encrypted before storage.
  • No data is shared with Perseus Computing LLC or any third party.

Third-Party Sharing

  • None. Perseus Vault is fully air-gapped by default. No API calls, no cloud services, no external network requests.
  • The optional dense vector embeddings feature uses a locally-compiled model — no external embedding API is called.

Data Retention

  • You control retention: entities can be soft-deleted (mimir_forget), archived (via decay/compact), or permanently purged (mimir_purge).
  • No automatic off-machine backup is performed.

Contact

Release Verification

Release binaries are built from tagged commits via GitHub Actions. Every release ships:

ArtifactDescriptionVerification
perseus-vault-<target>.tar.gzFull build (bundled embeddings, glibc)SHA-256 checksum in .sha256 sidecar
perseus-vault-lite-<target>.tar.gzLean build (--no-default-features, musl/static)SHA-256 checksum in .sha256 sidecar
SLSA provenance attestationSigstore-signed build provenancegh attestation verify <archive> --repo Perseus-Computing-LLC/perseus-vault

Verify a release binary

# 1. Verify SHA-256 checksum
sha256sum -c perseus-vault-lite-x86_64-unknown-linux-musl.tar.gz.sha256

# 2. Verify SLSA build provenance (requires gh CLI + OIDC session)
gh attestation verify perseus-vault-lite-x86_64-unknown-linux-musl.tar.gz \
  --repo Perseus-Computing-LLC/perseus-vault

# 3. Confirm the binary identity
./perseus-vault --version
# Should show both the release version AND the git commit hash, e.g.:
#   perseus-vault 2.20.2 (v2.20.2-0-gabcdef1)

# 4. Confirm the doctor reports the same identity
./perseus-vault doctor --db /tmp/test.db | head -1
#   perseus-vault doctor — v2.20.2 (v2.20.2-0-gabcdef1)

Build reproducibly from source

# The exact same binary (bit-for-bit) requires matching:
#   - Rust toolchain version (see rust-toolchain.toml)
#   - Locked dependencies: `cargo build --locked`
#   - Build flags: `--release` for release builds

cargo build --locked --release
./target/release/perseus-vault --version

License

MIT — see LICENSE.