Ogham MCP

Ogham (pronounced "OH-um") -- persistent, searchable shared memory for AI coding agents. Works across clients.

License: MIT Docker Python 3.13+ PyPI

What it is

AI coding agents forget everything between sessions. Switch from Claude Code to Cursor to Kiro to OpenCode and the context is gone -- decisions, gotchas, the shape of your codebase -- so you repeat yourself, re-explain, and re-debug the same issues.

Ogham gives your agents one shared memory that persists across sessions and clients. It is a retrieval engine: it stores what matters and finds it again, and your LLM reads the results.

The retrieval is structured -- hybrid search plus a typed-edge graph, not just vector similarity. That is what lets it answer questions whose answer is a path between two facts, the case where plain vector RAG falls down.

Quick start

uvx --from ogham-mcp ogham init

ogham init runs a setup wizard: it connects your database, picks an embedding provider, migrates the schema, and writes the MCP client config (Claude Code, Cursor, VS Code, and others). For Claude Code it runs claude mcp add for you; for other clients it prints the snippet to copy.

You need a database first -- a free Supabase project or a Neon database. On Neon or self-hosted Postgres, install the postgres extra so the driver is available:

uvx --from 'ogham-mcp[postgres]' ogham init

Then tell your agent to remember something and ask about it later -- from the same client or a different one. They share the database, so the memory follows you.

Manual setup

If you'd rather configure things yourself instead of using the wizard:

# Supabase
export SUPABASE_URL=https://your-project.supabase.co
export SUPABASE_KEY=your-service-role-key
export EMBEDDING_PROVIDER=openai  # or ollama, mistral, voyage
export OPENAI_API_KEY=sk-...      # for your chosen provider

# Or Postgres (Neon, self-hosted)
export DATABASE_BACKEND=postgres
export DATABASE_URL=postgresql://user:pass@host/db
export EMBEDDING_PROVIDER=openai
export OPENAI_API_KEY=sk-...

Run the schema migration (sql/schema.sql for Supabase, sql/schema_postgres.sql for Neon/self-hosted), then add the MCP server to your client.

Installation methods

Method Command When to use
uvx (recommended) uvx ogham-mcp Quick setup, auto-updates
Docker docker pull ghcr.io/ogham-mcp/ogham-mcp Isolation, self-hosted
Git clone git clone + uv sync Development, contributions

Claude Code

claude mcp add ogham -- uvx ogham-mcp

OpenCode -- add to ~/.config/opencode/opencode.json:

{
  "mcp": {
    "ogham": {
      "type": "local",
      "command": ["uvx", "ogham-mcp"],
      "environment": {
        "SUPABASE_URL": "https://your-project.supabase.co",
        "SUPABASE_KEY": "{env:SUPABASE_KEY}",
        "EMBEDDING_PROVIDER": "openai",
        "OPENAI_API_KEY": "{env:OPENAI_API_KEY}"
      }
    }
  }
}

Docker

docker run --rm \
  -e SUPABASE_URL=https://your-project.supabase.co \
  -e SUPABASE_KEY=your-key \
  -e EMBEDDING_PROVIDER=openai \
  -e OPENAI_API_KEY=sk-... \
  ghcr.io/ogham-mcp/ogham-mcp

From source

git clone https://github.com/ogham-mcp/ogham-mcp.git
cd ogham-mcp
uv sync
uv run ogham --help

SSE transport (multi-agent)

By default, Ogham runs in stdio mode -- each MCP client spawns its own server process. For multiple agents sharing one server, use SSE mode:

ogham serve --transport sse --port 8742

The server runs as a persistent background process. All clients connect to the same instance -- one database pool, one embedding cache, shared memory.

Client config for SSE (any MCP client):

{
  "mcpServers": {
    "ogham": {
      "url": "http://127.0.0.1:8742/sse"
    }
  }
}

Health check at http://127.0.0.1:8742/health (cached, sub-10ms). Configure via env vars (OGHAM_TRANSPORT=sse, OGHAM_HOST, OGHAM_PORT) or CLI flags. The init wizard (ogham init) walks through SSE setup if you choose it.

