ContextD
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 --versionuv 安装发布的普通 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 cargoSQLite 已经编译进去——不需要系统库、不需要 Docker、不需要额外的依赖。支持 Linux、macOS 和 Windows。从源码构建需要 Rust 1.85+。
可选的环境变量:
变量 | 作用 |
| 记忆存放位置(默认 |
| 禁用颜色,与 |
| 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命令
命令 | 作用 |
| 初始化 home 目录、数据库和配置文件 |
| 将仓库关联为一个项目 |
| 显示数量、git 状态、最新检查点、索引健康情况 |
| 记忆的增删改查 |
| 记录一条记忆取代另一条记忆 |
| 在记忆、ADR 和检查点中进行全搜索关键词优先的检索 |
| 提出一个问题,混合语义 + 关键词检索 |
| 保存并恢复“刚做到哪”的状态 |
| 架构决策记录 |
| 工作会话及它们取得的产出 |
| 合并重复、将失去价值的标记历史、重建索引 |
| 生成 Markdown 镜像并绑定 agent 文件 |
| 把上下文导入到 agent 文件,或导出 |
| 要与之交换记忆的机器 |
| 勘察一台机器上有什么,但不复制过来 |
| 对当前机器做同样的勘察 |
| 通过 SSH 一键按记录同步记忆 |
| 相同的交换,只不过用 JSON 文件 |
| 运行 MCP 服务器;列出其工具 |
| 显示设置和路径; |
每个命令都支持 --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暴露出的工具:
工具 | 说明 |
| 显示会话初始上下文,并且受 token 预算限制 |
| 关键词优先的搜索 |
| 一次完整读取一条记忆 |
| 通过对记忆的混合检索,回答问题 |
| 显示计数、分支、索引状态 |
| 当前目标、下一步、阻碍列表 |
| 当前有效的架构决策 |
| 哪个 agent 在什么时间做了什么,结果如何 |
| 写入操作(在 |
返回结果会包含生命周期状态,只要内容已被取代,它就会被标记为 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 firstremote 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=5mpull 会通过 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 otherEmbedding 不会打包传过去——但它们是派生出来的,而且另一台机器可能使用不同的提供方,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 进行搜索,它有两个后端:
后端 | 适用时机 |
| 对数据库中已有的向量进行暴力余弦检索。无需安装任何东西,个人规模下亚毫秒即可完成。 |
| 你已经在运行 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` shipsCI 在 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。
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