主管發了一個 PR 成功把 Claude Code 串上 CI 做 Code Review 了!
好酷喔!我一直以為這件事只能用 API 方案做沒想到可以用 token 處理耶 Claude 帳號的 Token 丟進公司 CI 跑這官方合法嗎?會不會封鎖? 開始一連串研究
這是兩道很實際的門檻:第一,官方到底有沒有合規依據;第二,如何在不洩漏憑證、不被惡意 PR 搞壞環境的前提下,用最少步驟把水管接通。
1. 官方依據:Token 怎麼放?合不合規?
很多人以為把 Claude 丟進 CI 只能走 API Key,或者需要透過未公開的逆向手法。其實 Anthropic 官方在文件裡有明文給出解法。
技術依據:claude setup-token
在官方文件 Authentication › Generate a long-lived token 中明確指出:
For CI pipelines, scripts, or other environments where interactive browser login isn’t available, generate a one-year OAuth token with
claude setup-token:
做法非常單純:
- 在本機終端機輸入:
Terminal window claude setup-token - 瀏覽器會跳出授權視窗,登入後終端機會印出一組
sk-ant-oat01-...的長期 Token(效期一年)。 - 到 Azure DevOps 的 Pipelines > Library 建立一個 Variable Group(例如
claude-review),把這組字串存成 Secret 變數:CLAUDE_CODE_OAUTH_TOKEN。
在技術上,官方明確承認在 CI 環境使用這個環境變數來驅動 CLI。
條款邊界:商業 vs 個人
依據官方 Legal and compliance 文件,有一條清楚的邊界:
- Team / Enterprise 方案:適用 Commercial Terms(商業條款)。
- Free / Pro / Max 方案:適用 Consumer Terms(個人條款),官方明文限制額度是基於「個人日常使用(individual usage)」。
具體判斷:如果要放在公司 CI 上跑,請務必綁定 Team 或 Enterprise 帳號 的席位。若團隊對「多個 PR 共用一個席位」有嚴格的合規風控考量,最乾淨無爭議的做法則是改去 Anthropic Console 申請 API Key(按用量計費,官方明文允許存於 Secrets Manager)。
2. 核心防線:四個步驟的最小憑證隔離
在 CI 上審查 PR,最危險的是 Prompt Injection:任何開 PR 的人,都可能在程式碼、Commit 訊息或 PR 描述中藏有惡意指令,試圖騙 AI 印出環境變數或執行破壞性腳本。
因此,最小可行架構的底線就是**「四步隔離,每一步只拿它需要的最小憑證」**:
① 拉取資料 (git diff) ── 憑證:System.AccessToken (只讀 ADO 資訊,組裝 prompt.md) │② 安裝 CLI ───────────── 憑證:無 (npm install,不給任何 Token,防止惡意依賴偷抓環境變數) │③ 跑 Claude Code ────── 憑證:只有 CLAUDE_CODE_OAUTH_TOKEN (只給 AI Token,不給 ADO Token) │ - 拔除 Bash / Write,鎖定純唯讀工具 │ - 只輸出 JSON 檔案 ▼④ 貼回 PR 留言 ───────── 憑證:System.AccessToken (讀取 JSON,由腳本呼叫 ADO API 貼文)關鍵參數與踩坑細節
在第 ③ 步呼叫 claude -p(非互動模式)時,有三個重要參數:
--disallowedTools Bash WebFetch WebSearch Write Edit NotebookEdit
把執行的 Bash、聯網的 Fetch、寫入檔案的 Edit 工具全關閉。
註:Linux 上的 Claude Code 預設不開 Glob 和 Grep(改用系統 Bash 工具);但只要你禁用了 Bash,CLI 就會自動把唯讀的 Glob 和 Grep 補回來,讓 AI 依然能在 repo 裡跳轉查找程式碼,但完全喪失寫入與執行指令的能力。--setting-sources user
只載入執行跑者的環境設定,忽略 PR 分支裡可能被動過手腳的.claude/settings.json。- Prompt 必須從標準輸入餵進去(
< prompt.md)
--disallowedTools會吞掉它後面的所有字串參數。如果把 Prompt 直接當參數接在後面,所有字都會被判定成「要禁用的工具名稱」,導致執行錯誤。
3. 最小實現:完整 Pipeline YAML
這是一個單一 Repo 內即可直接驗證的最小 Pipeline。
在 Repo 的 .azure-pipelines/claude-review.yml 放入以下內容,並在 Azure DevOps 將這支 Pipeline 設為 PR 的 Build Validation:
trigger: none
pr: branches: include: - main
pool: vmImage: 'ubuntu-latest'
variables: - group: claude-review # 內含 Secret 變數:CLAUDE_CODE_OAUTH_TOKEN
jobs: - job: aiReview displayName: 'Claude Code PR Review' steps: - checkout: self fetchDepth: 2 # 確保能拿到 HEAD^1 做比對 persistCredentials: false
# ── ① 準備 Diff 與 Prompt ── - bash: | set -euo pipefail
# 取得 git diff(排除 lock 檔) git diff HEAD^1 HEAD -- . ':!package-lock.json' ':!pnpm-lock.yaml' > diff.patch
if [ ! -s diff.patch ]; then echo "沒有需要審查的變更。" echo "##vso[task.setvariable variable=SKIP_REVIEW]true" exit 0 fi
# 組裝內嵌 Prompt(先用最簡單的結構,不外掛 Skill) cat << 'EOF' > prompt.md 你是一位資深工程師,請針對以下 git diff 進行 Code Review。
審查重點: 1. 邊界條件與潛在邏輯錯誤 2. 安全漏洞(注入、憑證洩漏) 3. 是否有未處理的例外或資源洩漏
請直接指出具體有問題的程式碼行數、錯誤情境與修改建議。若無重大問題請簡要總結。 輸出請使用清晰的 Markdown 格式。
=== 以下為變更內容 === EOF
cat diff.patch >> prompt.md displayName: '1. Prepare diff and prompt'
# ── ② 安裝 CLI(完全不給憑證)── - bash: | npm install -g @anthropic-ai/claude-code displayName: '2. Install Claude Code CLI' condition: ne(variables['SKIP_REVIEW'], 'true')
# ── ③ 執行唯讀審查(只帶 Claude Token)── - bash: | set -euo pipefail
# 執行非互動審查,輸出結果至 review.md claude -p \ --model "sonnet" \ --setting-sources user \ --strict-mcp-config \ --no-session-persistence \ --disallowedTools Bash WebFetch WebSearch Write Edit NotebookEdit \ < prompt.md > review.md displayName: '3. Run Claude Review' env: CLAUDE_CODE_OAUTH_TOKEN: $(CLAUDE_CODE_OAUTH_TOKEN) condition: ne(variables['SKIP_REVIEW'], 'true')
# ── ④ 將審查結果貼回 PR 留言(只帶 ADO Token)── - bash: | set -euo pipefail
COMMENT_CONTENT=$(cat review.md)
# 組裝 ADO PR Thread 請求 Payload PAYLOAD=$(jq -n --arg content "### 🤖 Claude Code Review 報告\n\n$COMMENT_CONTENT" '{ comments: [{ parentCommentId: 0, content: $content, commentType: 1 }], status: 1 }')
# 呼叫 ADO REST API 新增 PR Thread curl -sSf -X POST \ -H "Authorization: Bearer $SYSTEM_ACCESSTOKEN" \ -H "Content-Type: application/json" \ -d "$PAYLOAD" \ "${SYSTEM_COLLECTIONURI}${SYSTEM_TEAMPROJECT}/_apis/git/repositories/${BUILD_REPOSITORY_ID}/pullRequests/${SYSTEM_PULLREQUEST_PULLREQUESTID}/threads?api-version=7.1" displayName: '4. Post PR Comment' env: SYSTEM_ACCESSTOKEN: $(System.AccessToken) condition: and(succeeded(), ne(variables['SKIP_REVIEW'], 'true'))註:若要讓步驟 ④ 能正常貼文,請確保專案的 Project Collection Build Service 帳號在該 Repo 擁有 Contribute to pull requests 權限。
4. 具體判斷與這套做法的適用邊界
這是我們目前驗證過、門檻最低的最小可行實作(MVP),30 分鐘內即可跑通。
它的適用範圍:
- 單一 Repo 或小團隊:不需要建立集中管理管線,貼上 YAML 就能立刻跑起來。
- 安全底線清楚:嚴格落實四步隔離,PR 裡的不可信輸入無法讀取 ADO 的
System.AccessToken,也無法透過 Bash 或 Write 修改環境。
心得
查完文件才發現,claude setup-token 本來就是 Anthropic 提供給 CI 等非互動環境使用的方式。用 -p 在 Azure DevOps Pipeline 跑 PR review,串接方式比我原本想像的簡單。不過,Token 的方案條款與 pipeline 權限仍要各自確認,不能只靠四步隔離就說完全合規。
接下來我想研究怎麼把這段流程抽成可重用的 Skill,套用到多個專案,也讓各專案保有自己的審查標準。共用流程和專案規則要怎麼搭配,應該會很好玩。