Skip to main content

Local-first AI memory system — realms, domains, entities, hybrid search, entity graph, MCP

Project description

Alt Memory

Local-first persistent memory for AI agents. Store, search, and manage structured memory with hybrid vector/keyword search, a knowledge graph, agent diaries, personas, file mining, and an MCP server — all offline, no external services.

pip install alt-memory

Benchmarked at ~8ms/tool (FAISS backend, numpy embedder) — roughly 7x faster than the predecessor system.


Table of Contents


Installation

pip install alt-memory

This gives you FAISS + tokenizers (for numpy BERT embedder). On first use, it auto-selects the best embedder available.

Install Backend Embedder
pip install alt-memory FAISS numpy BERT (all-MiniLM-L6-v2 via pure numpy)
pip install alt-memory[chroma] + ChromaDB same
pip install alt-memory[onnx] same + ONNX MiniLM / Gemma / BERT
pip install alt-memory[all] + ChromaDB + ONNX + sentence-transformers

Extras explained

Extra Packages
[chroma] chromadb>=1.5.4
[onnx] onnxruntime, huggingface_hub, transformers
[all] chroma + onnx + sentence-transformers

Requirements: Python ≥ 3.10, Windows/Linux/macOS.


Quick Start — CLI

# Initialize a new dimension
alt-memory init

# Check status
alt-memory status

# Store a memory (realm=work, domain=bugs)
alt-memory add --realm work --domain bugs --content "Login freezes on Safari 18.2"

# Search — hybrid by default (vector + keyword)
alt-memory search "login safari" --limit 5

# Browse
alt-memory list --realm work
alt-memory realms
alt-memory rooms

# Knowledge graph
alt-memory kg-add --subject LoginBug --predicate affects --object Safari
alt-memory kg-query LoginBug
alt-memory kg-stats

# Agent diary
alt-memory record --agent claude --entry "Investigated the Safari freeze"

# Mine a file (auto-chunk, extract entities)
alt-memory mine --realm work --domain code src/auth.py

# MCP server
alt-memory mcp --transport stdio

Init with project detection

# Run init in a project directory — auto-detects corpus origin, entities, domains
alt-memory init /path/to/project --llm-provider ollama --llm-model qwen2.5

Core Concepts

Concept What it is Default MCP prefix SQL analogy
Dimension A directory on disk containing SQLite + FAISS/Chroma + config (implicit) database server
Realm Top-level bucket (e.g. work, personal, agent_claude) *_realm database
Domain Category within a realm (e.g. bugs, ideas, code) *_domain table
Entity Individual memory item with content + metadata *_entity row
KG fact Relationship triple (subject → predicate → object) with temporal validity kg_* edge
Node Cross-reference entry connecting source files to entity references *_node index
Tunnel Cross-realm link between domains (the "palace graph") *_tunnel foreign key
Record Per-agent temporal diary entry record_* / memory_* log
Persona Character definition (system prompt + name) with isolated realm *_persona schema

Hybrid search combines FAISS/Chroma vector similarity with SQLite FTS5 keyword matching, re-ranked by weighted BM25.

On-disk layout

~/.alt-memory/
├── dimension.db          # SQLite + FTS5 (all entities, metadata, KG)
├── index.faiss           # FAISS vector index (or chroma.sqlite3 for ChromaDB)
├── dimension.json        # Config (backend, embedder, model settings)
├── persona.json          # Persona registry
├── nodes/                # Packed cross-reference node storage
├── entity_registry.json  # Entity name → ID mappings
├── knowledge_graph.json  # Relationship store (backup/sync)
└── aaak_cache.json       # AAAK compression cache

All data is portable — copy ~/.alt-memory to another machine and it works.


Full CLI Reference

30+ commands. The dimension path defaults to ~/.alt-memory; override with --dimension.

Init & Status

Command Description
alt-memory init [dir] Initialize dimension; optionally scan a project directory for entities/domains
alt-memory status Show dimension status (JSON: entity count, realms, domains, embedder)
alt-memory repair-status Quick health check (entity count, SQLite integrity)

CRUD