Entry points

  • ogham -- the CLI. Use this for ogham init, ogham health, ogham search, and other commands you run yourself. Running ogham with no arguments starts the MCP server.
  • ogham-serve -- starts the MCP server directly. This is what MCP clients should call. When you run uvx ogham-mcp, it invokes ogham-serve.

Retrieval quality

Ogham is a retrieval engine -- it finds the memories, your LLM reads them. The headline numbers, and they measure different things:

  • Retrieval: 97.2% R@10 on LongMemEval with one Postgres query (pgvector + tsvector CCF hybrid search). The paper baseline is 78.4%. Other systems that report similar R@10 typically stack cross-encoder reranking, NLI verification, and knowledge-graph enrichment.
  • End-to-end QA: 85.8% on the AMB harness (500 questions, April 2026, strict substring judge, GPT-5-mini reader; R@10 99.5%), and 0.554 nugget on BEAM 100K (paper baseline 0.358; seven of nine categories beat the paper).

QA accuracy tests whether the full system (retrieval + LLM) produces the correct answer. R@10 tests whether retrieval alone found the right memories. Full tables, methodology, and the competitor comparison live at ogham-mcp.dev/features; the write-ups explain why the AMB and internal numbers differ (LongMemEval, BEAM).

85.8% QA accuracy on the AMB benchmark harness (500 questions, April 2026) -- 429/500 questions answered correctly using GPT-5-mini with reasoning, evaluated by Gemini 2.5 Flash Lite as a strict judge. Retrieval R@10: 99.5%. AMB is the standardised evaluation harness built by the Vectorize team (creators of Hindsight). Thanks to Nicolo and the Vectorize team for making the harness open.

Previously: 91.8% on our internal LongMemEval benchmark pipeline (gpt-5.4-mini reader, rubric judge). The AMB number is lower because AMB uses a stricter substring-matching judge -- see the full write-up for methodology differences.

0.554 nugget score on BEAM 100K (400 questions across 10 memory abilities, ICLR 2026), using the paper's exact judge prompt from Appendix G. The published baseline is 0.358 (Llama-4-Maverick + LIGHT). Retrieval R@10: 0.737. Seven of nine categories beat the paper. Full write-up.

End-to-end QA accuracy on LongMemEval (retrieval + LLM reads and answers):

System Accuracy Architecture
OMEGA 95.4% Classification + extraction pipeline
Observational Memory (Mastra) 94.9% Observation extraction + GPT-5-mini
Ogham v0.9.2 85.8% Verbatim + read-time extraction + gpt-5-mini (AMB harness, strict judge)
Ogham v0.9.1 91.8% Hybrid search + context engineering + gpt-5.4-mini (internal benchmark)
Hindsight (Vectorize) 91.4% 4 memory types + Gemini-3
Zep (Graphiti) 71.2% Temporal knowledge graph + GPT-4o
Mem0 49.0% RAG-based

Retrieval only (R@10 -- no LLM in the search loop):

System R@10 Architecture
Ogham 97.2% 1 SQL query (pgvector + tsvector CCF hybrid search)
LongMemEval paper baseline 78.4% Session decomposition + fact-augmented keys

Other retrieval systems that report similar R@10 numbers typically use cross-encoder reranking, NLI verification, knowledge graph enrichment, and LLM-as-a-judge pipelines. Ogham reaches 97.2% with one Postgres query. Optional FlashRank reranking is available for self-hosters who want extra ranking precision.

These tables measure different things. QA accuracy tests whether the full system (retrieval + LLM) produces the correct answer. R@10 tests whether retrieval alone finds the right memories. Ogham is a retrieval engine -- it finds the memories, your LLM reads them.

Category R@10 Questions
single-session-assistant 100% 56
knowledge-update 100% 78
single-session-user 98.6% 70
multi-session 97.3% 133
single-session-preference 96.7% 30
temporal-reasoning 93.5% 133

Full breakdown: ogham-mcp.dev/features

How it works

