关于 knock
knock 为代码仓库建立索引,向编码 Agent 提供简明代码图、精确行号,以及源文件变更后可标记为过期的记录。它适合需要调查陌生代码、追溯决策或在会话间保留发现的开发者。
主要功能
- 01按行号映射相关代码
- 02打开符号并查看调用关系
- 03保存供后续会话使用的发现
- 04源文件变更时标记记录过期
- 05增量索引已更改文件
适用场景
- 01修改前了解大型代码库
- 02追溯实现方案的决策依据
- 03复用先前调试会话的发现
- 04无需通读文件即可定位相关函数
MCP 相关
knock 以 MCP 服务形式运行,向编码 Agent 提供代码映射、源码读取和记忆工具。精简的 `map` 工具集包含 `map`、`open` 和 `remember`。
配置
本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。
工具
本地服务需要在你的电脑上运行后才能读取工具,维护者暂未提供工具列表。
详细介绍
🚪 knock
让你的 AI 编码 Agent 记住你的代码库。
别再每次会话都花钱让 Agent 重新读取相同的文件。先敲一下,再只读重要内容。
在 Saleor 上进行的两次真实 Claude Code 会话(内容经过删节):两侧均展示三次运行中成本的中位数。不同运行和代码库的结果会有所差异;在一个小型且熟悉的代码库中,差异处于噪声范围内。完整数据:docs/benchmark.md。
📝 数据背后的故事:我记录了 87 次 Claude Code 会话,想弄清钱都花在哪里了
🤔 一张表说清问题
每次与编码 Agent 开启新对话,它都会失忆。要回答 “X 在哪里?” 或 “我们如何部署?”,它会用 grep 搜索、打开大文件并阅读……而下一次会话又会从头再来。
| 😩 不使用 knock | 😎 使用 knock | |
|---|---|---|
| 第一步 | 用 grep 搜索、打开整个文件,或启动子 Agent 进行探索 | 调用一次 map:以骨架形式展示相关代码,并提供精确的行范围 |
| Agent 读取的文本 | 每个问题约 27,000–118,000 个字符 | 每个问题约 4,300 个字符 |
| 找到“为什么要这样做?” | 只有打开正确的文档才找得到 | 回答会附带决策及其原因 |
| 记住昨天的 Bug 排查 | ❌ | ✅ Agent 使用 remember 保存发现 |
| 知道笔记何时过时 | — | ✅ 每个回答都会标明 fresh 或 stale |
在留出基准测试中,每项任务的字符数中位数(针对性 grep 和 grep 并阅读的基线与 knock 对比)。字符数更少 ≠ 账单等比例减少;请参阅 FAQ。
⚡ 快速开始
只需设置一次 knock,之后照常使用你的 AI Agent 即可。 Agent 会在后台与 knock 通信;你无需在日常使用中运行 knock 命令。
1️⃣ 将其连接到 Claude Code(每个项目只需一次)
在你要处理的项目中运行:
claude mcp add knock -- uvx knock-mcp serve --repo . --toolset map
这里使用 uv,它会为你下载并运行 knock。没有 uv?运行 pipx install knock-mcp(或 pip install knock-mcp),然后运行 claude mcp add knock -- knock serve --repo . --toolset map。
--toolset map 会为 Agent 提供三个工具(map、open、remember),下方结果中的测试也使用了这种配置。省略此参数即可使用原来的八个工具。
就这么简单。下次你在该项目中打开 Claude Code 时,knock 会读取项目并自动生成笔记。小型项目只需几秒,约 5,000 个文件的项目需要一两分钟;之后,它只会重新读取发生更改的文件。
提示
将此行添加到项目的
CLAUDE.md,让 Agent 在适合时使用 knock: "在探索仓库之前(解答如何/为什么的问题、排查不明确的 bug、处理跨模块更改、查找无法通过一次搜索找到的代码),请根据你的任务调用 knock 的map工具。对于一次 grep 就能定位的小改动,可以跳过。使用remember保存不明显的发现。"在我们的录制中,knock 在大型代码库的调查中节省了成本,但会给快速编辑增加少量成本,因此这一行很重要。
2️⃣ 照常工作
向 Agent 提出你平时会问的问题。以下是幕后发生的变化:
| 你输入的内容 | Agent 的操作 |
|---|---|
| "为登录端点添加速率限制" | 先询问 knock,获取登录处理程序的 file:line、中间件约定和测试配置,然后只打开相关代码行 |
| "为什么我们使用 Postgres 而不是 Mongo?" | 从文档或 ADR 中获取决策及其原因,并附上来源链接 |
| "测试因 Redis 错误而失败,有什么头绪吗?" | 找到之前会话保存的发现:"登录测试需要运行 Redis" |
| (弄清楚某件事之后) | 使用 remember 保存,这样明天的会话就已经知道了 |
无需维护:代码更改时,knock 会更新笔记,并标记可能已过时的内容。
🖥️ 可选:在终端中自行使用 knock
你不一定需要使用这些命令,但它们很实用。
| 命令 | 使用场景 |
|---|---|
knock map "where are expired checkouts cleaned up?" | 查看 Agent 获取的同一份代码地图 |
knock open SomeClass.method | 查看某个符号的精确代码,以及它的调用方和被调用方 |
knock context "how do we deploy?" | 自行提问,例如熟悉不熟悉的仓库时 |
knock search "rate limit" | 查找 knock 对某个主题的了解 |
knock status | 检查笔记的新旧程度以及 knock 了解多少 |
knock index . | 立即更新笔记;通常由 Agent 为你完成 |
knock index . --full | 大规模重构后从头重建所有内容 |
knock forget . --yes | 删除 knock 为此项目保存的所有内容 |
想让 knock 忽略某些文件?将它们列在 .knockignore 文件中(格式与 .gitignore 相同)。
👥 为整个团队设置
将 .mcp.json 文件提交到仓库,每位队友的 Claude Code 都会自动加载 knock(每个人都需要安装 knock):
{
"mcpServers": {
"knock": { "command": "knock", "args": ["serve", "--repo", ".", "--toolset", "map"] }
}
}
每个人的笔记都保存在各自的设备上。目前还不支持在团队成员之间共享发现(参见下方的 Status)。
flowchart LR
A["📁 Your repo<br/>code · docs · configs · git log"] -->|"knock index<br/>(only changed files)"| B["🗂️ Notes<br/>each one points to<br/>file + lines + hash"]
B --> C[("💾 SQLite<br/>on your machine")]
C -->|"map"| D["🤖 Your agent"]
D -->|"open / Read<br/>(verify the real lines)"| A
D -->|"remember<br/>(save what it learned)"| C
- **索引:**knock 会读取你的代码库,但不会在其中运行任何内容。它会写下简短的笔记:每个模块定义了什么、文档中如何说明设置和部署、你使用了哪些工具和依赖项、做出决策的原因,以及哪些近期提交修复了错误。
- **提问:**你的 Agent 提出问题,并获得简短的排序结果,其中包含
file:line指针,而不必读取整个文件。 - **验证:**编辑前,Agent 只读取所需的代码行。原始文件始终是唯一可信来源。
- 记忆:Agent 会保存学到的内容。如果这些文件之后发生变化,knock 会将笔记标记为过时,以免有人误信过期信息。
🧰 Agent 能获取的内容
使用 --toolset map(推荐):
| 工具 | 功能 | |
|---|---|---|
map | 🗺️ | **需要探索时使用。**以骨架形式提供与任务相关的代码:函数签名、准确的行范围、每个函数使用和捕获的内容、调用者;以及背后的历史和相关文档。对于变更请求,则提供更精简的版本,指出需要阅读的准确范围和可复用的现有代码。 |
open | 📄 | 显示函数或类的准确代码行(带行号)及其调用者和被调用者、指定的行范围,或文件的骨架 |
remember | ✍️ | 为后续会话保存发现;引用的文件发生变化时会自动标记 |
原始的 8 工具集(不使用 --toolset map 时的默认配置)
| 工具 | 功能 | |
|---|---|---|
get_context | 🔎 | **需要探索时从这里开始。**提供与任务相关的排序结果包:笔记、带 file:line 的函数、值得打开的文件、相关提交,以及坦诚列出的“关于 X 没有已知信息”空缺 |
search_knowledge | 📚 | 搜索笔记,可按类别(架构、决策、工作流……)或文件夹筛选 |
get_knowledge | 🧾 | 查看一条笔记及其完整溯源信息:来源、时间,以及当前是否仍有效 |
get_source | 📄 | 读取文件中的实际代码行,并对机密信息进行隐藏。仅限 knock 已索引的文件 |
record_knowledge | ✍️ | 保存发现;自动合并重复内容,并标记矛盾 |
update_knowledge_status | ✅ | 将笔记标记为已验证或错误 |
get_repository_status | 🩺 | 查看索引的新鲜度,以及数量和统计信息 |
refresh_repository | 🔄 | 重新索引已更改的文件(只需几毫秒,不会调用 AI) |
👀 查看真实会话示例(8 工具集,Flask)
在 Flask 项目中,Agent 收到的指令是:“轮换 SECRET_KEY 后,使用旧密钥签名的 SECRET_KEY_FALLBACKS 中的会话会被拒绝”。
get_context返回约 7.7 KB 内容,包括:src/flask/sessions.py:317:SecureCookieSessionInterface.get_signing_serializertests/test_basic.py:374:test_session_secret_key_fallbacks- 相关提交
fb54159861 secret key rotation: fix key list ordering和e13373f838 enable secret key rotation - 关于会话和密钥的文档章节
get_source("src/flask/sessions.py", symbol="get_signing_serializer")返回约 80 行相关代码,而不是整个文件。record_knowledge保存发现:
下一次会话可立即获取这条信息。如果{"category": "debugging", "content": "get_signing_serializer builds the key list as SECRET_KEY_FALLBACKS followed by SECRET_KEY; ordering was fixed in fb54159.", "sources": [{"path": "src/flask/sessions.py", "start_line": 317, "end_line": 335}]}sessions.py发生变化,这条笔记就会被标记为过时。
通过可复现的基准测试进行测量:每个仓库包含 12 项工程任务,涵盖架构、查找功能、部署、Bug 调查、设计原理和遵循约定。
留出仓库(full-stack-fastapi-template;knock 从未针对它进行调优):
| 方法 | 找到所需事实 | 阅读字符数 | 工具调用次数 |
|---|---|---|---|
| 🐢 grep + 读取 3 个文件 | 9 / 12 | 1,215,570 | 72 |
| 🐇 定向 grep + 读取片段 | 7 / 12 | 328,206 | 60 |
| 🚪 knock | 10 / 12 | 88,962 | 17 |
更多数据,以及细节说明
- Flask(开发期间使用过,因此结果偏乐观):knock 为 12/12,耗费 92K 个字符;基准方法为 7/12,分别耗费 2.1M 和 247K 个字符。
- **速度:**约 200 个文件的仓库可在 0.3–0.6 秒内完成索引;没有变更时,重新索引耗时约 30 毫秒。
- **测量内容:**事实是否传达给了 Agent,而不是 Agent 随后是否解决了任务。基准方法是对 Agent 行为的模拟。
- 在真实的 Claude Code 会话中(每种情况运行 3 次),结果取决于仓库和任务:
- Flask(规模小且广为人知):在 Bug 调查中,knock 的成本与基准方法持平;在简单编辑中,成本略高,因为额外步骤的开销超过了单次搜索。
- Saleor(4,776 个文件,在测试前几天刚发布),使用精简的
map工具集:在一项涉及多个模块的调查中,knock 将成本中位数从 $0.49 降至 $0.29,将模型耗时从 170 秒降至 78 秒,而且每次 knock 运行的成本都更低。在后续编辑中,单次正则表达式搜索就能找到目标文件,knock 的成本更高($0.14 vs $0.08)。 - 最新版本(增加了编辑模式和“简单编辑时跳过 knock”的指导),在完整的“调查后编辑”场景中:Saleor 两天的成本中位数从 $0.70 降至 $0.43(−39%)。Flask 的成本为 $0.31 vs $0.27,处于每次运行的波动范围内。Claude 遵循了指导:所有调查都使用 knock,所有 Flask 编辑都跳过了它。
- 波动性检查(Saleor 调查每侧运行 8 次):成本中位数 $0.42 → $0.25(−40%),两侧均为 8/8 次回答正确,结果波动幅度约减半。不使用 knock 时,Claude 在 8 次运行中有 5 次委派给子 Agent;使用 knock 时,一次也没有。
- 完整情况,包括效果变差的版本:我记录了 87 次 Claude Code 会话……。
- 详情和注意事项见 docs/benchmark.md。
- **尚未测量:**使用在线模型时实际计费的 Token 数量。测试框架已就绪(
benchmarks/agent_bench.py),但运行需要消耗 API 额度。 - **knock 未能找到的内容:**措辞不匹配(“linters” vs “lint”),以及它目前尚未索引的模块级变量。
完整方法:docs/benchmark.md。
🔒 你的代码仍由你掌控
- 💻 所有内容均在本地:
~/.knock中的一个 SQLite 文件。无云端、无遥测、无网络调用(有测试确保这一点)。 - 🙈 跳过机密信息:
.env文件、密钥和凭据绝不会被索引,代码中的 Token 或密码也会被脱敏。 - 🧱 **不会执行任何内容:**knock 从不运行你的脚本、钩子或测试。它只读取内容。
- 🚧 **读取范围受沙箱限制:**Agent 只能获取 knock 已索引的文件,无法访问
../../anything。
重要
Agent 通过 knock 检索的任何内容都会进入 Agent 的上下文,就像它亲自读取了文件一样。请使用
.knockignore文件排除敏感内容。详情:docs/security.md。
❓ 常见问题
这样能节省 Token 吗?
这是我们的目标,基准测试也显示,传递给 Agent 的文本大幅减少。但你的账单还包括系统提示词、推理和输出,而且提示词缓存已经能为重复输入打折。预期最大的收益来自探索型问题(“X 是如何工作的?”、“Y 在哪里?”、“我们该如何部署?”),而单纯编写代码的收益不大。无论如何,回答更快、能在多个会话间保留记忆都是优势。
我需要 API 密钥或付费模型吗?
不需要。索引和搜索完全基于确定性逻辑,并在本地运行。唯一会使用 API 的是可选的基准测试。
它支持哪些 Agent?
任何支持通过 stdio 使用 MCP 的 Agent。已验证:Claude Code(本页顶部的会话是 Claude 使用 knock 工具的真实录制)和官方 MCP Python SDK 客户端(测试套件中覆盖全部 8 个工具)。Cursor、Windsurf 等应该也能使用,但尚未测试。配置方法:docs/agents.md。
它能理解哪些语言和文件?
Python(通过语法树深入解析),以及 JavaScript/TypeScript、Go、Rust、Java、Kotlin、C#、Ruby、PHP、Swift、C/C++ 等。它还会读取 Markdown 和 reStructuredText 文档、ADR、package.json、pyproject.toml、go.mod、Cargo.toml、Dockerfile、Makefile、GitHub Actions、linter 配置和 git 历史。完整列表:docs/architecture.md。
如果文档有误或已经过时怎么办?
每条笔记都会标明来源(extracted from docs、recorded by an agent、git history)和新鲜度。Agent 可以将笔记标记为错误,在来源发生变化前,该笔记会保持隐藏。只需调用一次 get_source 就能查看真实文件。
这和“在我的代码仓库上做 RAG”有什么区别?
它不使用嵌入,也不使用向量数据库。knock 会存储可追溯到确切代码行的小型结构化事实,跟踪这些代码行的变化,并允许 Agent 添加它们学到的信息。它更像一个能自我维护的团队 Wiki,而不是搜索索引。
🗺️ 状态
knock 目前处于早期 MVP 阶段(v0.1)。当前已实现的功能和后续计划:
- 增量式、可恢复的索引,遵循
.gitignore并跳过机密信息 - 带有来源、新鲜度和生命周期信息的结构化知识
- 提供 8 个工具、缓存和本地指标的 MCP 服务
- 使用保留测试代码仓库的可复现基准测试
- 模型参与的 Token 和成本基准测试(测试框架已就绪)
- 精简的 3 工具“代码地图”(
--toolset map),已在 Flask 和 Saleor 的真实 Claude Code 会话中测量 - 在更多大型代码仓库和私有代码库上进行测量
- 改进同义词匹配,并索引模块级变量
- 可选的 AI 辅助提取(需主动启用,并明确披露)
- 在团队间共享知识
🤝 贡献
欢迎提交 Issue 和 PR。请从 CONTRIBUTING.md 开始。
.venv/bin/pip install -e '.[dev]' && .venv/bin/pytest
更多文档:架构 · 安全性 · Agent · 基准测试 · 故障排除
📜 许可证
评论
一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。