Command Description
alt-memory add -w <realm> -r <domain> -c <content> Add an entity
alt-memory get <entity_id> Get an entity by ID
alt-memory list [-w <realm>] [-r <domain>] [-l <limit>] [-o <offset>] List entities with pagination
alt-memory delete <entity_id> Delete an entity
alt-memory realms [--verbose] List all realms
alt-memory rooms [--realm] List all domains (optionally filtered)

Search

Command Description
alt-memory search <query> [-w <realm>] [-r <domain>] [--mode <mode>] Search. Modes: hybrid (default), vector, keyword
alt-memory check-dup <content> [--threshold 0.9] Check for duplicate content

Knowledge Graph

Command Description
alt-memory kg-add -s <subject> -p <predicate> -o <object> Add a KG fact
alt-memory kg-query [entity] [--predicate] [--as-of] [--direction] Query KG facts
alt-memory kg-invalidate -s <subject> -p <predicate> -o <object> Mark a fact as ended
alt-memory kg-stats KG statistics

Records (Agent Diaries)

Command Description
alt-memory record -a <agent> -e <entry> [-t <topic>] Write a diary entry
alt-memory record-read -a <agent> [--last-n 10] Read diary entries
alt-memory record-ingest --dir <path> Ingest daily summary files into the dimension

Mining

Command Description
alt-memory mine <file> Mine a single file into the dimension
alt-memory mine <dir> [--mode projects|convos|extract] Mine a directory of files
alt-memory sweep <path> Sweep .jsonl files (message-granular mining)
alt-memory split [--source] [--output-dir] Split mega-files into per-session files

MCP Server

Command Description
alt-memory mcp --transport stdio Run MCP server over stdio (for AI coding agents)
alt-memory mcp --transport sse --port 8316 Run MCP server over HTTP SSE

Maintenance

Command Description
alt-memory sync [--apply] [--project-dir DIR] Prune stale entities (gitignored/deleted sources)
alt-memory rebuild-fts Rebuild FTS5 full-text search index
alt-memory migrate [--rebuild-faiss] [--status] Schema migration and FAISS rebuild
alt-memory repair [--integrity] [--vacuum] [--rebuild-fts] Repair utilities
alt-memory rebuild-from-sqlite Rebuild FAISS index from SQLite ground truth
alt-memory aaak <text> Compress text to AAAK format

Other

Command Description
alt-memory wake-up [--agent <name>] Show L0+L1 wake-up context
alt-memory hook run --hook <h> --harness <h> Run a hook (claude-code / codex)
alt-memory instructions <topic> Output skill instructions for AI agents

Python API

from alt_memory import Dimension

d = Dimension(path="~/.alt-memory")  # or Dimension(path="./my-dim", backend="faiss")
d.init()

Core CRUD

# Add an entity
eid = d.add_entity("work", "bugs", "Login freezes on Safari",
                   metadata={"priority": "high"}, source_file="src/auth.py")

# Get by ID
entity = d.get_entity(eid)

# List with filters
entities = d.list_entities(realm="work", domain="bugs", limit=20, offset=0)

# Update
d.update_entity(eid, content="Updated description", metadata={"status": "fixed"})

# Delete
d.delete_entity(eid)
d.delete_entities([eid1, eid2])

# Batch add
ids = d.batch_add_entities([
    ("work", "bugs", "Bug one", {}, "", None),
    ("work", "bugs", "Bug two", {}, "", None),
])

Search

# Hybrid (default) — vector + keyword, re-ranked
results = d.search("login safari", n_results=10, mode="hybrid")

# Vector-only — semantic similarity
results = d.search("authentication timeout", mode="vector")

# Keyword-only — exact match via FTS5
results = d.search("Safari 18.2", mode="keyword")

# Filter by realm/domain
results = d.search("login", realm="work", domain="bugs")

# Programmatic search (used by MCP)
results = d.search_memories("login", n_results=5, realm="work",
                            max_distance=0.5, candidate_strategy="union")

Each SearchResult has: id, text, distance, metadata, realm, domain.

Realm & Domain Management