AI Client (Claude Code, Cursor, Kiro, OpenCode, ...)
    |
    | stdio or SSE (MCP protocol)
    |
Ogham MCP Server
    |
    | HTTPS (Supabase REST API) or direct connection (Postgres)
    |
PostgreSQL + pgvector

Memories are stored as rows with vector embeddings. Search combines pgvector cosine similarity with PostgreSQL full-text search using Reciprocal Rank Fusion (RRF) -- position-based, score-agnostic fusion that handles different score scales correctly. The knowledge graph lives in a memory_relationships table walked with recursive CTEs; the typed-edge graph (v0.16) adds structural, predicate-typed relationships for two-fact join queries. No separate graph database. Optional FlashRank cross-encoder reranking adds a second pass for self-hosters.

What's in it

  • Memory operations -- store memories, decisions, preferences, facts, and events; update, reinforce, and contradict.
  • Hybrid search -- semantic + full-text (RRF), tag filters, multi-profile search, read-time fact extraction.
  • Typed-edge graph (v0.16) -- store_triple / query_join for two-fact join queries against a controlled predicate vocabulary. docs
  • Knowledge graph -- auto-linking, spreading-activation retrieval, and connection suggestions via shared entities.
  • Wiki layer -- synthesize a tag's memories into a cached markdown page; walk the graph; lint health.
  • Open Knowledge Format -- portable round-trip bundles (markdown + a self-contained graph viewer), OKF v0.1.
  • Entity enrichment -- regex entity tags across 18 languages with no LLM in the write path; a timeline table; Lost-in-the-Middle reordering.
  • Memory lifecycle -- FRESH / STABLE / EDITING stages, ACT-R importance, Hebbian decay, and automatic condensing.
  • Importers -- Claude Code auto-memory, Claude.ai export, Linear issues, and JSON.
  • Ingestion adapters (v0.17) -- capture into memory from an Obsidian/markdown vault (ingest-obsidian), Telegram (ingest-telegram), and Slack (ingest-slack). Outbound-only, idempotent, and timer-friendly; all three share one server-side enrichment and dedup path.
  • Lifecycle hooks -- recall context at session start, inscribe signal (not noise) after tool use; secrets masked before storage.
  • Skills -- ogham-research, ogham-recall, ogham-maintain.
  • Self-hoster options -- ONNX local embeddings (BGE-M3), optional FlashRank reranking, five embedding providers.

Full reference for every tool, env var, and setup path is in Reference below.

The deeper story

The retrieval pipeline is built on established information-retrieval and cognitive-science work, not ad-hoc heuristics:

  • Hybrid search -- Reciprocal Rank Fusion (Cormack, Clarke & Butt, SIGIR 2009): dense vector similarity rank-fused with BM25-style keyword matching, no score normalisation.
  • ACT-R importance + Hebbian decay -- recency, frequency, and surprise weighting (Anderson & Lebiere, 1998; Hebb, 1949). Unaccessed memories fade; frequently accessed ones potentiate and persist.
  • Read-time fact extraction -- verbatim storage with query-aware extraction at retrieval, so the ground truth stays re-extractable with different questions later (Anthropic, arXiv:2510.05179). Supports local models via Ollama for full data sovereignty.
  • Contradiction detection + supersession -- opposite-polarity memories are linked, not deleted; the edge records that the newer memory superseded the older one.
  • Append-only audit trail -- every store, search, delete, and update logged to an audit_log table in the same Postgres instance, aligned with GDPR Article 15 and OTEL GenAI conventions.

