OpenQodex:push 前用 22 个扫描器加独立 Claude Code / Codex 进程复审改动
项目地址 https://github.com/openqodex/openqodex ,官网 https://qodex.ai/openqodex ,npm 包 openqodex,Apache-2.0。
它的立场一句话:写代码的 agent 不审自己的代码。OpenQodex 在你本机跑,从 coding agent 或终端发起。
「change」指什么
未 push 的 commit,加上所有未提交改动。就这两部分,没有别的口径。
两阶段:扫描器 → reviewer
第一阶段,无模型扫描器。 扫描器是不带模型的检查程序,比如 gitleaks、semgrep;finding 是某处的一个问题带严重级。OpenQodex 按你改动的文件匹配扫描器,finding 只保留在改动行上;test fixture 里的 finding、你关掉的规则产生的 finding 直接丢弃。仓库里每个受支持的 lockfile,在每次 review 和每次扫描改动时都查 osv.dev。改动行之外的 advisory 会展示,但不计数,也不进 reviewer 的 brief;每条 advisory 会注明修复版本,或者说明尚无修复版本发布。
第二阶段,reviewer。 起独立的 Claude Code 或 Codex 进程,用你自己的登录。finder 会话逐段读改动,连同调用它的代码,提出候选并附引用行作为证据;脚本核对每条引用在代码里是否真实存在。verifier 会话对每条候选和每条扫描器 finding 做判断,必须给出确认或否定的理由。脚本再检查两件事:每条扫描器 finding 都被回答过,每一行改动都给过 reviewer。风格和命名类意见只作为 observation 展示,不拦。最后你自己挑哪些让 agent 修。
没跑完会说出来
一次 review 只有每个阶段都跑过才算完整。否则打印 Review incomplete 并说明缺什么,exit 2。产物是 report.html、report.md、report.json、report.sarif;结束时打印 receipt:verdict、每条 finding 一行、report.html 路径。skill 会让 agent 把 receipt 给你看,问 “Fix all, or tell me which?”,只修你点名的。
什么环境能跑
| Coding agent | 发起 review | 能当 reviewer | push gate |
|---|---|---|---|
| Claude Code | yes | yes | yes |
| Codex CLI | yes | yes | yes(先在 Codex 里信任该 hook) |
| Cursor | yes | no | no,用一条 rule 让 Cursor 去 review |
| Cline | yes | no | no,同上 |
Cursor / Cline 需要另装 Claude Code 或 Codex 作 reviewer。push gate 是个 hook,在 agent 执行 git push 之前找 review。
安装与常用命令
npx openqodex init
init 会找到机器上的 Claude Code、Cursor、Codex CLI、Cline,列出要写的文件,问一次,开始下载仓库需要的扫描器,然后在能起 reviewer 时直接 review 当前改动。
装完对 agent 说 “review my change with openqodex”,或自己在终端:
~/.openqodex/bin/openqodex review
~/.openqodex/bin/openqodex 是 init 写的 launcher;npx 安装不会把 openqodex 放进 PATH。
agent 场景下免交互:
npx -y openqodex@0.14.0 init --yes --agent
# host: claude-code / codex / cursor / cline
Codex 默认沙箱模式不给命令网络,所以这行要在自己的终端里跑。只装 skill 用 npx skills add openqodex/openqodex -g,不带 push gate、不下载扫描器,之后 init 会用自己那份 skill 覆盖掉。
其他入口:
openqodex review --all # 全仓库,排除 review.paths.exclude
openqodex review # 某个分支
openqodex review '#42' # 某个 PR
npx openqodex demo # 造一个带植入 bug 的小仓库再扫它
push gate 的能力边界
agent 内的 gate 只看当前工作有没有一次通过的 review,它不知道这次 push 到底会发什么。普通 git push 它就问当前工作;其他 push 命令它会明说无法判断。init 装的 git pre-push hook 才按真正要发的 commit 检查,但只对会执行 git hook 的 push 生效,git push --no-verify 直接跳过。
两者默认都只警告。只有 .openqodex/config.yaml 里配了 review.block_on_severity 才拦——严重级从 critical、major、minor、nitpick 到 info,达到或超过设定级别的 finding 拦下 push。
加一个 GitHub 上的自定义扫描器
先在 .openqodex/config.yaml 写清楚:
scanners:
custom:
- source: https://github.com/Bearer/bearer
run: bearer scan {target} --format sarif --output {report} --quiet --disable-version-check
target: repo
然后 npx openqodex trust:把 release asset 下载到隔离目录,显示将要执行的命令,问你 yes / no。批准后 npx openqodex scan --only custom:bearer 可以单跑验证,下次 review 就会带上它。兼容的扫描器要能输出 SARIF,或用 map block 转成 finding 的单个 JSON;安装来源限 release asset、精确的 npm / PyPI 版本或 PATH。只有该机器的 ~/.openqodex/trust.json 里存了对这一条的确切批准它才会跑——全新的 GitHub-hosted runner 没有这个文件,所以 GitHub Action 里会跳过。
22 个内置扫描器
大多数扫描器只在改动里出现它能读的文件时才跑;osv-scanner 例外,每次 review 和每次扫描改动都查全仓库所有受支持 lockfile。部分扫描器还会读改动文件周围的项目或目录。需要下载的扫描器首次使用时下载,每个都钉死一个版本。分类:代码里的密钥 1、代码安全问题 3、已知漏洞依赖 2、lint 5、GitHub Actions workflow 2、Dockerfile / Terraform / Kubernetes / CloudFormation 6、SQL 与数据库迁移 3。
Benchmark:真实 PR 那行不太能看
自建 planted-bug 集(dev split):
| Reviewer | 模型 | Issue recall | 每次成本 |
|---|---|---|---|
| Claude Code (claude-graph-on) | claude-opus-5-5 | 129/153 (84.3%) | $0.0870 |
| Codex (codex-graph-on) | gpt-6.1-sol | 115/153 (75.2%) | 未测 |
| 纯扫描器 | 无 | 32/51 (62.7%) | 未测 |
AACR-Bench 是真实 PR 集合,下面由它自己的 evaluator 给出(gpt-6.1-sol,dev-laptop 子集):semantic precision 22.8%、semantic recall 5.2%、F1 8.5%、noise rate 77.2%、line precision 49.4%、line recall 11.3%,每次 review $0.0839。
差别就摆在这:植入 bug 的召回好看,真实 PR 上 semantic recall 只有 5.2%、noise rate 77.2%。这组数字不足以让它当唯一门禁,更适合当第二道审查——挡掉明显问题,把可疑点整理成一份可读的 receipt,最终判断留在人这边。
限制
- Node 22+,需要 git;只在 macOS / Linux 测过,CI 在 Node 22 的 macOS 和 Ubuntu 上跑 gate,Windows 和 WSL 完全没有测试。
- reviewer 只有 Claude Code 或 Codex。Cursor 当不了(cursor-agent 2025.09.18 没有只读模式可以限制它);没有 reviewer 时 review 打印
Full review unavailable并 exit 2,扫描器结果原样存进unchecked-candidates.json。 - Codex 沙箱里起不了第二个 Codex 进程,所以那里不能当 reviewer。
- 用自己的 API key 跑 review 不支持,GitHub Action 除外。
- 没有 Homebrew formula、没有 install 脚本、没有 Docker 镜像,只能走 npm。
- 没有漏洞库的离线副本;osv-scanner 每次 review 都过 osv.dev,cargo-deny 要下 RustSec 库。
--offline只跳过 semgrep、osv-scanner、kubeconform、cargo-deny 这些联网扫描器并停掉下载,reviewer 仍会把改动发给模型服务;已批准的自定义扫描器照样跑它自己的命令。 - 没有哪次 review 能找全问题,报告里会写明哪个阶段没跑。
- 部分扫描器要语言运行时,OpenQodex 不装:brakeman / rubocop 要 Ruby,golangci-lint 要 Go,cargo-deny 要 Cargo。
其他
GitHub Action 在 workflow 给了 Anthropic API key 时对 PR 跑完整 review,没 key 只跑扫描器;pre-commit hook 也只跑扫描器。openqodex graph 回答「谁调用了这个函数」这类问题,init 通过 MCP server 把它交给你的 agent。
OpenQodex 自身不发遥测,semgrep 以关闭 metrics 的方式启动。内置扫描器在 OpenQodex 的调用方式下不发送代码;reviewer 会把你的改动发给 Claude Code / Codex 登录对应的模型服务。
项目在往 1.0 走,命令、flag 和配置文件在 minor 版本之间可能变。Apache 2.0,由 Qodex 维护,Qodex 另有一个托管 PR review 服务。