# Realms
d.list_realms()                           # → [{"name": "work", "entity_count": 42, ...}]
d.get_or_create_realm("work", "Work stuff")
d.delete_realm("work")                    # deletes all domains and entities within

# Domains
d.list_domains(realm="work")              # → [{"name": "bugs", "entity_count": 10, ...}]
d.get_or_create_domain("work", "bugs", "Bug tracking")
d.delete_domain("work", "bugs")

Knowledge Graph

# Add facts
d.kg.add("LoginBug", "affects", "Safari", valid_from="2026-05-01")
d.kg.add("LoginBug", "priority", "high")

# Query
facts = d.kg.query("LoginBug")                           # all facts about LoginBug
facts = d.kg.query("LoginBug", as_of="2026-05-15")        # temporal query
facts = d.kg.query("LoginBug", direction="outgoing")      # outgoing edges only

# Invalidate
d.kg.invalidate("LoginBug", "affects", "Safari", ended="2026-06-01")

# Stats & timeline
d.kg.stats()
d.kg.timeline(entity="LoginBug")          # chronological story of an entity

Agent Records (Diaries)

# Write entries at different layers
d.diary_write("claude", "DEBUG: found race condition in auth retry", topic="debug")
d.diary_write("claude", "SESSION:2026-05-31|fixed.auth|★★★", topic="summary")

# Read
entries = d.diary_read("claude", last_n=5)

# List all agents with records
d.list_agents()  # Note: standalone function, see API note below

Note on standalone functions: Some operations are standalone functions in their respective modules, not Dimension methods. These include sync (sync_dimension in sync.py), traversal functions (traverse, build_graph, create_tunnel in dim_graph.py), and mining functions (mine_file_into_dimension, mine_text_into_dimension, batch_mine in miner.py). They accept a dimension path string or Dimension object. See the MCP tools table for the full list — all operations are available via the MCP server regardless.

Backend & Embedder Control

# Switch vector store backend
d.set_backend("chroma")        # FAISS → ChromaDB
d.set_backend("faiss")         # ChromaDB → FAISS

# Switch embedding model (auto-reindexes all entities)
d.set_embedder("sentence")     # sentence-transformers (best quality)
d.set_embedder("numpy")        # TF-IDF+SVD (lightest)
d.set_embedder("minilm")       # ONNX MiniLM
d.set_embedder("spacy")        # spaCy GloVe
d.set_embedder("embeddinggemma")  # Google Gemma via ONNX

# Device control for ONNX embedders
d.set_embedder("minilm", device="cpu")
d.set_embedder("minilm", device="cuda")
d.set_embedder("minilm", device="dml")    # DirectML on Windows

Status & Maintenance

# Status
status = d.status()         # → {entities, realms, domains, embedder, ...}
taxonomy = d.get_taxonomy() # → {realm: {domain: count, ...}, ...}

# FTS rebuild
d.rebuild_fts()

# Duplicate check
dup = d.check_duplicate("new content to check", threshold=0.9)

# Reconnect after external changes
d.reconnect()

# Memories filed away check
d.memories_filed_away()

Export / Import

# Export all entities as JSON-serializable list
export = d.export_collection()
export = d.export_collection(realm="work", domain="bugs")  # filtered

# Import entities from list
count = d.import_entities(export, overwrite=False)

Personas

See the full dedicated docs at docs/personas.md.

# Quick reference
d.create_persona("coder", system_prompt="You are an expert Python developer.")
d.set_persona("coder")
d.get_persona()                        # → active persona dict
d.get_persona_character()              # → "You are an expert Python developer."
d.get_persona_character("coder")       # → same, by name
d.list_personas()                      # → all registered personas
d.delete_persona("coder")              # → True/False
d.switch_persona("architect")          # alias for set_persona

MCP Server

The MCP server exposes 65 tools over stdio (for coding agents) or SSE (for remote access).

# Stdio mode — for AI coding agents (Claude Code, Codex, Cline)
alt-memory mcp --transport stdio

# SSE mode — for remote/local HTTP access
alt-memory mcp --transport sse --port 8316

AI Agent Configuration

Configure in your MCP client:

{
  "mcpServers": {
    "alt-memory": {
      "command": "alt-memory",
      "args": ["mcp", "--transport", "stdio"]
    }
  }
}

All 65 MCP Tools

Category Tool Required Params Optional Params Description
Search search query n_results, realm, domain, mode Hybrid/vector/keyword search
check_duplicate content threshold Check if content exists
CRUD add_entity realm, domain, content metadata, source_file, entity_id Store a memory
get_entity entity_id Fetch by ID
update_entity entity_id content, metadata, realm, domain Update fields
delete_entity entity_id Delete one
delete_entities entity_ids (array) Bulk delete
list_entities realm, domain, limit, offset List with pagination
batch_add_entities entities (array) Bulk add
import_entities entities (array) overwrite Import from JSON
export_collection realm, domain Export as JSON
Realms create_realm name description Create top-level bucket
delete_realm name Delete realm + contents
list_realms List all
get_taxonomy Realm → domain → count
get_status Entity count, embedder info
Domains create_domain realm, name description Create domain
delete_domain realm, name Delete domain
list_domains realm List domains
KG kg_add subject, predicate, object valid_from, valid_to, source Add fact
kg_query entity, predicate, as_of, all, direction Query facts
kg_invalidate subject, predicate, object ended End a fact
kg_stats KG statistics
kg_timeline entity Chronological story
Records record_write agent, entry topic, realm Diary entry
record_read agent last_n, realm Read diary
list_agents All agents with records
Mine mine_file filepath, realm, domain Mine a single file
mine_text text, realm, domain source, chunk Mine text content
batch_mine directory realm, pattern Mine a directory
sync project_dir, realm, apply Prune stale entities
Graph create_tunnel source_realm, source_domain, target_realm, target_domain label, source_entity_id, target_entity_id Link domains
delete_tunnel tunnel_id Remove a tunnel
list_tunnels realm List all tunnels
find_tunnels realm_a, realm_b Find bridges between realms
follow_tunnels realm, domain Follow connections
traverse start_domain max_hops Walk the graph
graph_stats Overview of connections
Backend set_backend backend (faiss|chroma) reindex Switch vector store
get_backend Current backend name
Embedder set_embedder model device, reindex Switch embedder
set_default_embedder model Set global default
get_default_embedder Get global default
Persona get_persona Active persona
set_persona name system_prompt, description, metadata Set/switch persona
switch_persona name system_prompt, description, metadata Alias for set
create_persona name system_prompt, description, metadata Create without activating
list_personas All registered
delete_persona name Remove from registry
get_persona_character name Get system prompt string
AAAK aaak_compress text max_len Compress to AAAK
aaak_decompress text Decompress AAAK
aaak_parse text Parse AAAK entry
get_aaak_spec Full AAAK specification
Other hook_settings silent_save, desktop_toast Configure hooks
memories_filed_away Checkpoint status
rebuild_fts Rebuild FTS5 index
reconnect Reconnect to database
get_people_map Name variant mappings
set_people_map map Set name variant mappings
init_dimension Initialize dimension
close_dimension Close dimension gracefully
ping Health check

All 65 tools are available as JSON-RPC calls. Example:

{"name": "add_entity", "arguments": {"realm": "work", "domain": "bugs", "content": "Login freezes on Safari 18.2"}}
{"name": "search", "arguments": {"query": "login safari", "n_results": 5}}
{"name": "set_embedder", "arguments": {"model": "minilm"}}
{"name": "set_backend", "arguments": {"backend": "chroma"}}

Search Architecture

Three Search Modes

Mode Method How it works Best for
Vector mode="vector" Embed query → FAISS/Chroma cosine distance ranking Semantic similarity ("find related concepts")
Keyword mode="keyword" FTS5 token match → BM25 ranking Exact term lookup ("find where I wrote 'login bug'")
Hybrid mode="hybrid" (default) Vector + keyword merged, re-ranked by 0.6 vector + 0.4 BM25 General-purpose

Search Pipeline