Ogham's retrieval pipeline combines established information retrieval and cognitive science techniques:

  • Hybrid search -- Reciprocal Rank Fusion (Cormack, Clarke & Butt, SIGIR 2009) combining dense vector similarity (pgvector) with BM25-style keyword matching (PostgreSQL tsvector). Two independent retrieval systems, rank-fused without score normalisation.

  • Entity overlap boost -- memories sharing named entities with the query receive a bounded relevance boost (up to 1.4x), inspired by entity-linking literature (Kolitsas et al., CoNLL 2018). Entity extraction covers 18 languages via YAML-based word lists with no LLM in the write path.

  • Matryoshka embeddings -- flexible dimensionality via Matryoshka Representation Learning (Kusupati et al., NeurIPS 2022). Embedding providers (OpenAI, Voyage, Gemini, Ollama) produce native-dimension vectors truncated to 512d, enabling provider-portable storage without re-embedding.

  • Temporal diversity re-ranking -- density-gated soft penalty preventing semantic clustering on a single time period, extending Maximal Marginal Relevance principles (Carbonell & Goldstein, SIGIR 1998). Only activates when the top-k results are temporally concentrated, leaving well-distributed results untouched.

  • ACT-R importance scoring -- cognitive-architecture-inspired memory weighting based on recency, access frequency, and surprise (Anderson & Lebiere, 1998). Frequently accessed memories stay sharp, rarely accessed ones fade, disputed ones drop in ranking without deletion.

  • Hebbian decay and potentiation -- memories that are not accessed lose importance over time (5% per 30-day idle period). Memories accessed 10+ times become "potentiated" with a slower decay rate (1% per 30 days), simulating long-term potentiation. Based on Hebb's learning rule (Hebb, 1949) and computational models of synaptic plasticity (Bi & Poo, 2001). Importance serves as a multiplier in the relevance formula -- decayed memories sink in rankings but remain retrievable (floor at 0.05). Original importance is preserved in metadata for recovery. Run as a batch job via ogham decay or pg_cron.

  • Memory lifecycle (v0.11.0): FRESH / STABLE / EDITING. Every memory now has an explicit stage tracked in a dedicated memory_lifecycle table. New memories land at fresh. The session-start hook sweeps aged fresh memories to stable when they clear an importance-or-surprise gate and have dwelled long enough. Retrieval opens a 30-minute editing window on the returned memories so follow-up update_memory calls refine recent thoughts in place; windows auto-close on the next sweep. Memories retrieved together also strengthen their pairwise graph edges (eta=0.01 per co-retrieval, capped at 1.0). The design draws on three lines of prior art: Hebbian co-activation (Hebb, 1949), the hybrid exponential-then-power-law forgetting curve characterised by Wixted (2004) building on Ebbinghaus (1885), and the memory reconsolidation window from neuroscience (Nader, Schafe & LeDoux, 2000) for the editing-on-retrieval mechanic. Stage state lives in its own table so transitions do not touch the HNSW vector index.

  • Spreading activation -- when a search hits one memory, activation spreads along relationship edges to pull in connected memories that wouldn't have matched on their own. Integrated into cross-reference, ordering, and summary queries. Density-adaptive weighting means sparse graphs lean harder on graph signal, dense graphs rely more on retrieval score. Inspired by Collins & Loftus (1975) semantic network theory.

  • Contradiction detection -- when a new memory has opposite polarity to a high-similarity existing memory, Ogham automatically creates a contradicts relationship edge. Polarity detection uses negation markers across 18 languages loaded from YAML word lists. Contradicted memories are not deleted -- the edge records that the newer memory superseded the older one.

  • Read-time fact extraction -- query-aware extraction at retrieval time preserves verbatim storage for auditability, contrasting with write-time compression approaches. Verbatim storage ensures the ground truth is always available for re-extraction with different questions later -- a design choice informed by alignment considerations in persistent agent memory (Anthropic, arXiv:2510.05179). Supports local models via Ollama for full data sovereignty.

  • Append-only audit trails -- every store, search, delete, and update operation is logged to an audit_log table in the same Postgres instance. Designed for GDPR Article 15 subject access requests and cost governance. Fields align with OTEL GenAI Semantic Conventions. Query via ogham audit CLI. No extra infrastructure -- runs in the same database as memories.


Reference

