Skip to main content
Glama

ContextD

Менеджер контекста разработчика и семантической памяти для ИИ-агентов, пишущих код.

Вы в каждой сессии объясняете Claude Code, Codex и Cursor одно и то же: что это за проект, почему очередь — это NATS, а не Redis, что перед коммитом вы форматируете код с помощью rustfmt, и где вы остановились вчера ночью. ContextD сохраняет это один раз — для всех проектов и всех агентов — и возвращает только те части, которые важны для текущей задачи, через CLI и MCP-сервер.

Claude Code ─┐
Codex ───────┤
Cursor ──────┼── MCP ── ContextD ── SQLite + FTS5 + embeddings
other agents ┘

Два правила, которым следует дизайн

Хранить всё, внедрять только то, что важно. Год памяти не помещается в контекстное окно. Поиск гибридный (полнотекстовый + векторный), ранжированный и упакованный в явный лимит токенов; то, что не поместилось, учитывается, а не молча отбрасывается.

Актуальную правду должно быть можно отличить от исторической. Когда очередь задач переезжает Redis → PostgreSQL → NATS, агенту нужно сообщать NATS, а не тот вариант, который чаще всего упоминается. Заменённые записи сохраняют содержимое и остаются доступными для поиска, но помечаются, получают штраф при ранжировании и исключаются из выдачи, если их явно не запросили.

Related MCP server: ContextAtlas

Установка

uv tool install contextd        # puts `contextd` on your PATH
contextd --version

uv устанавливает опубликованный wheel, в который уже встроен скомпилированный бинарник — ни Rust-тулчейна, ни Python в рантайме не нужно. Если после установки contextd не находится, выполните uv tool update-shell (uv ставит в ~/.local/bin) и откройте новую оболочку. Чтобы попробовать без установки: uvx contextd status.

Из локального клона репозитория, или чтобы запустить ещё не выпущенное изменение:

uv tool install .               # builds with your Rust toolchain
cargo install --path .          # the same thing, straight from cargo

SQLite встроен — никаких системных библиотек, Docker или служб запускать не нужно. Linux, macOS и Windows. Сборка из исходников требует Rust 1.85+.

Дополнительные переменные окружения:

Переменная

Действие

CONTEXTD_HOME

Где живёт память (по умолчанию ~/.contextd) — укажите на синхронизируемую папку или разделите рабочую и личную память

NO_COLOR

Отключает цвет, как и --no-color и general.color = "never"

RUST_LOG

Уровень журнала для CLI и MCP-сервера; логи идут в stderr, никогда в stdout

Быстрый старт

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 stdio

contextd 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 serve

Команды

Команда

Что делает

init

Создать домашний каталог, базу данных и конфигурацию

attach / detach / list

Связать репозиторий как проект

status

Счётчики, состояние git, последний чекпойнт, состояние индекса

add / edit / delete / show / memories

Работа с записями памяти

supersede <old> <new>

Зафиксировать, что одна запись заменила другую

search

Поиск по ключевым словам среди записей, ADR и чекпойнтов

recall

Задать вопрос; гибридный семантический + текстовый поиск

checkpoint / resume

Сохранить и восстановить «где я остановился?»

decision add/list/show/supersede

Записи архитектурных решений

session start/end/list/show

Рабочие сессии и их результаты

refresh

Объединять дубликаты, помечать историю, пересобирать индексы

sync

Записать Markdown-зеркало и файлы, привязанные к агентам

import / export <agent>

Переносить контекст в файлы агента и обратно

remote add/list/remove

Машины для обмена памятью

remote scan

Обследовать машину: что на ней, не копируя

inventory

То же обследование этой машины

remote pull / remote push

Синхронизировать память по SSH, запись за записью

bundle export/import

Тот же обмен в виде JSON-файла

mcp serve / mcp tools

Запустить MCP-сервер; перечислить его инструменты

config

Показать пути и настройки; set, get, --check

Каждая команда принимает --json для скриптов, --project <name> для работы с другим проектом и --home <dir> (или $CONTEXTD_HOME) для указания на другое хранилище.

MCP

contextd mcp serve            # newline-delimited JSON-RPC on stdio
contextd mcp serve --read-only

Зарегистрируйте его в любом MCP-клиенте — например, для Claude Code:

claude mcp add contextd -- contextd mcp serve

