Skip to content

Memory Vault

The memory vault — where knowledge goes to be preserved, indexed, and occasionally forgotten on purpose

We built something that dreams.

Every morning at 4:17, while the haus sleeps, the vault does what a brain does overnight: it sorts the day’s raw observations, keeps what matters, and forgets the rest on purpose. Forgetting, here, is not a bug we tolerate — it is the feature we designed for. Somewhere during development we realized we’d shipped a system that remembers where you left your SSH keys, forgets trivial session data, and dreams at 4 AM. The horror movie writes itself.

The Memory Vault is Sanctum’s shared knowledge base, modeled on how human memory actually works. Three tiers of temporal memory — working, short-term, long-term — sit on top of a four-system backend stack, and a daily consolidation pass acts like sleep, distilling raw observations into lasting knowledge.

Today’s stack is the local git vault, fronted by two access surfaces (a Rust REST service and a Python MCP server), plus the entity graph running on the VM. The doc once described a four-layer design that included a mem0.ai cloud tier; that integration was never wired up, and the privacy posture decided on 2026-05-16 (vault GitHub mirror archived, “the haus does not sync its thoughts to the cloud”) makes wiring it now an explicit policy violation. Honesty over aspiration.

Layer Role Backend Cost
Memory Vault Git-native versioned source of truth, primary cross-agent semantic memory Local-only git repo at ~/.sanctum/memory/ (GitHub mirror archived 2026-05-16 as part of the privacy scrub; the haus does not sync its thoughts to the cloud) Free
sanctum-memory REST The read/write data plane over the vault git repo Rust service on 127.0.0.1:42069, serving /health and /v1/* HTTP routes (search, read, write, recall, ingest, consolidate) Free
memory_vault MCP Tool surface & Karpathy-style Second-Brain Wiki Compiler Native Rust binary (sanctum-memory-vault) over stdio + CLI flags (--consolidate, --wiki-lint, --hub-caps), exposing 9 memory_* tools Free
Neo4j / Graphiti Entity relationships & graph queries Reached via SSH tunnel on local port 31416 (graph runs on the VM, not the host) Free (self-hosted)
┌─────────────────────────────────────────────────────┐
│ LAYER 1: WORKING MEMORY (per-session, ephemeral) │
│ Agent's context window. Dies when session ends. │
├─────────────────────────────────────────────────────┤
│ LAYER 2: SHORT-TERM MEMORY (inbox/, days-weeks) │
│ inbox/{agent}/ — raw observations, session notes │
│ TTL: 7-30 days. Consolidated or discarded daily. │
├─────────────────────────────────────────────────────┤
│ LAYER 3: LONG-TERM MEMORY (consolidated, permanent)│
│ knowledge/{topic}/ — semantic facts (timeless) │
│ events/YYYY/MM/ — significant episodes │
│ procedures/ — how-to, runbooks │
│ Neo4j/Graphiti — entity relationship graph │
└─────────────────────────────────────────────────────┘
~/.sanctum/memory/
├── inbox/ # Short-term, per-agent
│ ├── claude-code/
│ ├── gemini-cli/
│ ├── openclaw/
│ └── home-assistant/
├── knowledge/ # Long-term semantic
│ ├── devices/
│ ├── network/
│ ├── systems/
│ ├── people/
│ └── preferences/
├── events/ # Long-term episodic
│ └── 2026/03/
├── procedures/ # Long-term procedural
│ ├── troubleshooting/
│ ├── maintenance/
│ └── automation/
├── archive/ # Expired, retained 90 days
└── meta/ # Schema, consolidation logs

Every note has standardized YAML frontmatter. Opinions may vary on whether your haus needs a metadata schema for its thoughts. Opinions are wrong.

---
type: semantic | episodic | procedural | observation | session_summary
source_agent: claude-code | gemini-cli | openclaw | user | system
created: 2026-03-20T17:00:00Z
updated: 2026-03-20T17:00:00Z
last_accessed: 2026-03-20T17:00:00Z
access_count: 3
importance: 0.85
consolidation_status: raw | reviewed | consolidated | archived
ttl_days: null # null = permanent, or integer days
superseded_by: null # path to newer version
tags: [network, infrastructure]
related_entities: [mac-mini, ubuntu-vm]
---
# Note Title
Content with [[wikilinks]] to related notes...

Every note has a computed importance score (0.0 to 1.0) that determines its TTL. The vault is, in essence, deciding what’s worth remembering. A power you’d think we’d reserve for sentient beings, but here we are.

Importance TTL Notes
> 0.8 Permanent Core knowledge, user-stated facts
0.5 - 0.8 90 days Agent-observed patterns
0.3 - 0.5 30 days Single observations
< 0.3 7 days Ephemeral session data

Score formula: source_weight x recency x access_frequency x link_density

Notes accessed 5+ times are protected from expiry regardless of score. If the system keeps coming back to a memory, there’s probably a reason. Even if that reason is paranoia.

Consolidation & Karpathy Second-Brain Wiki Compiler

Section titled “Consolidation & Karpathy Second-Brain Wiki Compiler”

The consolidation engine runs daily at 4:17 AM (LaunchAgent: com.sanctum.memory-consolidate) directly inside the Rust sanctum-memory-vault --consolidate binary (services/memory-vault-mcp/src/consolidate.rs). Inspired by Andrej Karpathy’s LLM Wiki second-brain architecture, it treats inbox/ and episodic streams as raw sources that are compiled into living, cross-linked canonical entity pages rather than merely shoveled into a growing folder of timestamped fragments.

  1. Scan inbox (both inbox/<agent>/*.md and top-level inbox/*.md drops) for notes older than 24 hours
  2. Compile into canonical Wiki pages — match fragments against 13 canonical entity pages (knowledge/{systems,network,devices,finance,people}/wiki-*.md), append structured dated synthesis entries with backlinks, and archive the raw fragment with superseded_by pointing to the canonical wiki page
  3. Update Agent Knowledge Frontiers — maintain agents/<agent>/knowledge-frontier.md with each agent’s latest domain contributions
  4. Refresh Maps of Content — regenerate the canonical index tables in MOC.md and MOC-systems.md
  5. Recompute importance scores and expire TTL-exceeded notes
  6. Enforce dynamic hub caps via sanctum-memory-vault --hub-caps and bounded archive-eviction
  7. Run Wiki Lint (sanctum-memory-vault --wiki-lint) — verify zero broken [[wikilinks]], zero orphan knowledge pages, and zero uncompiled fragment clusters
  8. Clean archive & SQLite artifacts — prune archived notes older than 90 days and stale .vault.db.stale-* files, then write meta/consolidation-log.md

Any agent can trigger consolidation or wiki linting manually via the memory_consolidate and memory_wiki_lint MCP tools.

To prevent bloat, each layer has a dynamic maximum note count computed by sanctum-memory-vault --hub-caps (base + per_hub * active_hubs). Without limits, a system that remembers everything eventually remembers nothing useful — a problem familiar to anyone who’s ever hoarded browser tabs.

Layer Base Cap Dynamic Hub Scaling (meta/caps.json) Action at Cap
Inbox 300 +7 per active hub (307 with 1 hub) Wiki compilation + bounded archive-eviction
Knowledge 1000 +197 per active hub (1197 with 1 hub) Wiki compilation + bounded archive-eviction
Events 500 Dynamic active window Bounded archive-eviction
Procedures 200 Static runbook cap Bounded archive-eviction

Eviction sorts candidates by (importance ascending, created ascending) and skips anything with importance > 0.8 — permanent knowledge and canonical wiki-*.md pages (importance: 0.95) survive cap pressure. Archived notes are retained for 90 days via ARCHIVE_RETAIN_DAYS before deletion — eviction is reversible during that window.

Tool Description
memory_search Full-text search (SQLite FTS5) with tag and folder filters
memory_read Read a note (auto-tracks access count and timestamp)
memory_write Create/update with schema enforcement
memory_delete Remove a note
memory_list List notes by folder, tag, or type
memory_links Traverse the wikilink graph
memory_consolidate Run the native Rust consolidator + Second-Brain Wiki compiler (dry-run by default)
memory_wiki_lint Audit the vault for broken [[wikilinks]], orphan knowledge pages, and uncompiled fragments
memory_health Vault health metrics dashboard

Earlier versions of this doc described a mem0.ai cloud tier as the primary cross-agent memory layer, with a planned set of MEM0_* cloud tools and a “push to Mem0” step in nightly consolidation. None of that integration was ever wired up — there’s no mem0 client in the repo, no API key, and no mem0.ai traffic from the host.

When the privacy posture was decided on 2026-05-16 (vault GitHub mirror archived, “the haus does not sync its thoughts to the cloud”), Mem0-as-cloud-tier became incompatible with explicit policy. The architecture quietly converged on the local-only model documented above; the doc just hadn’t caught up. This section exists so anyone reading old commit messages or older drafts knows what happened: the cloud tier is not coming back absent a deliberate privacy-posture reversal.

Tool Vault Access
Gemini CLI memory_vault MCP over stdio (~/.gemini/settings.json)
Claude Code Not currently wired — mcpServers is empty; reach the vault via the :42069 REST API or vault.sh until the MCP is added
OpenClaw agents SSH skill (vault.sh)
Sanctum automations :42069 REST API (/v1/write, /v1/search) — the old GitHub path died with the 2026-05-16 archive
Obsidian File system (~/.sanctum/memory/)
Holocron HausBrainPanel polls /vault/brain from Force Flow (:4077) every 5s; new-note particles fire in real time off an Electron IPC vault-event bridge, not a separate socket

After tonight’s reconciliation pass (2026-05-29), there are no open implementation gaps — the machinery does what this page says it does: short-term inbox + long-term knowledge/events/procedures, nightly consolidation with bounded archive-eviction, 90-day reversibility, the memory_* tool surface, the :42069 data plane.

One thing the caps table doesn’t show: the vault is currently over cap and grinding down. Events sits at roughly 8× its 500-note cap, and the nightly run evicts 100 events per cycle by design (MAX_EVICT_PER_RUN) rather than archiving thousands in one massacre. That’s the bounded-eviction design working, not a steady state — a system converging, not a system at rest.

The procedures layer was empty for months and is now seeded — 5 high-signal runbooks grounded in recent incidents live under procedures/{troubleshooting,maintenance,automation}/. The layer grows organically from there as incidents teach the haus new procedures worth remembering.

The only architectural decision left open is whether to ever re-introduce a cloud-sync tier (see On Mem0 above). That is a privacy-posture decision, not an engineering gap.

  • If derivable from code, logs, or sensors — don’t store it
  • If the same fact is stated multiple ways — dedup into one
  • If never accessed in 30 days and importance < 0.5 — archive
  • Raw data goes to time-series DBs, not memory
  • Every episodic memory needs context (who, what, when, why)
  • Every semantic memory should be self-contained

A haus that remembered everything would remember nothing worth keeping. So the vault forgets, on schedule, the way you do — and every morning at 4:17 it still wakes up knowing where the SSH keys are. That is the whole trick. Your own brain has been running it, unpatched, your entire life.