ogham init                      # Interactive setup wizard
ogham health                    # Check database + embedding provider
ogham config                    # Show runtime configuration (secrets masked)
ogham store "some fact"         # Store a memory
ogham search "query"            # Search memories (hybrid: semantic + keyword)
ogham search "q" --json         # JSON output for scripting
ogham search "q" --tags "a,b"   # Filter by comma-separated tags
ogham list                      # List recent memories
ogham list --json               # JSON output
ogham delete <id>               # Delete a memory by ID
ogham use <profile>             # Switch default profile
ogham profiles                  # List profiles and counts
ogham stats                     # Profile statistics
ogham export -o backup.json     # Export memories (JSON)
ogham export --format markdown  # Export as Obsidian-compatible markdown
ogham export --format okf       # Export as Open Knowledge Format v0.1 bundle
ogham import backup.json        # Import a JSON export
ogham import <okf-bundle-dir>   # Import an OKF bundle directory (auto-detected)
ogham cleanup                   # Remove expired memories
ogham hooks install             # Auto-detect client + configure hooks
ogham hooks recall              # Read from the stone (load project context)
ogham hooks inscribe            # Carve into the stone (capture activity)
ogham hooks inscribe --dry-run  # Preview hook memory without storing
ogham serve                     # Start MCP server (stdio, default)
ogham serve --transport sse     # Start SSE server on port 8742
ogham openapi                   # Generate OpenAPI spec

Multi-profile search -- search across multiple profiles in a single query (v0.8.5+):

# MCP tool
hybrid_search(query="architecture decisions", profiles=["work", "shared"])

# Python library
from ogham.service import search_memories_enriched
results = search_memories_enriched(
    query="architecture decisions",
    profile="work",
    profiles=["work", "shared", "project-alpha"],
)

When profiles is set, results include memories from all listed profiles with a profile field showing which profile each result came from.

Variable Required Default Description
DATABASE_BACKEND No supabase supabase or postgres
SUPABASE_URL If supabase -- Your Supabase project URL
SUPABASE_KEY If supabase -- Supabase secret key (service_role)
DATABASE_URL If postgres -- PostgreSQL connection string
EMBEDDING_PROVIDER No ollama ollama, openai, mistral, voyage, gemini, or onnx
EMBEDDING_DIM No 512 Vector dimensions -- must match your schema (see below)
OPENAI_API_KEY If openai -- OpenAI API key
MISTRAL_API_KEY If mistral -- Mistral API key
VOYAGE_API_KEY If voyage -- Voyage AI API key
GEMINI_API_KEY If gemini -- Google Gemini API key
OLLAMA_URL No http://localhost:11434 Ollama server URL
OLLAMA_EMBED_MODEL No embeddinggemma Ollama embedding model
MISTRAL_EMBED_MODEL No mistral-embed Mistral embedding model
VOYAGE_EMBED_MODEL No voyage-4-lite Voyage embedding model
GEMINI_EMBED_MODEL No gemini-embedding-2-preview Gemini embedding model
RERANK_ENABLED No false Enable FlashRank cross-encoder reranking
RERANK_ALPHA No 0.55 Cross-encoder score weight (0-1)
DEFAULT_MATCH_THRESHOLD No 0.7 Similarity threshold (see below)
DEFAULT_MATCH_COUNT No 10 Max results per search
DEFAULT_PROFILE No default Memory profile name
OGHAM_RECALL_ENABLED No true Enable memory recall/context retrieval
OGHAM_INSCRIBE_ENABLED No true Enable memory capture/content writes

Embedding providers

Provider Default dimensions Recommended threshold Notes
OpenAI 512 (schema default) 0.35 Set EMBEDDING_DIM=512 explicitly -- OpenAI defaults to 1024
Ollama 512 0.70 Tight clustering, scores run 0.8-0.9
Mistral 1024 0.60 Fixed 1024 dims, can't truncate. Schema must be vector(1024)
Voyage 512 (schema default) 0.45 Moderate spread
Gemini 512 0.35 gemini-embedding-2-preview, supports MRL truncation
ONNX 1024 0.35 Local BGE-M3 inference, dense + sparse vectors. See ONNX section

EMBEDDING_DIM must match the vector(N) column in your database schema. The default schema uses vector(512). If you use Mistral, you need to alter the column to vector(1024) before storing anything.