search(query, realm, domain, mode)
│
├── mode="keyword" ──▶ _build_fts_query(query)
│                      │  "login safari" → "login* AND safari*"
│                      │  "login AND safari" → passed through
│                      │  "\"login safari\"" → phrase query
│                      ▼
│                      FTS5 MATCH on entities_fts
│                      JOIN entities for realm/domain filter
│                      ORDER BY rank (BM25)
│                      Fallback to vector search if FTS5 fails
│
├── mode="vector" ────▶ embedder.embed(query) → np.ndarray
│                       FAISS IndexIDMap.search() or ChromaDB query()
│                       Cosine distance → filter by realm/domain → top-k
│
└── mode="hybrid" ────▶ Over-fetch 2× from both vector + keyword
                        Union dedup by entity ID (vector first)
                        Final score = 0.6 × vec_sim + 0.4 × BM25_norm
                        Return top-n_results

Full Pipeline (search_memories)

Used by the MCP search tool for richer results:

  1. Over-fetch 3× candidates from vector + keyword
  2. Apply max_distance threshold (filter out distant results)
  3. Merge candidates — "vector" strategy (default) or "union" (append BM25-only results)
  4. Node boost — entities from files with cross-reference nodes get priority
  5. Hydration — for boosted results, expand with ±1 neighbor chunks for context
  6. BM25 re-rank with weights 0.6 vector + 0.4 BM25
  7. Attach node_preview text to boosted results
  8. Return top-n_results dict

FTS5 Query Construction

Input Output Rule
"login safari" "login* AND safari*" Bare terms → prefix wildcard + AND
"login AND safari" passed through Operators (AND, OR, NOT, NEAR) verbatim
"\"login safari\"" passed through Phrase queries verbatim
"multi-part" "multi* AND part*" Hyphenated terms split on -

Direct Lookups (non-search)

d.get_entity("entity_id")          # SQL PK lookup
d.list_entities(realm="...")       # SQL with filters, ORDER BY created_at DESC

Embedder System

Auto-Detection

Alt Memory automatically picks the best embedder at runtime. No configuration needed.

Priority: sentence-transformers → numpy BERT → TF-IDF+SVD
Quality:  ★★★★★                 → ★★★★      → ★★
Speed:    ★★★★                  → ★★★       → ★★★★★
Deps:     PyTorch (~800MB)       → tokenizers → none

Embedder Reference

Name Quality Speed Dependencies Platform
sentence ★★★★★ ★★★★ sentence-transformers + PyTorch all
numpy_bert ★★★★ ★★★ tokenizers (included) all incl. Alpine
minilm ★★★★ ★★★★★ onnxruntime [onnx] glibc
embeddinggemma ★★★★★ ★★★★ onnxruntime [onnx] glibc
bert ★★★★ ★★★★ onnxruntime or tokenizers [onnx] all
spacy ★★★ ★★★ spacy + en_core_web_md all
numpy ★★ ★★★★★ none (always available) all

All embedders produce 384-dimensional vectors.

Switching Embedders

# CLI
export ALT_DEFAULT_EMBEDDER=minilm      # set global default
export ALT_DEFAULT_EMBEDDER=numpy       # TF-IDF+SVD (lightest)

# Python
d.set_embedder("sentence")              # auto-reindexes all entities
d.set_embedder("numpy", reindex=False)  # skip reindex (existing vectors stale)

# MCP
{"name": "set_embedder", "arguments": {"model": "minilm", "device": "cpu"}}
{"name": "set_default_embedder", "arguments": {"model": "numpy"}}

Device control for ONNX embedders:

  • "auto" — probe CUDA → CoreML → DirectML → CPU (default)
  • "cpu" — force CPU execution
  • "cuda" — NVIDIA GPU via CUDA
  • "coreml" — Apple Silicon
  • "dml" — Windows DirectML

When you change the embedder, all entities are automatically re-embedded. On large dimensions this can take time.


Backend Switching

Swap between FAISS and ChromaDB at runtime. All data persists in SQLite — only the vector index changes.

# CLI
alt-memory backend chroma   # Note: use MCP or Python API for switching

# Python
d = Dimension(path="~/.alt-memory", backend="chroma")  # initial backend
d.set_backend("faiss")        # hot-swap — moves vectors between backends
d.set_backend("chroma")

