关于 codeagent-memory
codeagent-memory(cam)是面向编码 Agent 的本地代码图谱与对话记忆系统。基于 Rust 的单一程序结合符号级仓库导航和可检索的项目知识,主 Agent 使用 MCP,子 Agent 使用命令行。
主要功能
- 01基于 Tree-sitter 的代码图谱与符号导航
- 02增量索引和文件监视
- 03向量与 BM25 混合记忆检索
- 04分支记忆层级与修订关联
- 05本地 SQLite 存储和嵌入
适用场景
- 01查找函数并追踪其调用方
- 02跨会话回忆项目决策
- 03通过命令行向子 Agent 提供代码导航
MCP 相关
使用 `cam mcp` 启动面向主 Agent 的 stdio MCP 服务,提供代码图谱和记忆操作;子 Agent 可使用对应的命令行接口。
配置
本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。
docker run -i --rm ghcr.io/hanochzhu/codeagent-memory:0.1.5本地服务需要在你的电脑上安装运行环境(如 Node.js 18+)。各客户端的配置文件位置不同,请参考客户端文档。
ghcr.io/hanochzhu/codeagent-memory:0.1.5stdio工具
本地服务需要在你的电脑上运行后才能读取工具,维护者暂未提供工具列表。
详细介绍
cam
English · 中文 · 日本語 · 한국어 · العربية · 🌐 网站
专为编码 Agent 打造的本地多轮对话记忆系统
代码图谱 + 记忆 · 精准读取 · 100% 本地 · MCP + CLI
内核采用 Rust 编写
目录
指南:交互式展示(网站) · 主 Agent 与子 Agent · 各 IDE 的 MCP 配置 · 中文说明
为什么选择 cam?
当 AI 编码 Agent 探索代码仓库时,通常会用低效的方式重新发现项目结构——逐个文件运行 grep、glob 并完整读取文件,然后在下一个会话中忘掉所有信息。
cam 在一个二进制文件中为 Agent 提供两个本地检索层:
| 层 | 存储内容 | Agent 的使用方式 |
|---|---|---|
| 代码图谱 | Tree-sitter 符号(函数、类型、方法),构成虚拟文件系统,并包含 1 跳调用者/被调用者 | ls、find、read src/file.rs/symbol、ref symbol --dir in|out——精准读取符号,而不是转储整个文件 |
| 记忆树 | 项目事实、架构决策、调试记录和用户习惯 | recall(向量 + BM25,通过 RRF 融合)和 add(支持分支参数 --parent 和修订参数 --supersedes) |
一个二进制文件,两种接口: 主 Agent 通过 MCP 调用
cam(cam mcp);子 Agent(通常不会继承 MCP 工具)调用完全相同的 CLI(cam --json …)。两者共用磁盘上的.cam/cam.db,100% 本地运行,无 API 费用。
快速开始
选项 1:一句话安装 Agent(推荐)
将此提示词直接粘贴到你的编码 Agent(Cursor、Claude Code、Codex、Windsurf、GitHub Copilot、Cline 等)中,让它为你安装、建立索引并配置 cam:
Install cam from https://github.com/HanochZhu/codeagent_memory: require a working Rust toolchain (rustup), run `cargo install --git https://github.com/HanochZhu/codeagent_memory --locked`, ensure ~/.cargo/bin (or %USERPROFILE%\.cargo\bin on Windows) is on PATH, then verify with `cam --help`. In this repo run `cam index`. For the main agent, register MCP stdio: command `cam`, args `["mcp"]` (Cursor: .cursor/mcp.json; Claude Code: .mcp.json). Subagents call `cam --json` in the shell. Do not add extra docs.
各 IDE / Agent 如何处理此提示词
| 环境 | 操作 |
|---|---|
| Cursor / Windsurf / Claude Code / Codex | 粘贴到 Agent / Chat 中;Agent 会运行终端安装、构建 .cam/cam.db 并写入 MCP 配置 |
| VS Code(Copilot / Continue / Cline) | 在启用了终端访问权限的 Agent / Chat 模式中粘贴 |
| JetBrains(IntelliJ / RustRover / GoLand) | 粘贴到 AI Assistant 中,或在内置终端中运行 cargo install |
注意:cargo install 会将 cam 安装到 ~/.cargo/bin(Windows:%USERPROFILE%\.cargo\bin)。如果在 PATH 中找不到 cam,请重启终端或 IDE。
选项 2:手动设置
1. 安装 CLI
需要 Rust 工具链:
cargo install --git https://github.com/HanochZhu/codeagent_memory --locked
cam --help
替代方案:从本地克隆构建或通过 Docker 运行
从本地克隆构建:
git clone https://github.com/HanochZhu/codeagent_memory.git
cd codeagent_memory
cargo install --path . --locked
Docker(无需 Rust 工具链):
docker pull ghcr.io/hanochzhu/codeagent-memory:0.1.5
docker run -i --rm -v "$PWD:/work" -w /work ghcr.io/hanochzhu/codeagent-memory:0.1.5
或者在本地构建:docker build -t cam https://github.com/HanochZhu/codeagent_memory.git
2. 为项目建立索引并进行查询
cd your-project
cam index # parse repo into .cam/cam.db
# Query the code graph
cam ls src/ # list files or symbols in a file
cam read src/main.rs/main # read a single symbol body
cam ref main --dir in # 1-hop callers (in) or callees (out)
# Query & write to the memory tree
cam recall "how does hybrid recall fuse BM25 and vectors"
cam add --summary "..." < notes.md
cam 首次使用时会自动初始化 .cam/。如果希望文件变更时实时增量更新图谱,可在后台运行 cam watch。
3. 为主 Agent 连接 MCP
将 cam mcp 添加到宿主的 MCP 配置中(例如 .cursor/mcp.json 或 .mcp.json):
{
"mcpServers": {
"cam": {
"command": "cam",
"args": ["mcp"]
}
}
}
请参阅 docs/mcp.md,了解各宿主专用的配置路径;另请参阅 docs/agents.md,了解主 Agent / 子 Agent 的提示词规则。
首次执行 recall 或 add 时,会下载默认嵌入模型(potion-multilingual-128M 至 ~/.cam/models/);如果处于离线状态,则会回退到词法哈希嵌入器。
主要功能
| 功能 | 详情 |
|---|---|
| SQLite 代码图谱 | Tree-sitter 将函数、类型和调用边解析到 .cam/cam.db,实现即时的符号级导航 |
| 虚拟路径 | src/main.rs 指向文件大纲;src/main.rs/main 可直接定位到符号主体 |
| 实时增量同步 | cam sync 对文件内容进行哈希;cam watch 会在文件保存时更新图谱 |
| 混合召回(RRF) | 通过倒数排名融合($k=60$),结合本地稠密嵌入(model2vec)与支持标识符的 BM25 |
| 修订链与树 | --parent 构建分支主题层级;--supersedes 链接线性修订,并自动折叠较早的条目 |
| 艾宾浩斯记忆保留 | 保留率 $R = e^{-t / S}$ 会轻微影响排名($\le 10%$),并标记 stale / needs_update 记忆,而不删除历史记录 |
| 双接口(MCP + CLI) | 主 Agent 使用 cam_* MCP 工具;子 Agent 在 shell 中运行 cam --json … |
| 100% 本地且私密 | 无需外部 API 密钥;完全基于本地 SQLite 和磁盘上的嵌入运行 |
| 9 种语言 | Rust、Python、TypeScript、JavaScript、Go、Java、C、C++、C# |
工作原理
- 提取 —
tree-sitter遍历工作区,并将符号定义和调用边存储在.cam/cam.db中。 - 精准读取 — Agent 通过虚拟路径导航(
ls→find→read→ref)。读取文件会返回其符号大纲;读取file/symbol只会返回该符号的源代码片段。 - 混合召回 —
recall接受英文查询,在本地生成嵌入向量,运行可识别标识符的 BM25(拆分snake_case、kebab-case、camelCase并进行英文词干提取),剔除低置信度的尾部结果,并通过 RRF ($k=60$) 融合两份列表,再按 $0.9 + 0.1 \times R$ 缩放。已被取代的修订会自动展开为其最新替代项。 - 回写 — Agent 解决非平凡任务后,会提取原子事实,确保每次
add只存储一条事实(英文摘要;正文支持非拉丁字符)。相关事实通过--link/links建立关联,形成知识图谱(通过mem show检查;召回目前尚未遍历图谱链接)。--parent将记忆关联到一个结构化主题;--supersedes会替换过时的记忆,同时保留其沿革关系。
架构深入解析(中文):DESIGN.md。
Agent 工作流
每项编码任务都遵循相同的四步循环:
- 先召回 — 在 grep 之前,先用英文查询
cam_recall/cam recall。如果命中项为latest且不需要更新(needs_update),则复用该结果。 - 确保已索引 — 如果图谱工具返回
not_indexed,则为该项目运行一次cam_index/cam index。 - 遍历图谱 — 未命中记忆时,使用
find或ls定位符号,使用read <file>/<symbol>读取符号正文,并使用ref <symbol> --dir in|out追踪调用方和被调用方。 - 回写 — 使用
cam_add/cam add将新发现的架构事实或修复作为原子事实持久化(每条记忆一项事实,英文摘要;正文支持非拉丁字符),并通过links/--link关联相关事实。
| 角色 | 接口 | 典型用法 |
|---|---|---|
| 主 Agent(聊天 / IDE 会话) | MCP(cam mcp) | 直接调用 cam_recall、cam_find、cam_ls、cam_read、cam_ref、cam_add、cam_mem_tree、cam_mem_show |
| 子 Agent(任务 / 探索 / CLI) | CLI(cam --json) | 在 shell 中运行 cam --json --project <dir> <cmd>(子 Agent 很少能继承 MCP 工具) |
完整的 Agent 规则和可直接复制粘贴的系统提示词:docs/agents.md。
CLI 参考
代码图谱命令
| 命令 | 说明 |
|---|---|
cam index | 使用 tree-sitter 解析项目并写入 .cam/cam.db(如有需要会创建 .cam/) |
cam sync | 使用内容哈希增量更新已修改文件对应的图谱 |
cam watch [--debounce-ms N] | 监视源文件并自动同步(--json 会在每次同步时输出一份 JSON 报告) |
cam ls [virt_path] | 列出目录、文件或文件中的符号 |
cam read <virt_path> [--full] | 读取文件的符号大纲、指定符号正文(path/symbol),或使用 --full 读取整个文件 |
cam find <query> [--kind K] [--file S] [--scope D] [--limit N] | 不区分大小写地对子串进行符号名称搜索(先显示完全匹配项,再显示前缀匹配项) |
cam ref <symbol> --dir in|out [--file S] [--kind K] [--scope D] | 查找一跳调用方(in / --callers)或被调用方(out / --callees)。名称不明确时返回按排名排列的 candidates |
记忆命令
| 命令 | 描述 |
|---|---|
cam recall "<query>" [--limit N] [--no-expand] [--include-superseded] [--snippets] | 混合 RRF 检索(英文查询)。--no-expand 跳过最新修订版扩展;--include-superseded 保留旧修订版;--snippets 将排名低于第 1 位的长正文截短 |
cam add --summary "..." [--parent ID] [--supersedes ID] [--link ID]... [--body TEXT | --file PATH] | 将一条原子事实存储为记忆(摘要必须为英文;正文支持非拉丁字符;可通过 --body、--file 或 stdin 提供)。--link 用于连接知识图谱中的相关事实;--parent 用于主题层级;--supersedes 用于替换较旧的记忆 |
cam mem tree | 显示记忆层级和修订链 |
cam mem show <id> | 完整查看单条记忆条目 |
服务与配置命令
| 命令 | 描述 |
|---|---|
cam mcp | 为主 Agent 启动 stdio MCP 服务(参见 docs/mcp.md) |
cam status | 显示解析后的项目根目录、数据库路径、节点/边/记忆数量和当前配置 |
cam config get | 输出当前的 ~/.cam/config.toml 设置 |
cam config set stale_days <N> | 设置将记忆标记为 stale 的时间阈值(天) |
cam config set embedding_model <model> | 设置 Hugging Face model2vec 仓库、本地模型目录、hash 或 default |
全局标志与约定:
--project <dir>(或CAM_PROJECT环境变量)会覆盖自动向上查找.cam/.git根目录的行为。--json输出紧凑 JSON(--pretty用于输出缩进 JSON)。使用--json时,错误会向stdout输出{"error":{"code":…,"message":…}},并以非零状态码退出。- 符号不明确: 当
read或ref匹配到多个定义时,cam会返回status: "ambiguous"和候选节点 ID(例如src/main.rs:function:main:12),这些 ID 可以直接传回read或ref。 - 忽略规则与多仓库目录: 会遵循任意深度的
.gitignore和.camignore。跳过 git 子模块和链接工作树;将嵌套的独立克隆索引为kind: "project"(可传给--scope)。
记忆规则
- 原子事实与知识图谱链接: 每条记忆只存储一条原子事实,避免在单个条目中塞入过多信息。多个事实相关时,使用
--link/links将它们连接起来,构建知识图谱(目前尚未启用图谱检索)。 - 英文查询与摘要: 检索查询和记忆摘要必须使用英文书写。记忆正文支持非拉丁字符。
- 保留与强化: 艾宾浩斯遗忘曲线 $R = e^{-t / S}$ 通过 $\text{relevance} \times (0.9 + 0.1 \times R)$ 调整检索分数。$R < 0.3$ 的条目会标记为
needs_update;超过stale_days(默认值为30)的条目会标记为stale。每次有效的检索命中(needs_update = false)都会刷新最后访问时间,并将稳定性 $S$ 乘以1.7。 - 非破坏性沿革: 记忆永远不会被删除。
--parent用于构建分支树;--supersedes用于构建线性修订链,其中只有末尾条目标记为latest,较旧的修订版则从默认检索结果中折叠隐藏。
配置
全局设置位于 ~/.cam/config.toml:
stale_days = 30
# embedding_model = "minishlab/potion-multilingual-128M" # default (cached under ~/.cam/models/)
# embedding_model = "minishlab/potion-base-8M" # lighter Hugging Face model2vec repo
# embedding_model = "/path/to/local/model2vec" # dir with tokenizer.json, config.json, model.safetensors
# embedding_model = "hash" # zero-download lexical hash embedder
使用 CAM_EMBED_MODEL 可为单个进程覆盖模型;也可以使用 cam config set embedding_model default 重置。嵌入模型发生变化时,下次执行 recall 会在评分前自动重新嵌入现有记忆。
基准测试
cam 在相同语料上,分别将其代码图和记忆层与最接近的开源系统进行评测:
| 层 | 基线/类似系统 | 基准语料 | 核心结论 |
|---|---|---|---|
| 记忆 | agentmemory 混合检索 + 分词后的 grep | coding-agent-life-v1 | 1.000 R@5 / 0.240 P@5(达到混合检索上限;在修订链上 1.000 newest R@5) |
| 长期记忆 | BM25/稠密检索器 | LongMemEval-S | 使用 potion-multilingual-128M 时,0.909 R@5 / 0.980 Hit@5 / 0.840 MRR |
| 代码图 | codegraph v0.9.6 | LongMemCode(clap) | 在支持的 1 跳任务上为 0.769,对比 0.768;P95 ≈ 5.2 ms,$0 |
| 工作流检索 | 词法/BM25 文件检索 | Agent Retrieval Bench V2 edit2ripple | 0.297 MRR(首次命中排名最佳,P95 7.3 ms) |
| 多轮 Token 数 | 完整上下文转储 | DeepSeek 多轮 | 记忆轨道的 Token 数减少 57%,代码轨道的 Token 数减少 98% |
通用聊天记忆框架(Mem0、Zep、Letta)针对的是对话日志,而非这些编码 Agent 语料,因此未列入下表。
系统对比
| cam | agentmemory | codegraph | |
|---|---|---|---|
| 存储内容 | 代码图 + 记忆树 | 会话/聊天记忆 | 代码图 |
| 查询原语 | recall / ls / find / read / ref | smart-search / remember | explore / 调用方 / 被调用方 |
| 接口 | MCP + CLI | MCP + REST + 钩子 | MCP + CLI |
| 排序/融合 | 向量 + BM25 + RRF + 保留策略 | BM25 + 嵌入 + 重排 | FTS5 + 图遍历 |
| 成本 | 完全本地($0) | 本地服务 | 本地 |
1. 记忆 — coding-agent-life-v1
15 个会话,15 个查询,$k=5$(评分方式与 agentmemory 的 score.ts 相同;P@5 上限为 0.240)。
| 系统 | 命中率 | R@5 | P@5 | 来源 |
|---|---|---|---|---|
grep(分词子串) | 15 / 15 | 0.967 | 0.227 | 本仓库,2026-09-23 |
cam min-max 求和(旧版) | 15 / 15 | 0.933 | 0.213 | 历史数据,哈希嵌入 |
cam RRF | 15 / 15 | 1.000 | 0.240 | 本仓库,哈希嵌入 |
agentmemory 混合检索 | 15 / 15 | 1.000 | 0.240 | 已发布的 v0.9.26 |
修订链(--lineage): 将每一轮重新摄取为 --supersedes 修订,以测试 top-$k$ 是否会返回每条黄金链的最新节点(newest R@k),以及是否有被取代的节点错误地声称自己是 latest(stale latest)。
| k | R@k | P@k | newest R@k | stale latest |
|---|---|---|---|---|
| 5 | 1.000 | 0.240 | 1.000 | 0 |
| 10 | 1.000 | 0.120 | 1.000 | 0 |
2. 长期记忆 — LongMemEval-S
从清理后的 LongMemEval-S 中,使用种子 42 抽取 100 个非弃答问题。检索以 $k=10$ 使用 RRF 融合嵌入和 BM25,且不使用大模型阅读器。
| 嵌入器 | R@1 | R@5 | R@10 | Hit@1 | Hit@5 | Hit@10 | MRR | 检索 P50 / P95 |
|---|---|---|---|---|---|---|---|---|
hash(离线测试) | 0.382 | 0.803 | 0.922 | 0.580 | 0.910 | 0.970 | 0.718 | 24.1 / 35.5 ms |
potion-multilingual-128M | 0.474 | 0.909 | 0.952 | 0.740 | 0.980 | 0.990 | 0.840 | 1.12 / 1.34 s |
3. 工作流检索 — Agent Retrieval Bench V2(edit2ripple)
在 44 个冻结的仓库快照中,包含 58 个锚定变更查询(不使用 LLM;BCY = 在规范的 8K token 文件打包协议下的预算上下文产出)。
| 系统 | Recall@5 | Recall@10 | Recall@20 | MRR | BCY@8k |
|---|---|---|---|---|---|
cam graph | 0.300 | 0.335 | 0.378 | 0.297 | 0.300 |
| 词法检索 | 0.412 | 0.536 | 0.588 | 0.243 | 0.447 |
| BM25 | 0.207 | 0.287 | 0.499 | 0.154 | 0.243 |
cam graph 的首次命中排名最高(MRR 0.297,查询 P95 为 7.3 ms),而词法检索能覆盖更多文件,因此我们采用图检索与词法检索的排名融合。
4. 代码图 — LongMemCode(clap)
clap v4.6.1,针对 SCIP 标注数据进行 536 个场景评测(不使用 LLM,P95 ≈ 5.2 ms,$/1k = 0)。
| 切片 | n | cam | codegraph 0.9.6 |
|---|---|---|---|
| 支持的操作(1 跳) | 478 | 0.769 | 0.768 |
lookup / file_symbols | 293 / 55 | 0.808 / 0.915 | 0.808 / 0.915 |
callers / callees | 67 / 18 | 0.397 / 0.811 | 0.355 / 0.867 |
implementors | 40 | 0.119 | 0.094 |
| 原始 / 加权(全部 536 个) | 536 | 0.709 / 0.704 | 0.704 / 0.700 |
5. 多轮 Token 节省 — DeepSeek
完整上下文转储与逐轮 cam 检索对比(deepseek-flash、哈希嵌入器,2026-10-13):
| 赛道 | n | 完整上下文准确率 | cam 准确率 | 完整上下文 Tokens | cam Tokens | Token 节省 |
|---|---|---|---|---|---|---|
记忆(coding-agent-life) | 15 | 1.00 | 0.87 | 22,796 | 9,904 | 57%(每轮 1,471 → 616) |
| 代码(已索引此仓库) | 6 | 0.83 | 0.33 | 379,066 | 6,342 | 98%(每轮 63,076 → 1,000) |
复现所有基准测试
数据集路径在 eval/datasets.toml 中配置(coding-agent-life-v1 默认使用 ../agentmemory 或 CAM_EVAL_CODING_LIFE)。
python3 eval/coding_life/run.py --adapter grep
python3 eval/coding_life/run.py # potion; errors if the model fails
python3 eval/coding_life/run.py --hash-embed # hash embedder
python3 eval/longmemeval/run.py --sample 100 --seed 42 --workers 8 # potion
python3 eval/longmemeval/run.py --sample 100 --seed 42 --workers 8 --hash-embed
python3 eval/locomo/run.py --workers 4 # potion, evidence recall
git clone --depth 1 https://github.com/eyuansu62/agent-retrieval-bench \
eval/agent_retrieval/vendor/agent-retrieval-bench
python3 -m pip install -e eval/agent_retrieval/vendor/agent-retrieval-bench
arb download-benchmark --version v2_edit2ripple --local-dir eval/agent_retrieval/data --force
python3 eval/agent_retrieval/run.py --workers 8
python3 eval/llm_multiturn/run.py --track both # potion; requires DEEPSEEK_API_KEY
python3 eval/longmemcode/run.py --corpus clap
python3 eval/charts/generate.py
支持的 Agent
为主 Agent注册 cam mcp(stdio);子 Agent可直接使用 cam --json CLI,无需额外设置。
| 宿主 | MCP 配置 | 子 Agent / 备注 |
|---|---|---|
| Cursor | .cursor/mcp.json、~/.cursor/mcp.json 或 .cursor-plugin/plugin.json | Task / explore 子 Agent 使用 CLI |
| Claude Code | .mcp.json、~/.claude.json 或 claude mcp add cam -- cam mcp | 工具受限的子 Agent 使用 CLI |
| Codex | ~/.codex/config.toml → [mcp_servers.cam] | codex exec 使用 CLI |
| Windsurf | ~/.codeium/windsurf/mcp_config.json | Cascade 使用 MCP |
| GitHub Copilot | .vscode/mcp.json 或 ~/.copilot/mcp-config.json | 聊天使用 MCP;CLI 脚本使用 CLI |
| Continue / Cline | ~/.continue/config.yaml / ~/.cline/mcp.json | |
| JetBrains | AI Assistant → MCP(cam / mcp) | 如果 IDE 的 PATH 为空,请使用 cam 的绝对路径 |
| Gemini CLI / Antigravity / OpenCode / Zed / Droid | 参见 docs/mcp.md |
可直接复制粘贴的配置:docs/mcp.md · 系统提示词:docs/agents.md。
支持的语言
| 语言 | 扩展名 | 索引的节点和边 |
|---|---|---|
| Rust | .rs | 函数、结构体、枚举、特征、调用 |
| Python | .py | 函数、类、调用 |
| TypeScript | .ts, .tsx | 函数、方法、类、调用 |
| JavaScript | .js, .jsx | 函数、方法、类、调用 |
| Go | .go | 函数、方法、结构体、调用 |
| Java | .java | 函数、方法、类、接口、调用 |
| C | .c | 函数、结构体、调用 |
| C++ | .cc, .cpp, .cxx, .h, .hpp | 函数、方法、类、结构体、调用 |
| C# | .cs | 函数、方法、类、接口、调用 |
支持的平台
cam 可通过 cargo install --git https://github.com/HanochZhu/codeagent_memory --locked 在 macOS、Linux 和 Windows 上原生编译,也可通过 Docker (ghcr.io/hanochzhu/codeagent-memory:0.1.5) 在任何环境中运行。请参阅开始使用。
许可证
MIT
评论
一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。