Each provider clusters vectors differently, so the similarity threshold matters. Start with the recommended value and adjust based on your results.

Temporal search -- queries with time expressions like "last week" or "three months ago" are resolved automatically using parsedatetime, no configuration needed. This handles roughly 80% of temporal queries at zero cost. For expressions parsedatetime cannot parse ("the quarter before last", "around Thanksgiving"), set TEMPORAL_LLM_MODEL to call an LLM as a fallback:

# Self-hosted with Ollama (free, local)
TEMPORAL_LLM_MODEL=ollama/llama3.2

# Cloud API
TEMPORAL_LLM_MODEL=gpt-4o-mini

Any litellm-compatible model string works -- deepseek/deepseek-chat, moonshot/moonshot-v1-8k, etc. The LLM is only called when parsedatetime fails and the query has temporal intent, so costs stay near zero. If TEMPORAL_LLM_MODEL is empty (the default), parsedatetime handles everything on its own. Requires the litellm package.

Ogham hooks inject memory context at session start and preserve it across compaction. Install for your client:

ogham hooks install
Client What gets installed
Claude Code Hooks in ~/.claude/settings.json (recall on SessionStart/PostCompact, inscribe on PostToolUse/PreCompact)
Kiro Instructions for Hook UI (recall on Prompt Submit, inscribe on Agent Stop)
Codex, Cursor, others Project instruction file (CLAUDE.md, AGENTS.md, or .cursorrules)

Two commands, named after the Ogham stones:

  • recall -- read from the stone. Searches Ogham for memories relevant to your project and injects them as context. Fires at session start and after compaction.
  • inscribe -- carve into the stone. Captures meaningful tool activity as memories. Skips noise (ls, cat, git status) and only stores signal (commits, deploys, errors, config changes). Fires after tool use and before compaction. Secrets are masked before storing.

Disable either flow when you want an agent attached to Ogham without letting it pull memory into context or write new memory:

OGHAM_RECALL_ENABLED=false ogham serve       # no context injection / memory search
OGHAM_INSCRIBE_ENABLED=false ogham serve     # no memory capture / content writes
ogham hooks recall --no-recall               # one-off hook recall skip
ogham hooks inscribe --no-inscribe           # one-off hook capture skip
ogham search "query" --no-recall             # one-off CLI search skip
ogham store "some fact" --no-inscribe        # one-off CLI store skip

For MCP clients, put the env vars in that client's Ogham server config:

{
  "mcpServers": {
    "ogham": {
      "command": "ogham-serve",
      "env": {
        "OGHAM_RECALL_ENABLED": "false",
        "OGHAM_INSCRIBE_ENABLED": "false"
      }
    }
  }
}

Admin operations such as config, health, stats, audit, export, delete, and cleanup remain available so you can inspect or clean memory even when recall or inscribe is disabled.

Smart filtering: Hooks don't capture everything. Routine commands (ls, pwd, git add) are skipped. Only signal events (errors, deployments, commits, config changes) are stored -- typically 20-30 memories per session instead of hundreds.

Secret masking: API keys, tokens, passwords, and JWTs are automatically replaced with ***MASKED*** before storing. The event is captured ("configured Stripe API key") but the actual secret never touches the database.

Memory operations

Tool Description Key parameters
store_memory Store a new memory with embedding content (required), source, tags[], auto_link
store_decision Store an architectural decision decision, reasoning, alternatives[], tags[]
store_preference Store a user preference with strength metadata preference, subject, alternatives[], strength
store_fact Store a factual statement with confidence and citation fact, subject, confidence, source_citation
store_event Store an event with temporal and participant metadata event, when, participants[], location
update_memory Update content of existing memory memory_id, content, tags[]
delete_memory Delete a memory by ID memory_id
reinforce_memory Increase confidence score memory_id
contradict_memory Decrease confidence score memory_id

Search

Tool Description Key parameters
hybrid_search Combined semantic + full-text search (RRF) query, limit, tags[], graph_depth, profiles[], extract_facts
list_recent List recent memories limit, profile
find_related Find memories related to a given one memory_id, limit

