Skip to main content
Glama

ContextD

面向 AI 编码代理的开发者上下文与语义记忆管理器。

每个会话中,你都要向 Claude Code、Codex 和 Cursor 解释同样的事情:这个项目是什么,为什么队列用的是 NATS 而不是 Redis,提交前要用 rustfmt 格式化,以及你昨晚进行到了哪里。ContextD 将这些信息只存储一次——跨项目、跨代理——并且只返还手头任务真正需要的部分,通过 CLI 和 MCP 服务器提供。

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

设计遵循的两条规则

存储一切,只注入重要的东西。 一年的记忆放不进上下文窗口。检索是混合式的(全文 + 向量),经过排序,并被打包装进一个明确的 token 预算;放不下的部分会被统计出来,绝不悄悄丢掉。

当前的事实必须与历史的事实可区分。 当任务队列从 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)并在新开的 shell 中使用。不想安装就试试:uvx context-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

初始化 home 目录、数据库和配置文件

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 镜像并绑定 agent 文件

import / export <agent>

把上下文导入到 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

显示会话初始上下文,并且受 token 预算限制

memory_search

关键词优先的搜索

memory_get

一次完整读取一条记忆

semantic_recall

通过对记忆的混合检索,回答问题

project_status

显示计数、分支、索引状态

checkpoint_latest

当前目标、下一步、阻碍列表

architecture_decisions

当前有效的架构决策

session_history

哪个 agent 在什么时间做了什么,结果如何

memory_add、checkpoint_create、session_summarize

写入操作(在 --read-only 下会被忽略)

返回结果会包含生命周期状态,只要内容已被取代,它就会被标记为 NOT current,这样模型就不会把历史信息当作当前设计。

多台机器

在笔记本电脑和台式机之间工作,过去意味着两份彼此断开的记忆。ContextD 交换的是记录,不是文件:

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 会先扫描一台机器,再执行重要操作时没有任何压力。它只报告记录数,而不传输内容——所以临时了解一台机器上有多少记忆,只需要几 KB 的传输量,而不是整个记忆库;即使该机器还没有被配置为 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 会加入每个项目的分类明细。contextd inventory 在本地执行相同的扫描。账号以及远程主机的家目录($CONTEXTD_HOME 和 ~/.contextd)都会在那台机器上被解析——如果它们存储在别处,就在远程使用 --remote-home。

需要密码登录的机器

直接从终端运行就可以了,ssh 会像平时一样提示输入密码:

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

密码提示、host key 确认以及 2FA 都能正常工作,因为 ssh 直接会在终端读取这些信息。每条命令自行判断,如果遇到终端,就让 ssh 正常交互;否则——比如 cron 任务、管道、MCP 服务器中——就会传入 BatchMode=yes,缺少密钥时立即失败,而不会挂起等待一个没人回答的提示。强制使用 --interactive 或 --batch 选择一种方式。

在远端已经有 contextD 但 ssh 找不到它

ssh host command 运行的是一个非交互式、非登录的 shell,而未修改的 ~/.bashrc 会在前面就退出;它们等不到后面把 ~/.local/bin 或 ~/.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'

注意引号。如果没有引号,你自己的 shell 会先展开 ~,然后 ContextD才会传给它——而远端配置的路径来自这台机器。如果两个账户的 home 目录结构不同之外,这值得留意。ContextD 会在你记错时给出提示。

一个带引号的 ~/ 或 $HOME/ 路径会在远端展开,而不是在前端展开;即使登录 shell 会打印一段欢迎信息也不会受影响——JSON 数据会从输出中被提取出来。

一次询问替代每一步

每次命令都会打开一次连接,所以 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 会通过 SSH 在远处运行 contextd bundle export,并把返回的内容合并进来。这合并是基于 UUID 的记录:

  • 执行两次不会产生任何第二次效果;

  • 如果相同记录在两边都存在,优先 updated_at 较新的那个;

  • 如果两者都有改动,则保留本地的副本,并将差异列出,而不是默默解决;

  • 记录被取代的关联也会随之迁移,因此在一台机器上完成的“历史”在另一台机器上也会被闭合;

  • 删除也会迁移且持续迁移:一条在笔记本上被删除的记忆,会在桌面上被移除,并通过其中一台机器,也能同步到了第三台机器。