Доступные инструменты:

Инструмент

Назначение

project_context

Контекст в начале сессии с ограничением по лимиту токенов

semantic_recall

Ответ на вопрос из памяти (гибридный поиск)

memory_search

Поиск по ключевым словам

memory_get

Одна запись целиком

project_status

Счётчики, ветка, состояние индекса

checkpoint_latest

Текущая цель, сделанное, следующий шаг, открытые проблемы

architecture_decisions

Решения, действующие на текущий момент

session_history

Какой агент и когда работал, и что из этого вышло

memory_add, checkpoint_create, session_summarize

Запись (отсутствуют в режиме --read-only)

Результаты содержат статус жизненного цикла, а всё заменённое помечается как NOT current, чтобы модель не приняла историю за текущее состояние проекта.

Несколько машин

Работа на ноутбуке и на рабочей станции раньше означала две изолированные памяти. ContextD обменивает records, а не файлы:

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 first

remote scan обследует учётную запись до того, как вы на что-то решитесь. Он сообщает счётчики, а не содержимое, поэтому выяснить, что находится на машине, стоит пару килобайт, а не всю память; и он работает с целевой машиной, которая ещё не является настроенным удалённым узлом:

$ 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 добавляет разбивку по категориям для каждого проекта. contextd inventory выполняет такое же обследование локально. Учётная запись — это ваша учётная запись для входа по SSH, а домашний каталог определяется уже на той машине ($CONTEXTD_HOME, else ~/.contextd) — передайте --remote-home, если он расположен .[A].

Машины, которые требуют пароль

Запустите из терминала, и ssh спросит, как спросил бы сам:

$ contextd remote scan dev@lab-box
dev@lab-box's password:

Prompt пароля, подтверждение host-ключей и 2FA работают, потому что ssh читает их прямо с терминала. Каждая команда решает сама: при наличии терминала она позволяет ssh подиграть, а без терминала — cron, конвейер, MCP-сервер — передаёт BatchMode=yes, чтобы отсутствующий ключи не повис на вопросе, который никто не услышит. Принудительно задают этот режим с помощью --interactive или --batch.

Когда на удалённой стороне есть contextd, но ssh его не находит

ssh host command запускает неинтерактивный shell без логина, и стандартный ~/.bashrc для таких вызовов завершается сразу — до строк, которые добавляют ~/.local/bin or ~/.cargo/bin в PATH. Поэтому contextd может быть установлен и работать там, но остаётся «not found». В каком вы случае:

ssh you@host 'command -v contextd'                  # nothing? not installed
ssh you@host 'bash -lc "command -v contextd"'       # found? a PATH problem

Любое из исправлений работает:

contextd remote add lab you@host --login-shell                 # read ~/.profile first
contextd remote add lab you@host --command '~/.local/bin/contextd'

Обратите внимание на кавычки. Без них ваша оболочка развернёт ~ до того, как ContextD это увидит, а удалённая машина будет настроена с путьом этой машины — и это стоит учитывать, если у двух учёт;a записи по‑разаные домашние каталоги. ContextD предупредит вас об этом недочёте.

Путь в кавычках ~/ или $HOME/ разворачивается на удалённом узле, а не локально, и login-shell, печатающий приветственный банер, ничего не сломает — JSON-payload выхватывается из вывода.

Спрашивать один раз вместо каждого раза

Каждая команда открывает собственное подключение, поэтому scan, затем pull, спросит дважды. Два способа этого избежать:

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=5m

pull выполняет contextd bundle export на удалённой стороне по SSH и объединяет результаты. Слияние — по UUID, поэтому:

  • запуск повторно во второй раз уже ничего не меняет;

  • если запись есть обеих сторон, побеждает более новая по updated_at;

  • если изменились обе стороны, сохраняется локальная копия, а расхождение выводится в списке, а не разрешается молча;

  • связи «заменено» переносятся, поэтому история, закрыто на одной машине, остаётся закрытой и на на другой;

  • удаления тоже переносятся и продолжают двигаться: запись, удалённая на ноутбуке, удаляется на рабочей станции и достигает третьей машины через одну из них.

Удаление на нескольких сторонах

contextd delete создаёт tombstone — пометку, что запись была удалена и когда, — и эта пометка синхронизируется, как и любая другая запись. Без неё следующая синхронизация с машины, где запись ещё есть, с препятствием вернула бы всё назад.