Knowledge graph

Tool Description Key parameters
link_unlinked Auto-link memories by embedding similarity threshold, limit
explore_knowledge Traverse the knowledge graph memory_id, depth, direction
suggest_connections Find hidden connections via shared entities memory_id, min_shared_entities, limit

Typed-edge graph (v0.16) -- structural, typed relationships for two-fact join queries. Full detail in /docs/typed-edges/.

Tool Description Key parameters
store_triple Write a typed edge against a controlled predicate vocabulary; supersedes the prior current edge for the same subject + predicate + object subject, predicate, object, profile, source_memory_id
query_join Walk a typed predicate path from a start entity; returns the entities (BFS order), edges, and citations along the path -- no fuzzy ranking start_entity, predicate_path[], hop_limit (required), direction

Importers

Tool Description Key parameters
import_linear Import Linear issues as memories, read-only, deduped by tracker id (v0.16) see /docs/import-linear/

Profiles

Tool Description Key parameters
switch_profile Switch active memory profile profile
current_profile Show active profile --
list_profiles List all profiles with counts --
set_profile_ttl Set auto-expiry for a profile profile, ttl_days

Import / export

Tool Description Key parameters
export_profile Export all memories in active profile format (json, markdown, or okf), include_viewer (default true for OKF)
import_memories_tool Import a JSON export string OR auto-detect an OKF bundle directory by path data, dedup_threshold