# MCP
{"name": "set_backend", "arguments": {"backend": "chroma"}}
{"name": "get_backend", "arguments": {}}

When reindex=True (default), all entities are re-embedded into the new store.


Knowledge Graph

The KG stores structured relationship triples with temporal validity.

Concepts

  • Subject — the entity doing/being something (e.g. LoginBug)
  • Predicate — the relationship type (e.g. affects, priority, found_in)
  • Object — the connected entity (e.g. Safari, high, v4.3.0)
  • Temporal validityvalid_from / valid_to dates let you answer "what was true at a given time"

MCP Usage

{"name": "kg_add", "arguments": {"subject": "LoginBug", "predicate": "affects", "object": "Safari"}}
{"name": "kg_add", "arguments": {"subject": "LoginBug", "predicate": "priority", "object": "high", "valid_from": "2026-05-01"}}
{"name": "kg_query", "arguments": {"entity": "LoginBug"}}
{"name": "kg_query", "arguments": {"entity": "LoginBug", "as_of": "2026-05-15"}}
{"name": "kg_invalidate", "arguments": {"subject": "LoginBug", "predicate": "priority", "object": "high", "ended": "2026-06-01"}}
{"name": "kg_stats", "arguments": {}}
{"name": "kg_timeline", "arguments": {"entity": "LoginBug"}}

Agent Records / Diaries

Per-agent temporal entries with three memory layers.

L0 — Immediate Records (per-exchanges)

d.diary_write("claude", "DEBUG: found race condition in auth retry", topic="debug")
d.diary_write("claude", "User prefers async Python with asyncio", topic="preference")

L1 — Daily Summaries (end of session)

d.diary_write("claude", "SESSION:2026-05-31|fixed.auth.race.cond|★★★", topic="summary")

L2 — Patterns (weekly/ongoing)

d.diary_write("claude", "PATTERN: auth.timeouts→rate.limit.insufficient|★★★★★", topic="pattern")

Reading

alt-memory wake-up --agent claude --last-n 5   # L0+L1 context
alt-memory record-read --agent claude --last-n 10
entries = d.diary_read("claude", last_n=5)

MCP

{"name": "record_write", "arguments": {"agent": "claude", "entry": "Fixed login bug", "topic": "debug"}}
{"name": "record_read", "arguments": {"agent": "claude", "last_n": 5}}
{"name": "list_agents", "arguments": {}}

File Mining

Mine source files, conversations, and text into the dimension. Auto-chunks, extracts metadata, and stores entities with source file references.

CLI

# Mine a single file
alt-memory mine src/auth.py --realm myproject --domain code

# Mine a directory (auto-globs, respects .gitignore)
alt-memory mine /path/to/project --realm myproject

# Conversation mode
alt-memory mine /path/to/convos --mode convos

# Extraction mode
alt-memory mine /path/to/formats --mode extract

# Preview without filing
alt-memory mine /path/to/project --dry-run

# Sweep .jsonl files
alt-memory sweep /path/to/file.jsonl

Python

from alt_memory.miner import mine_file_into_dimension, batch_mine, mine_text_into_dimension

# Single file
mine_file_into_dimension(dim, "src/auth.py", "myproject", "code")

# Directory (batch)
batch_mine(dim, "/path/to/project", realm="myproject",
           respect_gitignore=True, file_limit=100)

# Text content
mine_text_into_dimension(dim, text, "myproject", "notes", source="clipboard")

MCP

{"name": "mine_file", "arguments": {"filepath": "src/auth.py", "realm": "myproject", "domain": "code"}}
{"name": "batch_mine", "arguments": {"directory": "/path/to/project", "realm": "myproject"}}
{"name": "mine_text", "arguments": {"text": "raw text...", "realm": "myproject", "domain": "notes"}}

Personas

Full documentation: docs/personas.md

A persona is a character definition — a system prompt with a name, matching the Eternal AI .txt file model. Model and framework are deployment choices, not part of the character definition.

Each persona gets an isolated persona_<name> realm for memories, KG facts, and diary entries.