Удаление трактуется как решение о времени, поэтому действует последнее решение о записи:

Ситуация

Результат

Удалено on A, не тронуто on B

Удалено на B, и на всех машинах после этого

Удалено on A, затем изменено on B

Изменение побеждает; запись возвращается, tombstone очищается

Удалено и на A, и на B

Удалено везде, один раз

Удаление целого проекта (contextd detach --purge) — локальная очистка и намеренно не синхронизируется: одна машина прибирающая не должна заставлять другие забыть проект.

Tombstones хранятся в течение sync.tombstone_retention_days (по умолчанию год), а затем забываются командой contextd refresh. Машина, не синхронизировавшаяся дольше этого срока, по-прежнему может оживить запись, удаление которой она не обнаружила; уменьшайте срок хранения только если все машины синхронизируются часто.

Если вы хотите вернуть запись, выбирайте contextd delete --archive: это обратимо, оно тоже синхронизируется, и архивные записи не участвуют в выдаче, оставаясь доступными в contextd memories --all.

Копирование contextd.db было отклонено осознанно: если обе машины записали что-то после последнего обмена, они должны сохранить работы каждой, а копия файла может победит вовсе.

Проекты на разных машинах сопоставляются by git-ransactions: use унифицируемых форм URL SSH и HTTPS как одних и га же repository, а затем по slug. Проект, пришедший из другого места, не имеет локального пути; запуск contextd attach в твоем checkout-е усваивается его, не создавая второй проекта для того же кода.

Нет SSH? Tо обмен через файл:

contextd bundle export --out memory.json     # on one machine
contextd bundle import --file memory.json    # on the other

Весы не терюбо vanлки: offtherepолangan fromget or sun"а не отображаются — they are calculaj, on другой может use different provider, and при пул extract first результативно локально, чем это заняла бы передача.

Сессии

Сессия — это один отрезоль работы над проектом одним агентом. contextd mcp serve открывает её автоматически при подключении клиента — имя агента берётся из MCP-рукопожатия — и закрывает при разрыве соединения. Из терминала:

contextd session start --agent claude
contextd session end "heartbeat wired up"
contextd session list
contextd session show          # what the current or last session produced

Чекпойнты, созданnet в открытой сессии, связаны в ней; записи памяти и решения атрибутируются по временному окну. Это превращает «что было в прошлый раз?» в настоящий ответ:

$ 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 transport

На один проект открыта только одна сессия: запуск новой закрывает предыдущую, поэтому агент, который упал, не сможет забрать работу следующего агента. Сессии записывают активность на этой машине, поэтому они остаются локальными — contextd bundle переносит знания, а не посещаемость.

Как работает поиск

query → project detection → FTS5 → semantic → ranking → token budget → context

Оценка кандидата — взвешенная сумма, умноженная на коэффициент жизненного цикла:

(fts + semantic + priority + recency + project_match) × status_multiplier

Каждый вес живёт в config.toml, а скорер — это трейт search::scoring::Scorer, поэтому формулу можно заменить, не трогая поиск. contextd search --explain выводит разбивку по каждому совпадению.

Эмбеддинги

Провайдер по умолчанию — local: офлайн-эмбеддер на хешировании признаков — без загрузки модели, без сети, без API-ключа. Он улавливает лексическое пересечение и формулировки — этого достаточно, чтобы гибридный поиск превзошёл поиск по ключевым словам, но он не может связать слова, которые никогда не встречаются вместе.

Для настоящего сопоставления парафраз направьте ContextD на любой OpenAI-совместимый эндпоинт (Ollama, TEI, vLLM, LM Studio или сам OpenAI). bge-m3 — хороший выбор по умолчанию: он мультиязычный, поэтому вопрос на китайском найдёт воспоминание, записанное на английском.

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 model

API-ключ, когда он нужен, читается из переменной окружения, указанной в embeddings.api_key_env, — и никогда не записывается ни в конфигурационный файл, ни в базу данных. provider = "none" полностью отключает векторы, и ContextD возвращается к полнотекстовому поиску.

Векторное хранилище

Векторы ищутся через трейт VectorIndex с двумя бэкендами:

Backend

Когда

sqlite (по умолчанию)

