English | 简体中文
面向工程团队的编码智能体复用闸门:每个新建文件和符号,都必须先给出可核验的复用理由。
你的 Coding Agent 每天都在往仓库里塞没人要求的新文件。ReuseGate 把「懒即美德」类 Skill 从一句提示词升级成机器可核验的闸门:Agent 在新建任何文件、符号或服务之前,必须先对照现有 能力清单给出理由,而每一条理由都会留下可审计的记录。
让 Agent「少写代码」的提示词和 Skill 已经很流行,但提示词只能施加压力,无法核验:Agent 答应了「先找现有的」,没有任何机制检查它是否真的找了。事后扫描器(查重、AI slop 检测) 能在合并后发现重复,但那时冗余代码已经落盘,反馈回路永远慢一步。
ReuseGate 把检查放进写入发生之前的那个瞬间:
- 计划时拦截 — Claude Code 的 PreToolUse 钩子在 Write / Edit 落盘前调用闸门;
- 机器可核验 — Agent 必须用一行
# reusegate: 路径:符号引用清单里的现有能力, 闸门核验该引用真实存在、且排名在最近候选的前 k 名之内,否则记为unjustified; - 只警告、不阻断 — 闸门永远返回 allow(v0.1 不阻断任何写入),需求文本随决策 一起回给 Agent,由 Agent 自己决定改为扩展现有模块;
- 全程留痕 — 每次尝试(无论通过与否)都追加进
.reusegate/justifications.jsonl, 变成评审时读得懂的记录。
匹配完全确定性:归一化名称等价、rapidfuzz 相似度、token 指纹重叠。闸门内部没有 大模型、没有向量检索、没有网络请求——可解释、可复现、可调阈值。
前提:Python 3.12+,一台装了 uv 的机器(pipx 同样可用)。
1. 安装 CLI
git clone https://github.com/SuperMarioYL/reusegate
cd reusegate
uv tool install . # 之后 reusegate 在 PATH 上;pipx install . 亦可2. 在你的仓库里建能力清单
$ cd your-repo
$ reusegate scan
reusegate: 49 files, 832 symbols (py 49) -> .reusegate/inventory.json10k 行的示例仓库实测 0.2 秒完成扫描(tree-sitter 解析,Python / TypeScript / Go)。
想先看看效果,可以用 python3 docs/make_demo_repo.py /tmp/demo-repo 生成一个 10k 行
的样例仓库。
3. 把钩子接进 Claude Code
$ reusegate install claude-code
reusegate: PreToolUse hook wired in .claude/settings.json这一步往仓库的 .claude/settings.json 写入 PreToolUse 钩子(matcher
Edit|Write|MultiEdit|NotebookEdit),已有配置原样保留,可重复执行。
4. 让 Agent 正常干活
给 Agent 一个普通任务,比如「加一个日期格式化辅助函数」。当它伸手去写一个全新的
utils/format_date_v2.py 时,钩子在 Agent 循环内打断,给出机器核验过的要求(下面是
真实输出):
permissionDecision: allow
reusegate: before creating the new file `utils/format_date_v2.py`, cite the nearest
existing capability and justify create-vs-extend.
Nearest capabilities already in this inventory:
1. src/time_utils.py:format_date def format_date(raw: str, *, limit: int = 10) -> str (score 65.0)
...
If you are extending an existing capability, add a citation header to the file instead
of creating a duplicate:
# reusegate: src/time_utils.py:format_date
Agent 引用现有能力后再次尝试,闸门核验通过:
reusegate: justification accepted — `src/time_utils.py:format_date` ranks #1 within the
top-5 nearest (score 64.98).
于是它改为扩展现有的 src/time_utils.py,而不是新建重复文件。
5. 看报告
$ reusegate report # 最近一次会话的尝试计数与全部理由记录
$ reusegate report --inventory # 每个目录的能力计数不装 Claude Code 也能直接体验钩子——事件 JSON 走 stdin,决策 JSON 走 stdout:
printf '%s' '{"tool_name":"Write","tool_input":{"file_path":"utils/format_date_v2.py","content":"def format_date(raw):\n return raw.split(\"T\")[0]\n"}}' \
| reusegate hook claude-code同一份 10k 行样例仓库、同一个「加日期格式化」任务跑两遍。闸门关:Agent 自由发挥,留下
3 个新文件、2 个新符号、0 条记录。闸门开:0 个新文件,改为扩展现有符号,留下 2 条读得懂
的理由记录。完整录制见 assets/demo.cast(asciinema 格式,约 22 秒):
asciinema play assets/demo.cast # 或直接阅读下面这段真实输出reusegate report --delta baseline.json after_off.json after_on.json 的真实输出:
┏━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━┳━━━━━━━━━┓
┃ metric ┃ gate OFF ┃ gate ON ┃
┡━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━╇━━━━━━━━━┩
│ new files │ 3 │ 0 │
│ new symbols │ 2 │ 0 │
│ extended symbols │ 0 │ 1 │
│ justified records │ 0 │ 1 │
│ unjustified records │ 0 │ 1 │
└─────────────────────┴──────────┴─────────┘
gate OFF — new files
+ utils/compat_shim.py
+ utils/date_extra.py
+ utils/format_date_v2.py
gate OFF — new symbols
+ utils/date_extra.py:days_between
+ utils/format_date_v2.py:format_date
gate ON — extended symbols
~ src/time_utils.py:format_date
想复现:python3 docs/make_demo_repo.py <目录> 生成样例仓库,assets/demo.tape
是这次录制的逐条命令脚本(重新录制:
asciinema rec --overwrite --output-format asciicast-v2 --window-size 110x34 -c "bash assets/demo.tape" assets/demo.cast)。
一次写入能否通过,由四条确定性规则决定,没有自由发挥的空间:
- 没有引用 →
unjustified(内容里找不到reusegate:引用行); - 引用不存在 →
unjustified(清单里没有那个路径或符号); - 引用存在但排名在 top-k 之外 →
unjustified(所引能力与要写的东西并不相近); - 引用存在且排名在前 k(默认 k=5)→
justified。
匹配信号只有三个,全部确定性:归一化 token 等价(format_date_v2 与 format_date
的 token 集合相同,因为 v2 这类重复标记会被剥掉)、rapidfuzz 名称相似度、
名称 + 签名的 token 指纹 Jaccard 重叠。v0.1 的目标恰恰是先量化误报率:台账里每一条
unjustified 都可以人工复核,为后续阈值调优提供依据。
边界与已知限制:
- 仅警告:v0.1 永不阻断写入;闸门返回
allow,需求文本放在permissionDecisionReason里随决策回传; - 语言:Python、TypeScript(含 TSX)、Go 的顶层函数 / 类 / 方法;
- 清单是本地的:
.reusegate/只在你的仓库里,闸门运行时无任何网络请求; - 清单会过期:代码大改后重新
reusegate scan即可(亚秒级)。
| 环节 | 提示词 / Skill | 事后扫描器 | 计划时闸门(ReuseGate) |
|---|---|---|---|
| 介入时机 | 任务开始前 | 写入 / 合并之后 | 写入发生前的那个瞬间 |
| 核验方式 | 无(靠 Agent 自觉) | 检测已落盘的重复 | 对照清单核验引用 |
| 输出 | 改变了对话语气 | 问题清单 | 可审计的理由台账 |
| 能否扭转 Agent 行为 | 间接 | 不能(代码已存在) | 能(Agent 仍在循环里) |
这不是「又一个查重工具」:查重回答「哪里重复了」,ReuseGate 回答「这次新建有没有理由」。
- v0.1 —
scan能力清单(py / ts / tsx / go)、install claude-code、 PreToolUse 钩子、report会话 / 目录 / OFF-vs-ON 报告、51 个测试、CI - v0.2 — 用真实台账调优阈值;误报率达标后引入可选的硬阻断模式
- 更多入口 — Cursor / Gemini CLI 适配器、git hook、CI 模式
- 团队版 — 多仓库台账聚合、组织级复用看板、CI 策略(见下)
ReuseGate 采用 自托管开源核心 + 团队版授权 的形态:
- 开源核心(本仓库,MIT):单仓库的清单、闸门与台账,功能完整,数据不出你的内网—— 闸门运行时本身无任何网络依赖。
- 团队版(试点中):面向 5–50 人工程团队的多仓库台账聚合、组织级复用看板、 CI 级策略(例如「未给出理由的新文件使 CI 失败」)。按座订阅,¥1,500/座/年 (前十个试点团队享创始人折扣,签授权文件即可,无授权服务器)。
想加入试点:在 Issues 里开一个标题
带 [team-pilot] 的帖子,附上你们当前的 Agent 栈描述即可。
git clone https://github.com/SuperMarioYL/reusegate && cd reusegate
uv venv && uv pip install -e .[dev]
.venv/bin/pytest -q # 测试
.venv/bin/ruff check src tests # lint发布流程:更新 VERSION 与 CHANGELOG.md,打 vX.Y.Z 标签推送,Release 工作流会把
wheel + sdist 构建进 dist/ 并附 sha256 校验和。
MIT © 2026 SuperMarioYL
MIT © 2026 SuperMarioYL