ContextD
ContextD
Entwicklerkontext- und semantischer Erinnerungs-Manager für KI-Codierungsagenten.
Du erklärst Claude Code, Codex und Cursor in jeder Session dasselbe: was dieses Projekt ist, warum die Warteschlange NATS statt Redis ist, dass du vor dem Commit mit rustfmt formatierst, und wo du letzte Nacht aufgehört hast. ContextD speichert das einmal – projekteübergreifend und agentübergreifend – und gibt über eine CLI und einen MCP-Server nur die Teile zurück, die für die jeweilige Aufgabe relevant sind.
Claude Code ─┐
Codex ───────┤
Cursor ──────┼── MCP ── ContextD ── SQLite + FTS5 + embeddings
other agents ┘Zwei Regeln, denen das Design folgt
Alles speichern, nur das Relevante einspeisen. Ein Jahr Erinnerungen passt nicht simpackage in ein Kontext fenster. Der Abruf ist hybrid (Volltext + Vektor), gewichtet und in ein explizites Token-Budget queeft; was nicht mehr hineinpasst, wird gezählt und nie stillschweigend verworfen.
Aktuelle Wahrheit muss von historischer Wahrheit unterscheinbare. Wenn eine Warteschlange von Redis über PostgreSQL zu NATS wechselt, muss einem Agent NATS gesagt werden, nicht die Option, die zufällig am häufigsten erwähnt wurde. Überholte Erinnerungen behalten ihren – und bleiben durchsuchbar, sind aber markiert, werden geteert und aus Retrieval ausgeschlossen, es sei denn, sie werden explizit angefragt.
Related MCP server: ContextAtlas
Installation
uv tool install contextd # puts `contextd` on your PATH
contextd --versionuv installiert das veröffentlichte wheel, das die kompilierte Binary enthält – keine Rust-Toolchain und keine Python-Medizin zur Laufzeit. Wird contextd danach nicht gefunden, führe uv tool update-shell aus (uv installiert in ~/.local/bin) und öffne eine neue Shell. Ohne Installation kannst du es testen mit: uvx contextd status.
Aus einem checkout, oder um eine unveröffentlichte Änderung auszuführen:
uv tool install . # builds with your Rust toolchain
cargo install --path . # the same thing, straight from cargoSQLite ist eingebaut – keine Systembibliotheken, kein Docker, keine Dienste, die laufen müssen. Linux, macOS und Windows. Builds aus dem Umbruch erfordert Rust 1.85+.
Optionale Umgebungsvariablen:
Variable | Wirkung |
| Wo der Speicher liegt (default |
Oder Du may keep work and personal Speicher getrennt. | |
NO_COLOR| Farbe deaktivieren, wie auch--no-colorundgeneral.color = "never"| |RUST_LOG| Protokolllevel für die CLI und den MCP-Server; Logs gehen nach stderr, nie nach stdout. |
Schnellstart
contextd init # create ~/.contextd
cd ~/projects/orbit
contextd attach # detects git, name, agent files
contextd add --category architecture \
"GPU scheduler uses NATS for task transport"
contextd checkpoint "worker heartbeat completed" \
--goal "Implement distributed GPU scheduling" \
--done Coordinator --next "Lease-based GPU allocation" \
--problem "Worker reconnect"
contextd search "scheduler" # keyword search, ranked
contextd recall "which message transport does the scheduler use?"
contextd export claude # writes CLAUDE.md
contextd export codex # writes AGENTS.md
contextd status
contextd mcp serve # speak MCP on stdiocontextd status:
ContextD
─────────────────────────────────
Project Orbit
Branch main @ a1b2c3d (2 dirty)
Memories 124
Decisions 18
Checkpoints 7
Last checkpoint
worker heartbeat completed (2 hours ago)
Current goal
Implement distributed GPU scheduling
Next
- Lease-based GPU allocation
Semantic index ✓ 149/149 local · hashing-v1
Agents claude, codex
MCP ✓ contextd mcp serveBefehle
Befehl | Funktion |
| Erstellt Home-Verzeichnis, Datenbank und Konfiguration |
| Verfolgt ein Repository als Projekt |
| Anzahl, Git-Status, letzter Checkpoint, Index-Zustand |
| CRUD für Memory |
| Hobides end that one Memory replaced another |
| Schlüsselwort-first Suche über Memory, ADRs and Checkpoints |
| Frage stelden;hybridisches semantisches + Schlüsselwort-Retrieval |
| "Where was I?" speichern und öfterherstellen |
| Architecture Decision Records |
| Arbeitsanzeige und Sockets das Ergebnis |
| Duplikate zusammenführen, Historie markieren, Indizes neu |
| Markdown- Mirror and bound agent files |
| Context in and from agent files |
| Maschinen, with denen Informationen exchange |
| Bestandsaufnahme a-macht; was es hat, ohne compare it |
| Das gleiche Lokal control |
| Sync memory over SSH, record for record |
| Dieselbe Entsetze als JSON-Datei |
| MCP auslisted; showing tools |
| Zeigt Pfade und Einstellungen; |
Jeder Befehl nimmt --json aspezifische Ausgaben, --project <name>, um auf einem anderen Projekt zu arbeiten, and --home <dir> (oder $CONTEXTD_HOME ), um auf einen anderen Speicher zu zeigen.
MCP
contextd mcp serve # newline-delimited JSON-RPC on stdio
contextd mcp serve --read-onlyRegistriere es bei jedem MCP-Client – für Claude Code:
claude mcp add contextd -- contextd mcp serveAngebotene Tools:
Tool | Verwendung |
| Kontext am Sitzungsbeginn, limitiert auf eine Token-Menge |
| Beantwortet eine Frage aus dem Speicher (hybrid Abruf) |
| Schlüsselwort zuerst Suche |
| Ein einzelnen Speicher vollständig |
|
|
| Aktuelles Ziel, Erledigtes, Nächst, offene Probleme |
`architecture_decisions: | Zurzeit geltende Entscheidungen |
| Welcher Agent wann gewirkt hat, und was dabei froh ist |
| Schreibe (übersprungen bei |
Ergebnisse tragen Lebensphases-Status, und alles, was superseded (überholt) ist, wird NICHT current markiert, damit ein Modell Historynicht mit dem gegenwärtigen Stand verwechselt.
Mehrere Rechner
Zwei Geräte benutzen – Laptop und Desktop – war früher die Sommer bedeutet, zwei Zustand. ContextD tauscht records aus, notfiles:
contextd remote scan dev@lab-box # what does that account hold?
contextd remote add lab dev@lab-box # a Host alias from ~/.ssh/config works too
contextd remote pull lab # bring their memory here
contextd remote push lab # send yours there
contextd remote pull lab --dry-run # see what would change firstremote scan inventarisiert ein Gerät, bevor man sich festlegt. Es meldet Zahlen instead of content; was ist uns on a Maschine ist used little Kilobyte statt deren ganzen Memory, and it zuggte with a destination that has not yet been configured as remote:
$ contextd remote scan lab
lab-box contextd 0.1.0
─────────────────────────────────
Home /home/dev/.contextd
Memories 124 (118 current, 6 superseded)
Decisions 18
Checkpoints 7
Last activity 2 hours ago
Embeddings openai · bge-m3 · vectors in qdrant
project mem adr ckpt last activity last checkpoint
Orbit 80 12 5 2 hours ago worker heartbeat completed
Sable 38 6 2 3 weeks ago parser rewrite landed
plus 6 global memories, applying to every project: 4 convention, 2 user
Nothing was copied. `contextd remote pull lab` merges it here.--detail fügt eine Auflistung pro Projekt hinzu. contextd inventory macht dieselbe Bibliothek lokal. Das Konto is das, unter dem du per SSH eingeloggt bist; das Home-Verzeichnis is on that machine resolved ($CONTEXTD_HOME, otherwise ~/.contextd). Wenn sie woanders liegt, gib --remote--home an.
Rechner, die ein Passwort wollen
Run it in a terminal and ssh will ask, just like in standalone:
$ contextd remote scan dev@lab-box
dev@lab-box's password:Passworteingabe, Host-Key-Checks and 2FA work because ssh reads them from the terminal. Each command decides by itself: if a terminal is present, ssh gets asked; if not no previous date – cron, a Pipeline, the MCP server – it passes BatchMode=yes, so a missing key fails after instead of waiting and waiting. Force either side with --interactive or --batch.
Wenn das Remote über ein installiertes contextd verfügt, ssh es aber nicht findet
ssh host command tries to start a non-interactive, non-login shell, and the stock ~/.bashrc immediately returns those – before the lines that would put ~/.local/bin or ~/.cargo/bin into PATH. Thus contextd can be installed and work there but still be "not found". Which case that is for you:
ssh you@host 'command -v contextd' # nothing? not installed
ssh you@host 'bash -lc "command -v contextd"' # found? a PATH problemBoth ways to fix:
contextd remote add lab you@host --login-shell # read ~/.profile first
contextd remote add lab you@host --command '~/.local/bin/contextd'Note the quotes. If they are missing, your own shell expands ~ before ContextD ever sees it, and so the remote config got a path expressed from that machine – which is relevant when both accounts have different home directories. ContextD notes this if you forget.
A quoted ~/ or $HOME/ path is expanded remote rather than local, and a login shell that emits banner text still doesn't break anything – the JSON result is extracted from the output.
Asking once instead of every time
Each command opens its own connection, so scan and then pull would ask twice. Two ways to avoid that:
ssh-copy-id dev@lab-box # key-based auth, asked once, ever
# or reuse one authenticated connection for a few minutes
contextd remote add lab dev@lab-box \
--ssh-option=-o --ssh-option=ControlMaster=auto \
--ssh-option=-o --ssh-option=ControlPath=~/.ssh/cm-%r@%h:%p \
--ssh-option=-o --ssh-option=ControlPersist=5mpull runs contextd bundle export on the remote via SSH and merges the result. Merging is by UUID, therefore:
Run it twice, second run has no effect;
if a record exists on both sides, the newer
updated_atwins;if both sides were changed, the local copy is kept and the divergence is reported instead of silently resolving;
supersensible tags travel, so endA history closed on one machine remains closed on the other;
deletions travel too, and they keep: a memory deleted on the laptop goes from the desktop and reaches a third machine via either one.
Deleting on multiple machines
contextd delete writes a tombstone – a note of that deletion with a time – and that note travels like any other record. Without it, the next sync from a machine that still has the memory would happily hand it back.
A deletion is treated as a decision with a time, so the most recent decision decides:
Situation | Ergebnis |
On A deleted, on B unchanged | Also removed on B, and on every subsequent machine |
On A deleted, on B later edited | The edit wins, the record returns, the tombster is cleared |
On A and B deleted | Removed everywhere, exactly once |
Deleting an entire project (contextd detach --purge) is a local cleanup and deliberately not synced: when one machine tidies up, it shouldn't force the others to forget the project.
Tombstones are kept for sync.tombstone_retention_days (one year by default) and are then discarded by contextd refresh. A machine that hasn't synced in that time can later reanimate a record that it never knows it's deleted – reduce the retention only if you actually sync enough.
If you might want a record back, prefer contextd delete --archive: it is reversible, it also syncs, and archived memories remain out of Abruf but appear in contextd memories --all.
Copying contextd.db around was deliberately rejected: two devices that both record something since the last exchange must both keep their work, and a file copy can only pick one winner.
Projects are matched on multiple machines by Git remote (SSH and HTTPS URL forms are treated as the same repo), then by slug. An arriving “projekt” has no local path; contextd attach in your checkout pulls it in instead of creating a detour second something projekt.
no SSH? Same exchange as a file:
contextd bundle export --out memory.json # on one machine
contextd bundle import --file memory.json # on the otherEmbeddings are not transported – they are derived; the other machine may use a different provider, and a pull locally rebuilds embeddings faster than it woulda be to send them.
Sitzungen
A session is one sich clinging workstring on one project by one agent. contextd mcp serve opens one automatically as soon as a client connects – the agent’s name comes from the MCP handshake – and closes it when the connection ends. Our terminal:
contextd session start --agent claude
contextd session end "heartbeat wired up"
contextd session list
contextd session show # what the current or last session producedCheckpoints can be linked to during a session; memories and decisions are attributed using the time window. That turns "what happened last time?" into a real answer:
$ contextd session show
Session b506bd93
─────────────────────────────────
agent claude
window 2026-08-24T14:42:21Z → 2026-08-24T15:10:03Z
ran 27m 42s
summary heartbeat wired up
Checkpoints
6e702570 worker heartbeat completed
Memories
069a5f19 [architecture] GPU scheduler uses NATS for task transportPro Projekt ist nur eine Sitzung geöffnet: Wird eine neue gestartet, schließt das die vorherige, sodass ein abgestürzter Agent nicht die Arbeit des nächsten einsammeln kann. Sitzungen zeichnen Aktivitäten auf dieser Maschine auf und bleiben daher lokal — contextd bundle transportiert das Wissen, nicht die Anwesenheit.
So funktioniert das Retrieval
query → project detection → FTS5 → semantic → ranking → token budget → contextDer Score eines Kandidaten ist eine gewichtete Summe, multipliziert mit einem Lifecycle-Faktor:
(fts + semantic + priority + recency + project_match) × status_multiplierJedes Gewicht steht in config.toml, und der Scorer ist ein Trait (search::scoring::Scorer), sodass die Formel ausgetauscht werden kann, ohne das Retrieval anzufassen. contextd search --explain gibt die Aufschlüsselung pro Treffer aus.
Embeddings
Der Standard-Provider ist lokal: ein Offline-Feature-Hashing-Embedder — kein Modell-Download, kein Netzwerk, kein API-Schlüssel. Er erfasst lexikalische Überlappung und Formulierung, was für hybrides Retrieval reicht, um Schlüsselwörter allein zu schlagen, aber er kann Wörter, die nie gemeinsam vorkommen, nicht in Beziehung setzen.
Für echtes Paraphrase-Matching richtest du ContextD auf einen beliebigen OpenAI-kompatiblen Endpunkt (Ollama, TEI, vLLM, LM Studio, OpenAI selbst). bge-m3 ist ein guter Standard: mehrsprachig, sodass eine Frage auf Chinesisch eine auf Englisch geschriebene Erinnerung findet.
ollama pull bge-m3
contextd config set embeddings.provider openai
contextd config set embeddings.model bge-m3
contextd config set embeddings.api_base http://localhost:11434/v1
contextd config set embeddings.dimensions 1024
contextd config --check # asks the endpoint for a real vector
contextd refresh --force-embeddings # re-embed with the new modelDer API-Schlüssel wird, wenn einer benötigt wird, aus der Umgebungsvariable gelesen, die in embeddings.api_key_env benannt ist — und nie in die Konfigurationsdatei oder die Datenbank geschrieben. provider = "none" deaktiviert Vektoren vollständig und ContextD fällt auf Volltextsuche zurück.
Vektorspeicher
Vektoren werden über einen VectorIndex-Trait mit zwei Backends durchsucht:
Backend | Wann |
| Brute-Force-Cosinus über die Vektoren, die bereits in der Datenbank sind. Nichts zu installieren, sub-Millisekunden in persönlichen Maßstab. |
| Du betreibst bereits Qdrant, oder deine Erinnerung ist über einen Scan hinausgewachsen. |
contextd config set vector.backend qdrant
contextd config set vector.url http://localhost:6333
contextd config set vector.collection contextd
contextd refresh --reindex-vectors # publish existing vectors, no re-embedding
contextd config --checkDie Kollektion wird beim ersten Verwenden erstellt, dimensioniert nach dem Embedding-Modell und mit Cosinus-Distanz; eine bestehende Kollektion mit falscher Breite (etwa beim Wechsel von einem 384-Dimensionen-Modell auf bge-m3's 1024) wird mit dem Befehl gemeldet, der sie korrigiert, statt bedeutungslose Nachbarn zu erzeugen.
SQLite behält die maßgebliche Kopie jedes Vektors, welches Backend auch immer gewählt ist, sodass ein externer Index immer neu erstellt werden kann, contextd bundle weiter läuft und eine Maschine ohne Qdrant dieselbe Erinnerung lesen kann.
Wenn der Vektorspeicher oder der Embedding-Endpunkt nicht erreichbar ist, fällt das Retrieval auf Volltextsuche zurück und sagt das auch — context viele status zeigt das Backend und ob es antwortet.
Speicherlayout
SQLite ist die Quelle der Wahrheit. Der Markdown-Spiegel existiert, damit du deine Erinnerungen lesen, diffen und committen kannst:
~/.contextd/
├── config.toml
├── contextd.db
├── projects/Orbit/
│ ├── overview.md architecture.md decisions.md tasks.md
│ └── checkpoints/
└── global/
├── coding.md git.md preferences.mdDeine Dateien gehören dir
Generierte Inhalte leben in einem markierten Block:
# House rules ← yours, never touched
Never force-push to main.
<!-- contextd:begin -->
...generated context... ← ContextD's
<!-- contextd:end -->ContextD zeichnet einen Hash dessen auf, was es geschrieben hat. Wenn der Block sich danach verändert hat, verweigert contextd export den Export und beendet sich mit einem Nicht-Null-Exitcode, bis du --force übergibst. Das Gleiche gilt für den Markdown-Spiegel, wo contextd sync --adopt deine manuellen Bearbeitungen in Erinnerungen verwandelt, statt sie zu verwerfen.
Architektur
cli / mcp entry points (thin)
↓
agents per-agent import/export adapters
↓
core projects, memories, checkpoints, context building
↓
search / embeddings retrieval, pluggable providers
↓
storage repository traits + SQLite implementationJede Schicht hängt nur von den darunterliegenden ab. Nichts oberhalb von storage erwähnt SQLite, nichts oberhalb von embeddings nennt einen Provider, und der MCP-Server ist ein Client von core ganz genau wie das CLI — damit aus der geplanten Entwicklung (SQLite → FTS → Embeddings → semantisches Gedächtnis → MCP) nicht ein verworren fand eines einzigen Moduls wird.
src/
├── cli/ argument parsing, rendering, one module per command group
├── core/ model, project, memory, checkpoint, decision, session, context, refresh
├── storage/ repository traits + sqlite/ (migrations, FTS, vectors)
├── search/ fulltext, semantic, hybrid fusion, scoring, indexer
│ └── vector/ VectorIndex trait, sqlite scan, qdrant client
├── embeddings/ EmbeddingProvider trait, local, openai-compatible
├── agents/ AgentAdapter trait, claude, codex, cursor, generic
├── sync/ agent files, Markdown mirror, bundles, SSH remotes
├── mcp/ JSON-RPC protocol, tools, stdio server
├── config/ config.toml, path resolution
└── ui/ terminal formattingEntwicklung
cargo fmt
cargo clippy --all-targets
cargo test # unit + CLI + MCP + migration tests
uv build --wheel # the artefact `uv tool install contextd` shipsCI führt die gleichen drei Befehle auf Linux, macOS und Windows aus und prüft, dass das Wheel sich installieren und läuft. Das Taggen mit v* baut Wheels für jede Plattform und veröffentlicht sie über Trusted Publishing auf PyPI.
Tests laufen gegen temporäre CONTEXTD_HOME-Verzeichnisse und fassen deinen echte Speicher nie an.
Konfiguration
contextd config gibt Pfade und aktuelle Einstellungen aus; contextd config --toml gibt die Datei aus. Wichtige Stellschrauben:
[context]
max_context_tokens = 6000 # the injection budget
max_memories = 40
[vector]
backend = "sqlite" # or "qdrant"
url = "http://localhost:6333"
collection = "contextd"
[search]
fts_weight = 1.0
semantic_weight = 1.0
priority_weight = 0.35
recency_weight = 0.25
project_weight = 0.5
recency_half_life_days = 90.0
superseded_penalty = 0.35 # how far history is pushed below current truth
[sync]
tombstone_retention_days = 365 # how long deletions keep propagating
[refresh]
duplicate_threshold = 0.9 # at or above this, memories are merged
similar_threshold = 0.65 # at or above this, they are reported
summarizer = "none" # or "openai" to consolidate clustersStatus
Heute funktioniert: Projekte, Erinnerungen, Checkpoints, Entscheidungen, Sessions, FTS5-Suche, hybrides semantisches Abrufen, Kontext-Budgetierung, Claude/Codex/Cursor/generische Adapter, Markdown-Spiegel mit Konflikterkennung, Refresh, Cross-Machine-Sync über SSH, austauschbare Embedding-Provider (lokal oder ein beliebiger OpenAI-kompatibler Endpunkt), austauschbare Vektorspeicher (SQLite oder Qdrant) und der MCP-Server.
Geplant: Umfassendere Konfliktlösung in refresh, weitere Agent-Adapter und ein geplanter Hintergrund-Pull für Maschinen, die in der Regel erreichbar sind.
Lizenz
MIT — siehe LICENSE.
This server cannot be installed
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Servers
- AlicenseAqualityDmaintenanceProvides persistent memory for AI agents using hybrid search (vector embeddings + BM25) with neural reranking, enabling storage and retrieval of insights, debugging solutions, and patterns across coding sessions.8MIT
- AlicenseNot gradedqualityCmaintenanceEnables AI coding agents to retrieve and manage code context with hybrid search, project memory, and observability via MCP tools.29MIT
- AlicenseNot gradedqualityBmaintenanceEnables infinite searchable memory for coding agents across sessions, allowing them to recall past decisions and context.4814MIT
- AlicenseAqualityAmaintenanceProvides persistent, searchable memory across AI coding agent and chat history (Claude Code, Codex, Gemini CLI, ChatGPT, and more) via retrieval-augmented generation, enabling semantic and hybrid search to retain context across sessions.55MIT
Related MCP Connectors
Persistent memory and knowledge graphs for AI agents. Hybrid search, context checkpoints, and more.
Persistent memory for AI agents. Search, store, and recall across sessions.
Universal memory for AI agents and tools. Save, organize and search context anywhere.
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/JohnsonWang1015/ContextD'
If you have feedback or need assistance with the MCP directory API, please join our Discord server