d.create_persona("donald_trump", system_prompt="Act as if you are Donald Trump...")
d.set_persona("donald_trump")
prompt = d.get_persona_character()
# → "Act as if you are Donald Trump..."
# Inject as {"role": "system", "content": prompt} in your LLM call

7 MCP tools: get_persona, set_persona, switch_persona, create_persona, list_personas, delete_persona, get_persona_character.


AAAK Compression

AAAK is a compressed memory dialect — readable by humans and LLMs without decoding. Uses 3-letter entity codes, emotion markers, pipe-separated fields, and importance ratings.

# CLI
alt-memory aaak "Alice loves Jordan, they have two kids: Riley (18, into sports)"
# → FAM: ALC→♡JOR | 2D(kids): RIL(18,sports) | ★★★★

# Decompress / parse
alt-memory aaak "FAM: ALC→♡JOR" --output-format json
from alt_memory import aaak_compress, aaak_decompress, aaak_parse_entry

compressed = aaak_compress("Long text here")
parsed = aaak_parse_entry(compressed)
original = aaak_decompress(compressed)
{"name": "aaak_compress", "arguments": {"text": "Your long text here"}}
{"name": "aaak_decompress", "arguments": {"text": "FAM: ALC→♡JOR..."}}
{"name": "aaak_parse", "arguments": {"text": "FAM: ALC→♡JOR..."}}
{"name": "get_aaak_spec", "arguments": {}}

Palace Graph (Tunnels)

The palace graph connects domains across realms via tunnels — explicit cross-realm relationships.

from alt_memory.dim_graph import create_tunnel, traverse, graph_stats, find_tunnels

# Link two domains
create_tunnel(
    source_realm="work", source_domain="bugs",
    target_realm="personal", target_domain="learnings",
    label="Same root cause",
)

# Walk the graph from a domain
traverse(start_domain="bugs", max_hops=2)

# Find bridges between realms
find_tunnels(realm_a="work", realm_b="personal")
{"name": "create_tunnel", "arguments": {
  "source_realm": "work", "source_domain": "bugs",
  "target_realm": "personal", "target_domain": "learnings",
  "label": "Same root cause"
}}
{"name": "traverse", "arguments": {"start_domain": "bugs", "max_hops": 2}}
{"name": "graph_stats", "arguments": {}}
{"name": "follow_tunnels", "arguments": {"realm": "work", "domain": "bugs"}}

Sync & Maintenance

Sync (prune stale entities)

Removes entities whose source files were deleted or moved:

# Dry-run preview
alt-memory sync --project-dir /path/to/repo

# Actually delete
alt-memory sync --project-dir /path/to/repo --apply

# Limited to one realm
alt-memory sync --project-dir /path/to/repo --realm myproject --apply

Repair

# Quick health check
alt-memory repair-status

# Check SQLite integrity
alt-memory repair --integrity

# Run VACUUM
alt-memory repair --vacuum

# Rebuild FTS5 index
alt-memory repair --rebuild-fts

# Interactive repair mode
alt-memory repair --mode status
alt-memory repair --mode scan
alt-memory repair --mode prune
alt-memory repair --mode rebuild

# Full rebuild from SQLite (covers FAISS corruption)
alt-memory rebuild-from-sqlite

Migration

# Check schema status
alt-memory migrate --status

# Apply pending migrations
alt-memory migrate

# Rebuild FAISS from SQLite
alt-memory migrate --rebuild-faiss

# Dry run
alt-memory migrate --dry-run

Maintenance

# Rebuild just the FTS5 index
alt-memory rebuild-fts

# Check for duplicate content
alt-memory check-dup "content to check"

Configuration

Global configuration is stored in ~/.alt-memory/config.json.

Environment Variables

Variable Default Description
ALT_DIM_PATH ~/.alt-memory Default dimension path
ALT_DEFAULT_EMBEDDER auto Force a specific embedder (numpy, numpy_bert, sentence, minilm, spacy)
ALT_EMBEDDING_DEVICE auto ONNX device (cpu, cuda, coreml, dml)

Config File (~/.alt-memory/config.json)

