Skip to content
← 文章目次 HCYTLOG / 文章與筆記

GitLab Duo CLI 進階篇:批次自動化、多模型比較與降噪技巧

保留 2026 年 6 月的 Duo CLI 批次 review 經驗,更新 2026-10-08 的模型識別碼、headless 自動核准與 Credits 計費。附可重試的完成標記、timeout 腳本,以及單次實測的限制。

For English readers, switch to the English version.EN
本文目錄

這篇是上一篇入門文的延續,保留 2026 年 6 月的批次 review 經驗。2026-10-08 補查版本、模型識別碼、計費與 headless 行為;腳本的本機流程有離線測試,這次沒有實跑消耗 Credits 的任務。

為什麼要批次跑

在原文裡,我記下一次接手 review 一個跨了十幾個模組的重構 MR。在網頁上一個模組一個模組問 Duo Chat,問到第五個的時候我已經忘記第一個的結論了。而且每次都要重新給 context,因為 Duo Chat 不知道我之前問了什麼(那時候還沒有 session 同步)。

那次之後我就開始寫腳本了。把十幾個模組的 review 任務排成佇列,一口氣跑完,結果存成檔案。我泡杯咖啡回來,所有結果都在那裡等我。

批次跑的好處是:等待 AI 回答時,不用一直盯著畫面,可以先去做別的事。

最小可行的批次架構

2026-10-08 更新:批次前的設定與執行邊界

先完成入門篇的版本、認證與 namespace 設定。官方安裝頁目前要求 glab 1.107.0 以上;GitLab 19.2 起是正式版,18.11 到 19.1 需要 beta 與實驗功能。還要符合 Agent Platform 前置條件,並設定 default Duo namespace,或在有 Duo 存取權的專案啟動。席次與群組權限不是腳本能繞過的。

官方 headless 說明現在寫得很清楚:glab duo cli run 自動核准工具,不需要額外加 --dangerously-skip-permissions。下面拿掉這個 flag,不代表腳本變成唯讀。批次分析要用可丟棄的工作副本與受控沙盒,隔開正式憑證,結束後檢查差異;prompt 寫「只做 review」不是安全限制。

任務資料與完成標記

不需要搞得很複雜。我的做法是三個資料夾:

my-review/
├── cells/        # 每個任務一個 JSON 檔
├── state/        # 完成標記(.done 檔)
└── results/      # AI 回覆存在這

一個 cell 長這樣:

{
  "id": "auth-module-error-handling",
  "target": "/path/to/repo",
  "model": "claude_opus_4_6_20260205",
  "goal": "Review auth 模組的錯誤處理,特別注意 token 過期的 edge case"
}

跑的腳本:

#!/bin/bash
for cell_file in cells/*.json; do
  cell_id=$(jq -r '.id' "$cell_file")

  # 已經跑過就跳過
  [ -f "state/${cell_id}.done" ] && continue

  goal=$(jq -r '.goal' "$cell_file")
  target=$(jq -r '.target' "$cell_file")
  model=$(jq -r '.model' "$cell_file")

  echo "⏳ Running: $cell_id"

  if glab duo cli run \
    -C "$target" \
    --goal "$goal" \
    --model "$model" \
    > "results/${cell_id}.md" 2>&1; then
    touch "state/${cell_id}.done"
    echo "Done: $cell_id"
  else
    status=$?
    echo "Failed: $cell_id (exit $status); retry on the next run" >&2
  fi

  sleep 30  # 避免打太快
done

echo "這輪處理結束。"

重點是那個 .done 檔:只有指令成功結束才建立。失敗的輸出留在 results/,不標記完成;下次重跑會再試一次,已成功的任務則會跳過。

我通常在 cell 之間 sleep 30 秒。不是技術上一定要,但實測打太快偶爾會被限流,30 秒是穩定的間隔。

別忘了加 timeout

這是我學到的教訓:有些任務 AI 會想超級久,特別是你給它一個很大的 repo 加一個很模糊的問題。有一次我睡前開始跑 10 個 cell,醒來發現它卡在第 3 個已經跑了 6 小時。

後來我加了 timeout 機制:

# 背景執行 + 計時
glab duo cli run -C "$target" --goal "$goal" \
  --model "$model" \
  > "results/${cell_id}.md" 2>&1 &
PID=$!

TIMED_OUT=0
ELAPSED=0
while kill -0 "$PID" 2>/dev/null; do
  sleep 10
  ELAPSED=$((ELAPSED + 10))
  if [ "$ELAPSED" -ge 900 ]; then  # 15 分鐘上限
    TIMED_OUT=1
    kill "$PID" 2>/dev/null || true
    break
  fi
done
if wait "$PID"; then
  status=0
else
  status=$?
fi

# 等待指令結束後再追加,避免它的輸出覆寫逾時紀錄。
if [ "$TIMED_OUT" -eq 1 ]; then
  echo "TIMEOUT after 15min" >> "results/${cell_id}.md"
fi

if [ "$TIMED_OUT" -eq 0 ] && [ "$status" -eq 0 ]; then
  touch "state/${cell_id}.done"
else
  echo "Failed: $cell_id (exit $status, timed_out=$TIMED_OUT); retry on the next run" >&2
fi

15 分鐘是我目前覺得合理的上限。正常的 review 任務大概 2-5 分鐘會跑完,超過 15 分鐘通常代表它陷入某種迴圈了。逾時紀錄會接在原本的輸出後面,不建立 .done;這輪先處理下一個任務,下次重跑還能再試。這個簡例只對單一 PID 送出 TERM,未涵蓋子程序或忽略 TERM 的情況。

多模型比較的正確姿勢

上一篇提過我會用多模型交叉比對。這篇來分享具體數據。

原文的比較紀錄

原文記下我拿同一個 code review 任務跑過 9 個模型,表格保留以下 7 筆摘要。原文沒有註明測試日期、完整 prompt、每個模型版本與逐輪輸出,這些數字只能當作那次使用紀錄,不能用來排現在的模型名次:

模型 輸出大小 我的評價
Claude Opus 4.6 10.2 KB 面面俱到,什麼都講到了,適合第一次看不熟的 code
Claude Opus 4.8 7.9 KB 直接告訴你該改什麼
Claude Opus 4.7 5.9 KB 極簡,只講結論,適合你只想快速確認
GPT 5.5 7.4 KB 偶爾切入角度完全不同,有驚喜
Gemini 3.1 Pro 7.1 KB 結構清晰,範圍切得很精準
Gemini 3.5 Flash 4.4 KB 最快,但深度不夠,當快篩用
GPT 5.4 0.3 KB 那一輪拒絕回答,原因沒有另外驗證

幾個實用的心得:

依任務選模型。 我當時的組合是:

  • 快速初篩:Gemini 3.5 Flash(那輪回覆最快)
  • 全面分析:Claude Opus 4.6(什麼都不想漏掉的時候)
  • 第二意見:GPT 5.5(思路跟 Claude 很不一樣)

交叉比對後,還是要查證。 兩個模型都指出同一個問題,可以優先看,但也可能共享相同誤解。只有一個模型提到的發現,也不能只因為少數就刪掉;最後還是看程式碼、重現條件與測試。

2026-10-08 更新:用 GitLab 的模型識別碼

--model 和 GITLAB_DUO_MODEL 接受的是 gitlab_identifier,不是供應商 API 的模型名稱。下面按官方 model registry的 2026-10-08 內容更新;實際可選模型仍看你的實例與群組設定,也可以在互動模式用 /model 查看。

寫成腳本就是多跑幾次:

MODELS=("claude_opus_4_6_20260205" "claude_opus_4_7" "gemini_3_5_flash_vertex")

for model in "${MODELS[@]}"; do
  glab duo cli run -C "$TARGET" \
    --goal "$GOAL" \
    --model "$model" \
    > "results/${CELL_ID}-${model}.md" 2>&1
  sleep 30
done

縮小 review 範圍,再查證發現

git log 錨點:給 AI 一張地圖

這是我從實戰中摸出來的,效果提升非常明顯。

問題是這樣的:你叫 AI「review 這個 repo」,它不知道從哪裡開始。一個幾千個檔案的 repo,它要自己決定看什麼、跳過什麼。結果常常是:花了很多時間在不重要的地方,真正有問題的地方反而沒看到。

解法:先給它一張地圖。

# 撈出特定主題的 commit 歷史
git log --all \
  --grep='error\|exception\|retry\|timeout\|fallback' \
  --regexp-ignore-case \
  --name-only \
  --format='%h %cs %s' \
  > error-handling-anchors.txt

這份檔案告訴 AI:「這些是最近跟錯誤處理相關的改動,專注看這些。」

glab duo cli run -C ~/project \
  --goal "以下是近期跟錯誤處理相關的 commit:
$(head -50 error-handling-anchors.txt)

根據這些 commit:
1. 錯誤處理的 pattern 是否一致?
2. 有沒有某些模組做了 retry 但類似的模組忘了做?
3. 有沒有 exception 被吞掉(catch 了但沒處理)的跡象?"

為什麼效果好?因為 git log --grep 撈出來的是真正被改過的地方。開發者花時間修的東西,代表那裡曾經有問題。AI 從這些點出發去分析「還有沒有類似的問題」,可以先把調查範圍縮小;「精準十倍」沒有對照測試,不能當作測量結果。

我常用的幾組 keyword:

  • 錯誤處理:error|exception|retry|timeout|fallback
  • 重構:refactor|extract|rename|move|split
  • 效能:perf|slow|cache|optimize|batch
  • 技術債:TODO|FIXME|HACK|workaround|temporary

prompt 驗證條件:降噪 90% 的密技

我用了一陣子才發現,最麻煩的是「AI 找到太多問題,大部分是假的」。

一個 code review 任務回報 20 幾個 finding,你一個一個看,結果 18 個是「嗯理論上是個問題但實際上不會發生」或「已經有其他機制處理了」。浪費的時間比不跑 AI 還多。

轉捩點是我開始在 prompt 尾端加驗證條件:

glab duo cli run -C ~/project \
  --goal "Review 這個模組的錯誤處理 pattern。

回報前,每個發現都要通過以下檢查:
1. 在預設設定下這個問題真的存在嗎?(不是只有特殊設定才觸發)
2. 有沒有現有的防護機制已經處理了?(看上下文有沒有 catch / retry / guard)
3. 影響範圍是否超出一般使用?(不是要極端操作才碰到的)
4. 這個問題是真的會造成影響的,不是 style 偏好?

不通過的標為「不適用 — 原因:___」。
只詳細報告通過全部四項的發現。"

當時的結果:某次跑出 21 個結果,加上驗證條件後剩 2 個,回報數少了約 90%。這是單次任務的數量變化,不是誤報率或正確率;被刪掉的 19 個仍可能有漏判,留下的 2 個也要人工查證。

這個做法是:讓 AI 做兩次判斷。 第一次找問題,第二次驗證問題是否真的成立。兩次判斷之間的落差,就是你省下的人工篩選時間。

驗證條件可以根據場景客製化。做 code review 和做技術債盤點的條件不一樣,但結構相同:給 AI 一組「這個 finding 值得回報」的判斷標準。

跟其他工具的搭配

我也會把 Duo CLI 和其他工具搭配使用。

階段 工具 為什麼
廣度掃描 Duo CLI 多模型、可批次,當時的使用額度適合初篩
深度分析 Claude Code 有記憶、有工具鏈、適合來回多輪
機械性驗證 Codex CLI 沙盒執行、適合跑確認腳本

流程大概是:

  1. Duo CLI 把 repo 的模組批次掃一遍(廣度),用 2-3 個模型交叉看
  2. 結果裡標記「需要深入看」的部分,丟給 Claude Code 逐一挖(深度)
  3. 最後整理成結論,確認修正方向

Duo CLI 在這裡的角色是「第一道濾網」。它不需要做得完美,它需要做得快、做得廣。下一輪的深度分析仍需要明確範圍與驗證,不能保證補回所有漏掉的問題。

2026-10-08 更新:比較成本要看呼叫與額度

六月的流程用到了我當時取得的貢獻者使用額度,並不代表 Enterprise seat 自動附帶同樣額度。官方計費文件把 Agent Platform usage billing 與 Duo Pro/Enterprise 的席次型功能分開,community subscriptions 不附 included credits。不同模型的 credit multiplier 不同,一個任務可能有多次 LLM 呼叫;重跑三個模型,成本也會增加。

批次前先查 namespace 的可用 Credits、用量上限與 on-demand 設定。要比較其他工具,就記下同一任務的實際消耗與驗證後的有效結果,不能只看「都是 Credits」。

一些零散但實用的小提醒

  • 結果存 .md 比 .txt 好。 AI 的回覆通常有 markdown 格式,存成 .md 之後用任何 markdown viewer 打開就很好讀。
  • 用 GITLAB_DUO_MODEL 環境變數設預設模型。 不用每次都打 --model。
  • 大 repo 拆模組跑。 一次丟整個 repo 效果通常不好。指定子目錄或用 --ai-context-items 只注入相關檔案,分析會更集中。
  • prompt 越具體越好。 「review 這段 code」不如「review 這段 code 的錯誤處理,特別注意 timeout 的 edge case」。
  • 留一份 prompt 模板。 好的 prompt 值得重複用。我有一個資料夾專門放常用的 prompt 模板,不同任務類型套不同模板。

結語

Duo CLI 的進階玩法核心就三件事:批次化、多模型、降噪。把這三個搞定,你就從「一次問一個問題」變成「一次掃一整個 codebase」。

CLI 工具本來就能互相組合,Duo CLI 也一樣。把 AI 接進命令列,就能用 shell script 串起這些工作。

如果你有更好的做法,歡迎在社群分享,我也還在調整自己的流程。