延伸到多台机器的删除

contextd delete 会写一条 tombstone(墓碑记录),记录该记录已在何时被删除。这条墓碑记录像任何普通记录一样被同步。没有它,下一次从仍然保留着这条记忆的机器同步,就会巧妙地把这条记忆传回给你。

删除视为一条带时间戳的决策,因此关于记录最新的决策胜出:

情况

结果

在 A 上删除,B 上未修改

在 B 上被删除,之后所有机器一致

在 A 上删除,B 随后对同一条做了修改

修改获胜,记录复活,墓碑被清除

同时在 A 和 B 上删除

在所有地方删除一次

删除整个项目(contextd detach --purge)是本地清理,故意不同步:一台机器整理自己的东西份额,不应该让其他所有机器都丢失这个项目。

墓碑保留 sync.tombstone_retention_days 天(默认一年),之后由 contextd refresh 清理。如果一台机器一直超过该期间未同步,它仍可能从另一台机器恢复出一条它从未收到过的已删记录——只有当所有机器经常同步时,才把保留时间缩短。

当你可能想找回记录时,优先使用 contextd delete --archive:它是可逆的,也会同步,得到记忆不在检索中出现在预期结果里,但存在 contextd memories --all 中。

这也是“不要去复制 contextd.db”的原因:如果两台机器在最近一次交换后都发生了写入,双方的操作都必须保留,不可能靠文件复制只从中选出一个赢家。

项目跨机器匹配是基于 git 远端(SSH 与 HTTPS 两种形式当同一仓库),然后才是 slug。从一个不同的项目到一台计算机,它没有任何本地路径;在你的 checkout 中运行 context attach 会收养它,而不是为同一代码创建第二个项目。

没有 SSH?一样的工作,只是在文件里完成:

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

Embedding 不会打包传过去——但它们是派生出来的,而且另一台机器可能使用不同的提供方,pull 在本地重新生成 embedding 会比传输快得多。

会话

一个会话是一个记录,是某个 agent 在一个项目上一次连续的、未被打断的工作。contextd mcp serve 会在客户端连接进来时自动打开一个会话,agent 名称从 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

在会话中创建的 Checkpoint 会关联到该会话;记忆和决策会按时间窗口归属角色。这就是绝对“我上次做到哪里了?”的答案:

$ 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 中,评分器是一个 trait(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 trait 进行搜索,它有两个后端:

后端

适用时机

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 维模型换成 bge-m3 的 1024 维),会报告一条修复命令,而不是产生无意义的近邻。

无论选择哪个后端,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 服务器和 CLI 一样,只是 core 的客户端——因此,计划中的演进路径(SQLite → FTS → 嵌入 → 语义记忆 → 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,并通过可信发布将构建的 wheel 发布到 PyPI。

测试会在临时 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

状态

目前已有:项目、记忆、检查点、决策、会话、FTS5 全文搜索、混合语义召回、上下文预算、Claude/Codex/Cursor/通用适配器、带冲突检测的 Markdown 镜像、refresh、通过 SSH 的跨机器同步、可插拔的嵌入提供方(local 或任何 OpenAI 兼容端点)、可插拔的向量存储(SQLite 或 Qdrant),以及 MCP 服务器。

计划中:refresh 内更丰富的冲突解决、更多智能体适配器,以及为通常可达的机器提供定时后台拉取。

许可证

MIT —参见 LICENSE。

Maintenance

ActivityStale
ResponsivenessNo issues

Related MCP Connectors

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
    D
    maintenance
    Enables AI coding agents to retrieve and manage code context with hybrid search, project memory, and observability via MCP tools.
    30
    MIT
  • A
    license
    A
    quality
    B
    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
    MIT
  • A
    license
    Not graded
    quality
    A
    maintenance
    Provides persistent, searchable memory and knowledge capture for AI-assisted development, enabling agents to retain decisions, bugs, and patterns across sessions and projects.
    MIT