{
  "dim_path": "~/.alt-memory",
  "default_embedder": "numpy_bert",
  "embedding_device": "auto",
  "people_map": {"Alex": "Alexander", "Beth": "Elizabeth"},
  "hooks_auto_save": true,
  "hook_silent_save": true,
  "hook_desktop_toast": false
}

Hook Settings (via MCP)

{"name": "hook_settings", "arguments": {"silent_save": true, "desktop_toast": false}}

Docker

# FAISS + numpy BERT (Alpine, ~117MB content)
docker run -v ~/.alt-memory:/root/.alt-memory kilv/alt-memory:alpine mcp

# Full install (Debian, includes chroma + onnx)
docker run -v ~/.alt-memory:/root/.alt-memory kilv/alt-memory:latest mcp

Tags:

  • kilv/alt-memory:latest — Debian-based, full install

  • kilv/alt-memory:4.5.4 — versioned Debian

    • kilv/alt-memory:4.5.4-alpine — versioned Alpine

Architecture

┌──────────────────────────────────────────────────────┐
│              MCP Server (stdio / SSE)                 │
│           65 JSON-RPC tools for AI agents             │
├──────────────────────────────────────────────────────┤
│                     Dimension                         │
│         orchestrates realms, domains, entities        │
├──────────────────────┬───────────────────────────────┤
│    Vector Store       │    SQLite + FTS5              │
│  (FAISS / ChromaDB)   │  (entities, KG, metadata)    │
├──────────────────────┴───────────────────────────────┤
│              Embedder Layer (pluggable)                │
│  numpy (TF-IDF+SVD) ── numpy_bert ── minilm (ONNX)    │
│  sentence-transformers ── spaCy ── embeddinggemma      │
└──────────────────────────────────────────────────────┘

Key files

File Purpose
alt_memory/dimension.py Main Dimension class — all CRUD, search, status, personas
alt_memory/mcp_server.py MCP server — 65 JSON-RPC tools over stdio/SSE
alt_memory/cli.py CLI — 30+ commands
alt_memory/backends/embedder.py Embedder factory — numpy, ONNX, sentence, spaCy
alt_memory/backends/faiss_store.py FAISS vector store
alt_memory/backends/chroma_store.py ChromaDB vector store
alt_memory/backends/knowledge_graph.py Knowledge Graph (temporal triples)
alt_memory/searcher.py BM25 ranking, hybrid re-rank, neighbor expansion
alt_memory/dim_graph.py Palace graph — tunnels, traversal
alt_memory/miner.py File mining — auto-chunk, entity extraction
alt_memory/sync.py Sync — prune stale entities
alt_memory/dialect.py AAAK compression dialect
alt_memory/layers.py L0/L1/L2 memory stack
alt_memory/config.py Configuration manager

License

MIT

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

alt_memory-4.5.4.tar.gz (287.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

alt_memory-4.5.4-py3-none-any.whl (288.6 kB view details)

Uploaded Python 3

File details

Details for the file alt_memory-4.5.4.tar.gz.

File metadata

  • Download URL: alt_memory-4.5.4.tar.gz
  • Upload date:
  • Size: 287.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.3

File hashes

Hashes for alt_memory-4.5.4.tar.gz
Algorithm Hash digest
SHA256 213e39485cb450565b8985dafe1cc7928bc6486774cd54c5d4cb2870c6b91531
MD5 044d205bac8708d440d5c62c0cebad23
BLAKE2b-256 8663e4ec0caa82109077d47822032304f1b361de4e2769c931ebc6061ff6cd88

See more details on using hashes here.

File details

Details for the file alt_memory-4.5.4-py3-none-any.whl.

File metadata

  • Download URL: alt_memory-4.5.4-py3-none-any.whl
  • Upload date:
  • Size: 288.6 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.3

File hashes

Hashes for alt_memory-4.5.4-py3-none-any.whl
Algorithm Hash digest
SHA256 173b02bc5b4a8b5454ceeddd7286a201a39bfac1f9794e95583f2ab67417d71f
MD5 724caf7d246aa02c30e033c85aea07a4
BLAKE2b-256 bed8d3e5f803eedc18652f3d3070ac8e270029d7cc103a1b3db4b769aa4cc4ec

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page