Полный перебор с косинусной близостью по векторам, уже лежащим в базе. Ничего устанавливать не нужно, меньше миллисекунды при личном масштабе данных.

qdrant

Вы уже запускаете Qdrant или ваша память выросла больше одного сканирования.

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 --check

Коллекция создаётся при первом использовании, её размер берётся из эмбеддинг-модели, а расстояние считается косинусным. Если существующая коллекция имеет неверную ширину (например, вы перешли с модели на 384 измерения на 1024 у bge-m3), будет выведено сообщение с командой, которая это исправляет, — вместо бессмысленных соседей.

SQLite хранит эталонную копию каждого вектора независимо от выбранного бэкенда, поэтому внешний индекс всегда можно пересобрать, contextd bundle продолжает работать, а машина без Qdrant всё ещё может читать ту же самую память.

Если векторное хранилище или эмбеддинг-эндпоинт недоступны, поиск откатывается к полнотекстовому и сообщает об этом — contextd status показывает бэкенд и отвечает ли он.

Структура хранения

SQLite — источник истины. Markdown-зеркало существует, чтобы можно было читать, диффить и коммитить свою память:

~/.contextd/
├── config.toml
├── contextd.db
├── projects/Orbit/
│   ├── overview.md  architecture.md  decisions.md  tasks.md
│   └── checkpoints/
└── global/
    ├── coding.md  git.md  preferences.md

Ваши файлы — ваши

Сгенерированное содержимое живёт внутри размеченного блока:

# House rules            ← yours, never touched
Never force-push to main.

<!-- contextd:begin -->
...generated context...  ← ContextD's
<!-- contextd:end -->

ContextD записывает хеш того, что он написал. Если блок с тех пор изменился, contextd export отказывается и завершается с ненулевым кодом, пока вы не передадите --force. То же самое относится к Markdown-зеркалу: contextd sync --adopt превращает ваши ручные правки в воспоминания, а не отбрасывает их.

Архитектура

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 implementation

Каждый уровень зависит только от уровней ниже. Ни один код выше storage не упоминает SQLite, ничто выше embeddings не называет провайдера, а MCP-сервер — клиент support точно так же, как и CLI. Поэтому запланированная эволюция (SQLite → FTS → embeddings → semantic memory → MCP) не превращается в один запутанный модуль.

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 formatting

Разработка

cargo fmt
cargo clippy --all-targets
cargo test              # unit + CLI + MCP + migration tests

uv build --wheel        # the artefact `uv tool install contextd` ships

CI запускает те же три команды на Linux, macOS и Windows и проверяет, что wheel устанавливается и запускается. Теги v* собирают wheel для всех платформ и публикуют их в PyPI через trusted publishing.

Тесты работают с временными каталогами CONTEXTD_HOME и никогда не касаются вашего настоящего хранилища памяти.

Конфигурация

contextd config выводит пути и текущие настройки, а contextd config --toml печатает сам файл. Примечательные параметры:

[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 clusters

Статус

[ Current ]: проекты, воспоминания, контрольные точки, решения, сессии, поиск FTS5, поиск, контекстное бюджетирование, адаптеры Claude/Codex/Cursor/уникальный универсальный./общий, Markdown-зеркало с обнаружением конфликтов, refresh, синхронизация между машинами по SSH, подключаемые эмбеддинг-провайдеры (local или любой OpenAI-совместимый эндпоинт), подключаемые векторные хранилища (SQLite или Qdrant) и MCP-сервер.

В планах: более точное разрешение конфликтов в refresh, больше адаптеров для агентов и запланируемый фоновый pull для машин, которые обычно доступны.

Лицензия

MIT — см. LICENSE.

A
license - permissive license
Not graded
quality - not tested
B
maintenance

Maintenance

Maintainers
Response time
Release cycle
Releases (12mo)
Commit activity

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

  • A
    license
    A
    quality
    D
    maintenance
    Provides 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.
    8
    MIT
  • A
    license
    Not graded
    quality
    C
    maintenance
    Enables AI coding agents to retrieve and manage code context with hybrid search, project memory, and observability via MCP tools.
    29
    MIT
  • A
    license
    A
    quality
    A
    maintenance
    Provides 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.
    5
    5
    MIT

View all related MCP servers

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.

View all MCP Connectors

Latest Blog Posts

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