跳到主要内容

Cursor 挂掉的六个小时,我搭了个本地兜底 Review Agent

Kevin
Kevin

· 阅读约 5 分钟

昨天下午 14:34 UTC,Cursor 的状态页标红:Automations、Cloud Agents、Review Agents、Codebase 一起降级。一直到 20:40 官方才说恢复。中间这六个多小时,我把 review 这件事搬回了本地,跑完全部 PR。这篇就把这个兜底方案完整交代出来,二十分钟能跑通,不依赖 Cursor 云,不依赖 GitHub Actions,只依赖你自己那台机器。

开搞之前先确认这几件事都齐了:

  • 仓库已经 clone 到本地,git status 能正常跑
  • 本机装了 Claude Code CLI,claude -p "say hi" 能正常返回,不用登录也行
  • 有一条你确定能当对比起点的 commit,比如 origin/main

三样齐了往下走,缺哪样先去补哪样。

Step 1:把 diff 拆成一份份本地文件

本地 review 的第一道坎不是模型不够聪明,是上下文太长。一个 PR 动几十个文件,整份 diff 一股脑喂进去,agent 读到后面基本忘了前面在改什么。我的做法:先把 diff 按文件拆开,一个文件一个文件喂,最后再汇总。

在仓库根目录放一个 fallback-review.sh

#!/usr/bin/env bash
# 本地兜底 review agent —— 不依赖任何云端 agent 服务
# 用法:./fallback-review.sh <base_sha> <head_sha>
set -euo pipefail

BASE="${1:-origin/main}"
HEAD="${2:-HEAD}"
REPORT_DIR="/tmp/fallback-review"

rm -rf "$REPORT_DIR"
mkdir -p "$REPORT_DIR"

git diff --name-only "$BASE" "$HEAD" > "$REPORT_DIR/files.txt"

while IFS= read -r file; do
  diffdir="$REPORT_DIR/$(dirname "$file")"
  mkdir -p "$diffdir"
  git diff --no-ext-diff "$BASE" "$HEAD" -- "$file" > "$REPORT_DIR/$file.diff"
done < "$REPORT_DIR/files.txt"

find "$REPORT_DIR" -name "*.diff" | wc -l

跑一下:

chmod +x fallback-review.sh
./fallback-review.sh HEAD~1 HEAD

这一步下来,/tmp/fallback-review 里应该躺着一堆 .diff 文件,和你这次改动一一对应。逐个打开确认内容没问题,至少看到两个文件的 diff 再往下一步。

⚠️ 这一步很多人会卡在新加的文件不进 git diff——它默认只比较已跟踪文件的改动,新建文件一概当没看见。review 漏掉一个整个新文件,比漏掉十行改动严重得多。先跑一遍 git add -N . 把所有新文件标成“空加入”,再跑脚本:

git add -N .
./fallback-review.sh HEAD~1 HEAD

git add -N 不会真的把文件加进暂存区,只让 git 在 diff 的时候把算进去。这个动作很快,别跳过。

Step 2:把每个 diff 喂给本地 agent

diff 拆好了,下一步让本地 agent 逐个看。这一步调 Claude Code 的 CLI 非交互模式,claude -p 接 prompt,diff 从 stdin 喂进去,输出直接落盘。

我没有让脚本帮你把 prompt 写死,因为这块差异太大——模型不一样,调性不一样,你自己对 review 的侧重点也不一样。下面这版是我现在自己用的,你照抄能跑,跑完按你团队的脾气改两行也不难。

在同一个目录下放 local-review.sh

#!/usr/bin/env bash
# 逐个文件跑本地 review,汇总成一份 REVIEW.md
set -euo pipefail

REPORT_DIR="/tmp/fallback-review"
REVIEWS_DIR="$REPORT_DIR/reviews"
mkdir -p "$REVIEWS_DIR"

while IFS= read -r file; do
  [ -f "$REPORT_DIR/$file.diff" ] || continue

  safe_name="$(echo "$file" | tr '/' '__')"
  claude -p "你是一名 review 工程师。下面是 $file 的 diff,请挑出正确性问题、明显的不合理设计和漏掉的边界情况。按严重程度排序,不要夸,不要改代码,每条意见给到能直接动手的程度。" < "$REPORT_DIR/$file.diff" > "$REVIEWS_DIR/$safe_name.md"
done < "$REPORT_DIR/files.txt"

cat "$REVIEWS_DIR"/*.md > "$REPORT_DIR/REVIEW.md"
wc -l "$REPORT_DIR/REVIEW.md"

跑一遍:

chmod +x local-review.sh
./local-review.sh

注意 prompt 里我没说任何客套话,故意不说的。review 这个场景,越客气模型越爱绕圈子,最后给你一堆正确的废话。你团队内部有自己的 review 口径,就把这段替换掉,格式可以不动。

这一步的节奏是串行的,一个文件一个文件走,几十个文件的大 PR 会跑一阵子。别动并行优化的心思,我试过,快是快了一点点,但 agent 的注意力被切碎之后,意见质量明显下滑。这台兜底机器要的是稳,不是快。

我写到这一步才想起来有个事得提前交代:如果你这个仓库比较大,第一次跑 git diff 会明显卡顿。别慌,那是在生成全量对比,等它跑完就行。嫌慢的话,Step 1 里 BASE 不用非得给 origin/main,给一个离 HEAD 更近的 commit,diff 范围小了自然就快。

Step 3:汇总报告,落回本地

local-review.sh 跑完,/tmp/fallback-review/REVIEW.md 就是这一整轮的 result。把每个文件的问题拎出来,按严重程度排一遍,读一遍有没有明显胡说的——这个动作别省,agent 有幻觉,你才是最后把关的人。

要不要顺手把报告自动写回 PR,我还没想清楚。理论上一个 gh pr comment 的事,但今天断的恰好就是云端这条链,兜底方案再去依赖同一个链路,等于没兜底。我的选择:先把这份 REVIEW.md 留在本地,等上游恢复了我手动贴回 PR。多一步,但每一步都踏实。

到这,这个本地兜底 agent 就搭完了。跑起来了吗,照这个清单自查一下:

  • /tmp/fallback-review 里有跟改动一一对应的 .diff 文件
  • local-review.sh 跑完生成了 REVIEW.md,每个文件各有一小节
  • 你手动抽查了至少一条意见,能对得上代码,不是胡说

都打勾了,这篇就算交付。接下来你可以试着把它接到你团队的 review 模板上,规定每条意见必须带文件路径和行号;或者每个周末手动跑一次,跟 Cursor 的 review 结果对一下,确认这台兜底机器真要上场的时候不是坏的。