--format okf writes an Open Knowledge Format v0.1 conformant bundle: a directory of one-markdown-file-per-memory with YAML frontmatter, a bundle-root index.md declaring okf_version: "0.1", and a self-contained viewer.html (Cytoscape.js graph, opens with file://, no server or CDN needed). Round-trip preserves UUID, content, tags, source, and metadata; the embedding is regenerated on import. Pass include_viewer=false to skip the HTML graph. See docs/okf-format.md for the round-trip contract.

Maintenance

Tool Description Key parameters
re_embed_all Re-embed all memories (after switching providers) --
compress_old_memories Condense old inactive memories (full text to summary to tags) --
cleanup_expired Remove expired memories (TTL) --
health_check Check database and embedding connectivity --
get_config Show runtime configuration with masked secrets --
get_stats Memory counts, sources, tags, and profile health (orphans, decay, tagging) --
get_cache_stats Embedding cache hit rates --

The wiki layer turns a tag full of related memories into a synthesized markdown page. Run compile_wiki on a tag, get back a summarized topic; the cache invalidates automatically when underlying memories change. Four MCP tools cover the lifecycle:

Tool Description Key parameters
compile_wiki Compile a tag's memories into a synthesized markdown page (LLM call, cached) topic, provider, model, force
query_topic_summary Read the cached page for a topic without recomputing topic
walk_knowledge Direction-aware graph walk from a known memory along relationship edges start_id, depth, direction (outgoing, incoming, both), min_strength, relationship_types
lint_wiki Health report: contradictions, orphans, stale lifecycle, stale summaries, summary drift stable_days, sample_size, include_drift

The wiki layer needs an LLM. Synthesis is the LLM step that turns a list of memories into a coherent page; embeddings alone aren't enough. You can run that LLM locally (Ollama with llama3.2, vLLM, or any OpenAI-compatible local server) or in the cloud (Gemini, OpenAI, Anthropic, Mistral, Groq, OpenRouter). Local keeps everything private and free; cloud generally writes more polished prose at the cost of a few cents per compile.

Set the default with LLM_PROVIDER and LLM_MODEL in your environment (e.g. LLM_PROVIDER=gemini + LLM_MODEL=gemini-2.5-flash, or LLM_PROVIDER=ollama + LLM_MODEL=llama3.2). Override per call with compile_wiki(topic=..., provider=..., model=...). The provider/model is stamped into the resulting page's frontmatter, so you can re-compile the same topic with a different LLM and see how the synthesis changes.

compile_wiki short-circuits when the source memories haven't changed since the last compile -- the call is effectively free if nothing has moved. Pass force=True to bypass that check (useful for re-compiling with a different model on the same source set).

The wiki layer requires migrations 028, 030, and 031 applied to your database. See Database setup for details.

Snapshot your wiki layer to a folder of Obsidian-compatible markdown files. One .md per topic with full YAML frontmatter, plus a README.md index. Wikilinks between topics are auto-detected and wrapped in [[brackets]] for Obsidian's graph view.

ogham export-obsidian /path/to/vault
ogham export-obsidian /path/to/vault --profile work --force

The export is read-only -- it writes files but never reads them back. Edits in Obsidian stay in Obsidian; re-run the export to refresh the snapshot. By design the exporter refuses to write into a directory that already contains files it didn't create; pass --force to override that guardrail.

Full guide with frontmatter reference, troubleshooting, and screenshots: obsidian export docs.

Round-trip portability for your memories. Ogham reads and writes Open Knowledge Format (OKF) v0.1, the markdown-based interchange format Google Cloud published in June 2026. The same bundle is portable to any other OKF-speaking tool -- Google's Knowledge Catalog, a colleague's homegrown reader, or your own future system.

# Export your profile as an OKF v0.1 bundle directory
ogham export --format okf

# Round-trip it back (auto-detected as an OKF bundle)
ogham import ogham-okf-<profile>-<timestamp>

The bundle is a directory tree:

ogham-okf-<profile>-<timestamp>/
├── index.md                     # declares okf_version: "0.1"
├── viewer.html                  # self-contained Cytoscape.js graph (opens with file://)
└── memories/
    ├── <slug>-<uuid8>.md        # one markdown file per memory
    └── ...

Each memory file has YAML frontmatter (type, id, tags, timestamp, source, optional title) and the memory body as markdown. type: is derived from the first type:X tag alphabetically (falling back to Memory). Round-trip preserves UUID, content, tags, source, and any extension metadata; the embedding is regenerated on import.

The viewer.html is a 425 KB self-contained file with Cytoscape.js (MIT) vendored inline -- no server, no internet, no CDN. Open it in any browser via file:// to see your memories as a graph coloured by type, with edges following intra-bundle markdown links. Pass include_viewer=false to skip it.

Import behaviour:

  • Memories with the id: extension upsert by UUID (idempotent re-imports).
  • Memories without id: insert as new; the count surfaces as missing_id_count in the result.
  • The importer requires a bundle-root index.md with okf_version declared so pointing it at a random directory fails fast.

User-facing docs: docs/okf-format.md.

From Claude Code (auto-memory MD files)

Claude Code's auto-memory system writes per-project notes under ~/.claude/projects/<encoded-cwd>/memory/. Each note is a markdown file with YAML frontmatter (name, description, type, optional originSessionId). Pull them into Ogham:

ogham import-claude-code ~/.claude/projects/<encoded-cwd>/memory \
    --project ogham --dedup 0.8

Each parseable file becomes one Ogham memory tagged source:claude-code-memory + type:<frontmatter type> + project:<inferred or explicit>. MEMORY.md (the index) and dotfiles are skipped. Files without recognisable frontmatter log a warning and are skipped.

The encoded-cwd directory naming is lossy on hyphenated repo names: openbrain-sharedmemory decodes to sharedmemory because every / and - becomes the same separator. Pass --project NAME to override the inferred tag and keep your project tags consistent.

The importer respects inscribe_enabled() -- --no-inscribe and OGHAM_INSCRIBE_ENABLED=false skip the import. Re-runs are dedup-safe via the --dedup cosine threshold (default 0.8). MCP tool: import_claude_code_memories(directory, project_tag=...).

From Claude.ai (conversation data export)

Anthropic offers a first-party data export at Settings → Privacy → Request your data. After ~24-48h you receive a ZIP containing conversations.json. Pull it into Ogham:

ogham import-claude-ai ~/Downloads/data-<id>-batch-0000 --profile claude-ai

Accepts the ZIP itself, the unzipped directory, or conversations.json directly. Each (human, assistant) turn-pair becomes one memory with the assistant turn as content (the signal you'll search on) and the human prompt in `metadata.u