1. 从 Cursor 到 Claude Code:我的 GitHub Action 自动化踩坑记
先说结论:不是 Cursor 不够强,是 Claude Code 在 CI 场景里太猛了。我用了大半年 Cursor 写业务代码,补全、重构、多文件编辑都很顺手,但一旦把场景搬到 GitHub Action 里,Cursor 的短板就暴露了——它本质是个 IDE,强依赖人在编辑器里交互,而 CI 里没有「人盯着编辑器」这个前提。Claude Code 不一样,它从设计之初就是命令行优先、可脚本化、可无头运行的,这三点恰好是 GitHub Action 自动化的命门。
Claude Code 是什么?一句话:Anthropic 推出的终端 AI 编程助手,能在命令行里读代码、改文件、跑命令、提交 PR。它能做什么?在 CI 里自动做代码审查、生成变更摘要、修复 lint 错误、补测试、甚至根据 issue 描述直接开分支改代码。适合谁?适合已经在用 GitHub Actions 做 CI/CD、想让 AI 真正进入流水线而不是停在编辑器里的团队和个人开发者。
我试过的第一个坑,是把 Cursor 的思路直接搬过来:以为在 workflow 里调个 API 就完事。结果发现真正的难点不在「调模型」,而在「让模型安全地读写仓库、跑命令、控制权限边界」。Claude Code 的/install GitHub Action引导流程解决的正是这件事——它帮你把 GitHub App 装好、把权限配好、把 workflow 模板生成好。下面我把从对比、接入到可运行验证的完整路径拆开讲,每一步都能直接复制。
2. TaoToken 前置:统一 Key 与 API 通道,别让 CI 里散落一堆密钥
在讲 workflow 之前,必须先解决一个现实问题:CI 里的密钥管理。如果你在 GitHub Action 里直接硬编码 Anthropic 的 Key,或者每个仓库配一套,维护成本会爆炸。更麻烦的是,Claude Code 在本地和 CI 里如果走不同的通道,行为可能不一致,排查起来很痛苦。
我的做法是用 TaoToken 做统一入口。它提供兼容的 API 通道,本地 Claude Code 和 GitHub Action 里可以共用同一个 Base URL 和 Key,模型 ID 也统一。这样本地验证通过的配置,推到 CI 里基本不会因为「通道不同」而翻车。官网入口在这里:https://taotoken.net/?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content= ,API 地址是 https://taotoken.net/api (注意这个不带 UTM)。
具体要准备三样东西,我称之为「三件套」:
第一,Base URL。Claude Code 通过环境变量ANTHROPIC_BASE_URL读取,填https://taotoken.net/api。
第二,API Key。在控制台生成,本地放 shell 环境变量,CI 里放 GitHub Secrets。生成入口:https://taotoken.net/console/api-keys?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite 。
第三,Model ID。日常 CI 任务用 Sonnet 就够,复杂推理再切 Opus。Model ID 要写全,比如claude-sonnet-4-20250514这类完整标识,别只写sonnet,否则在非交互环境里可能解析失败。
这里有个关键点:Claude Code 在 CI 里是「无头模式」,它不会弹交互菜单让你选模型。所以 Model ID 必须通过配置或环境变量显式传入。我见过太多人本地用/model sonnet切好了,推到 CI 里却报模型找不到,就是因为 CI 里没有这个交互步骤。
另外提醒一句:GitHub Secrets 里存的 Key,命名建议用ANTHROPIC_API_KEY和ANTHROPIC_BASE_URL,因为 Claude Code 和很多封装脚本默认读这两个名字,省得你再写映射逻辑。如果你用的是 Claude Code 的 coding plan 模式做长期 Agent 任务,可以在 https://taotoken.net/coding-plan?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite 看下额度策略,CI 高频触发时心里有数。
3. 可复制配置:workflow YAML + settings 片段一次给全
这一节是核心,我直接把能跑的配置贴出来。先给 Claude Code 的本地/CI 共用配置文件,再给 GitHub Action 的 workflow。
Claude Code 读取的配置,我习惯放在项目根目录的.claude/settings.json,这样本地和 CI 都能复用同一份逻辑(CI 里通过环境变量覆盖敏感值)。片段如下:
{ "env": { "ANTHROPIC_BASE_URL": "https://taotoken.net/api", "ANTHROPIC_MODEL": "claude-sonnet-4-20250514" }, "permissions": { "allow": [ "Read", "Edit", "Bash(git diff:*)", "Bash(git status:*)" ], "deny": [ "Bash(rm:*)", "Bash(curl:*)" ] } }注意permissions这块,CI 里一定要收紧。deny里禁掉rm和curl是底线,避免模型在自动化流程里执行危险命令。allow只放开它真正需要的读、改、看 diff 这几类。
然后是 GitHub Action 的 workflow,放在.github/workflows/claude-review.yml:
name: Claude Code Review on: pull_request: types: [opened, synchronize] jobs: review: runs-on: ubuntu-latest permissions: contents: read pull-requests: write steps: - uses: actions/checkout@v4 with: fetch-depth: 0 - uses: actions/setup-node@v4 with: node-version: '22' - name: Install Claude Code run: npm install -g @anthropic-ai/claude-code - name: Run Claude Code Review env: ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }} ANTHROPIC_BASE_URL: ${{ secrets.ANTHROPIC_BASE_URL }} run: | claude -p "审查本次 PR 的改动,指出潜在 bug、安全问题,并用中文输出简洁结论" \ --output-format json > review.json cat review.json - name: Comment on PR if: always() uses: actions/github-script@v7 with: script: | const fs = require('fs'); const raw = fs.readFileSync('review.json', 'utf8'); const data = JSON.parse(raw); const body = data.result || 'Claude Code 未返回内容'; github.rest.issues.createComment({ issue_number: context.issue.number, owner: context.repo.owner, repo: context.repo.repo, body: body });这里有几个细节值得说。fetch-depth: 0是为了让 Claude Code 能看到完整 git 历史,做 diff 分析时更准。claude -p是 headless 模式,-p后面跟 prompt,--output-format json让输出结构化,方便后续解析。Node 版本用 22,和 Claude Code 的要求对齐。
如果你用的是 Cline MCP 或者 Codex 的auth.json那套体系,三件套同样要写全:Base URL 填https://taotoken.net/api,Key 填控制台生成的,Model ID 填完整标识。别偷懒只填两个,CI 里缺一个就报错。
4. 验证请求:本地先跑通,再推 CI
配置写完别急着 push,先在本地验证一遍,能省掉大量来回调试的时间。本地验证分两步。
第一步,确认 Claude Code 能连上通道。在终端里:
export ANTHROPIC_API_KEY="你的Key" export ANTHROPIC_BASE_URL="https://taotoken.net/api" claude -p "用一句话说明这个仓库是做什么的" --output-format json如果返回了 JSON 且里面有正常文本,说明通道通了。如果报 401,往下看第 5 节的排查。
第二步,模拟 CI 里的审查命令。在本地仓库里造一个改动,然后跑:
git diff HEAD~1 > /tmp/changes.diff claude -p "审查以下 diff,指出问题:$(cat /tmp/changes.diff)" --output-format json这一步能验证模型是否真的读到了 diff 内容。我踩过的坑是:本地没提交改动,git diff是空的,模型返回「没有改动可审查」,推到 CI 里才发现逻辑没问题但输入是空的。所以本地一定要造一个真实改动来测。
本地跑通后,把 Key 和 Base URL 加到 GitHub Secrets:仓库 Settings → Secrets and variables → Actions → New repository secret,分别建ANTHROPIC_API_KEY和ANTHROPIC_BASE_URL。然后推一个 PR,看 Action 是否触发、是否成功评论。
成功的结果长这样:PR 下面出现一条 Claude Code 生成的评论,内容是中文的审查结论,指出改动里的问题。Action 日志里能看到claude -p执行完成、review.json生成、评论步骤成功。如果评论内容是空的,多半是 JSON 解析路径不对,检查data.result这个字段名是否和实际返回一致。
想更直观地看模型对话效果,可以到 https://taotoken.net/models?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite 手动发几条请求,确认通道和模型都正常,再回到 CI 里排查。
5. 本篇常见错排查:401、local proxy failed、reading choices、OAuth
这一节我按真实报错来对,都是我在 CI 里实际撞过的。
401 Unauthorized。最常见的原因是 Key 没传进容器,或者 Secrets 名字写错。检查 workflow 里env的变量名和 Secrets 里建的名字是否完全一致,大小写敏感。另一个原因是 Base URL 末尾多了斜杠,https://taotoken.net/api/和https://taotoken.net/api在某些客户端里行为不同,建议去掉末尾斜杠。
local proxy failed。这个报错通常出现在本地 Claude Code 配置了代理但 CI 里没有代理时。CI 环境是干净的,如果你本地settings.json里写了代理相关配置,推到 CI 会失败。解决办法是把代理配置从共享配置里拿掉,只保留 Base URL 和 Model ID。
reading choices 相关报错。这类错误一般是响应格式不符合预期,常见于 Model ID 写错或通道返回了非标准结构。先确认 Model ID 是完整标识,再确认 Base URL 指向的是兼容通道。如果本地能跑 CI 不能跑,对比两边的环境变量,八成是 Model ID 不一致。
OAuth 相关报错。Claude Code 某些版本会尝试走 OAuth 登录流程,在 CI 无头环境里会卡住。解决办法是显式用 API Key 模式,确保ANTHROPIC_API_KEY已设置,并且不要触发任何需要交互登录的命令。如果你在本地登录过,CI 里不要复用本地的凭据文件,用 Secrets 传 Key 最干净。
还有一个隐蔽的坑:GitHub Action 的permissions没给pull-requests: write,导致评论步骤静默失败。日志里不一定报错明显,但 PR 上就是没评论。检查 workflow 顶部的permissions块。
排查顺序建议:先看 Action 日志里claude -p那一步的原始输出,再看 JSON 解析,最后看评论步骤。大部分问题在第一步的原始输出里就能看到线索。
6. 语义一致 CTA:把通道和文档收好,下次直接复用
整套流程跑通后,你会发现真正值钱的不是某一条 workflow,而是「统一通道 + 可复制配置 + 明确排查路径」这套组合。本地和 CI 共用同一个 Base URL 和 Model ID,出问题时对比两边环境变量就能定位,不用在多个平台之间来回猜。
需要生成或轮换 Key 的时候,直接去 https://taotoken.net/console/api-keys?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite 。接入细节和参数说明看文档:https://taotoken.net/doc?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite 。如果你要做的是长期编码 Agent 而不是单次审查,Coding Plan 那条线更适合:https://taotoken.net/coding-plan?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite 。想先手动验证模型行为,用模型对话页最快:https://taotoken.net/models?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite 。
最后留一个我自己的实用习惯:把.claude/settings.json里的permissions.deny当成 CI 的安全底线,每次加新能力前先想清楚要不要放开对应权限。Claude Code 在 GitHub Action 里能做的事很多,但自动化流程里「能不做危险操作」比「能做多少事」更重要。