在 GitHub Actions 里跑 Claude Code:workflow 怎么写、密钥怎么给
一、它到底替你省了哪一步
先说清楚这篇讲的是哪个东西。官方文档在 GitHub Actions 那一页开头就特意提醒:叫 Claude Code 的产品有好几个,这一页只讲 claude-code-action 这个 workflow 集成——要靠你自己往仓库里放 workflow 文件的那种。想要「每个 PR 自动评审、但不维护 workflow 文件」,文档指的是另一页 Code Review;想在浏览器里开会话,那是 Claude Code on the web;想在 GitHub 之外做自动化,那是 Claude Agent SDK。文档还写明一句关系:Claude Code GitHub Action 本身是构建在 SDK 之上的。
装上之后能干什么,文档说得很具体:在 issue 或 PR 评论里 @claude,它会分析代码、做改动、推 commit;也可以给它一个 prompt,让它在任意 GitHub 事件上自动跑。
真正会咬人的从来不是「怎么用」,而是配置里那几行你不知道能不能删的东西,和「密钥到底放哪、名字必须叫什么」。这篇就落在这两件事上。
二、前置条件(这一段别跳)
- 仓库 admin 权限。文档写明:不管走快速安装还是手动安装,都需要对该仓库的 admin 访问权限。
- 走快速安装的话,本机要先有 GitHub CLI 并且已登录。文档写明先装 GitHub CLI 并执行
gh auth login,Claude Code 会检查它在不在,不在就会警告。 - 一份鉴权凭证,二选一:
ANTHROPIC_API_KEY:来自 Claude Console 的 API key;CLAUDE_CODE_OAUTH_TOKEN:与订阅绑定的 OAuth token,本地执行claude setup-token生成。
这两者在 workflow 里对应不同的输入名,别混:API key 传给 anthropic_api_key,OAuth token 传给 claude_code_oauth_token。官方示例里写的是前者,如果你存的是后者,就要把示例中那行换成 claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}。
还有一条跟组织有关的坑,文档专门点了:如果这份 secret 要在多个仓库间共享,用 API key 而不是 OAuth token,因为 OAuth token 是绑在当初执行 claude setup-token 那个人的订阅上的。
安装 GitHub App 时你实际授权了多少
手动安装的第一步是装 Claude GitHub App。文档明确区分了两件事:Claude Code GitHub Action 真正用到的是三项权限——Contents(读写,改文件)、Issues(读写,回 issue)、Pull requests(读写,建 PR 和推改动);但安装时你授予的是这个 App 的全套权限,因为它是所有 Claude 的 GitHub 集成功能共用的一个 App。文档给出的授权表共 11 项:Actions、Checks、Contents、Discussions、Issues、Members、Metadata、Pull requests、Repository hooks、Statuses、Workflows。
文档同时写明:GitHub 不允许你只接受其中一部分。如果你所在组织只想给那三项,官方给的路子是自己建一个 custom GitHub App(只配 Contents、Issues、Pull requests),代价是这个自建 App 只覆盖 Claude Code GitHub Action,Code Review 和网页端的 auto-fix 仍然需要官方 App。
另外,文档提到权限集可能先于功能变动:App 申请新权限时 GitHub 会向账户所有者(组织安装则是组织所有者)请求批准,在批准之前该安装保持旧权限。
三、workflow 文件:哪几行不是模板
官方那份响应 @claude 的示例,原文如下:
name: Claude Code
on:
issue_comment:
types: [created]
pull_request_review_comment:
types: [created]
jobs:
claude:
if: contains(github.event.comment.body, '@claude')
runs-on: ubuntu-latest
permissions:
contents: write
pull-requests: write
issues: write
id-token: write
actions: read
steps:
- uses: actions/checkout@v6
with:
fetch-depth: 1
- uses: anthropics/claude-code-action@v1
with:
anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}
文档自己挑出了「非样板」的四行,正好是最容易被当成可删项删掉的:
id-token: write:默认的 GitHub App 鉴权就需要它。不是只有云厂商场景才要。actions: read:让 Claude 能读 PR 上的 CI 结果。actions/checkout:给它一份本地仓库副本可以工作。if::避免不含@claude的评论也把 runner 拉起来。文档补了一句,动作本身也会再校验一次触发词。
交互模式 vs 自动化模式:由 prompt 决定
这一处的设计有点反直觉,值得单独记住:模式不是你声明的,是根据配置推断的。文档写明——workflow 里没有 prompt 输入时是交互模式,等触发词(默认 @claude,可用 trigger_phrase 改)出现在评论、PR review、或新开 issue 的正文/标题里;结果以评论形式回到那条 issue 或 PR 上。workflow 里给了 prompt 就是自动化模式,不等提及直接跑,默认结果落在 workflow run 日志里而不是评论里——除非 prompt 指示它去发、并且它手上有能发的工具。
顺带一提,从 @beta 升到 @v1 时要删掉 mode 输入,就是因为模式改成自动判断了;同时 direct_prompt 改叫 prompt,max_turns、model 这类 CLI 选项要挪进 claude_args,而 custom_instructions 没有同名 flag,对应到 --append-system-prompt。
谁能触发它
两道检查,任何一道拒绝就整个 run 失败:
- 写权限:issue 与 PR 事件上,触发者必须对仓库有写权限。想放行个别没有写权限的人,要设
allowed_non_write_users并传入你自己的github_token。像schedule这种没有作者的事件跳过这道检查。 - 人类身份:所有事件上都会拒绝 bot 触发者,除非列进
allowed_bots。文档说这是为了防止 bot 把 Claude 拉进循环。要注意定时任务也走这道检查——GitHub 会把定时运行归属到某个仓库用户,通常是最后改动cron的那个人;如果那是个 bot,就得把它加进allowed_bots。
常用输入速查
| 输入 | 作用 |
|---|---|
prompt | 给 Claude 的指令,纯文本或一次 skill 调用;省略则改为等触发词 |
claude_args | 透传给 Claude Code 的 CLI 参数 |
anthropic_api_key / claude_code_oauth_token | 两种鉴权凭证各自的入口 |
github_token | GitHub 操作用的 token;省略时以 Claude GitHub App 身份鉴权 |
plugin_marketplaces / plugins | 换行分隔的 plugin marketplace Git URL / 待安装 plugin 名 |
settings | Claude Code 设置,JSON 字符串或设置文件路径 |
trigger_phrase | 触发词,默认 @claude |
use_bedrock / use_vertex / use_foundry | 改走对应云厂商 |
claude_args 里文档列为常用的有:--max-turns(限制回合数)、--model、--mcp-config、--allowedTools(--allowed-tools 别名同样有效)、--debug。
有一个组合很容易漏。文档在 code-review 那个示例里特意解释:即使 skill 自己的 allowed-tools frontmatter 已经写了同一个工具,claude_args 里那行 --allowedTools 也不能删——因为发内联评论的那个 MCP server,只有在 claude_args 的 --allowedTools 点名它时才会被启动。同一段还说明 --comment 决定评审去哪:带上它,评审发到 PR 上;不带,你只能去 workflow run 日志里看。
四、云厂商凭证怎么接
默认是直接调 Claude API。要把推理走自己的云账号,文档给的是三个输入之一:use_bedrock: "true"、use_vertex: "true"(Google Cloud’s Agent Platform)、use_foundry: "true"(Microsoft Foundry)。
关键点在于:这三家都不是往仓库里塞一份长期云凭证,而是让云侧信任 GitHub 签发给这次 workflow 的 OIDC token,每次运行换一份短期凭证。所以 id-token: write 在这里更是硬性的。
云侧建什么,文档按厂商分开写:AWS 侧加一个 GitHub OIDC identity provider(provider URL https://token.actions.githubusercontent.com,audience sts.amazonaws.com),建一个被它以 web identity 方式信任的 IAM role,并用类似 repo:your-org/your-repo:* 的 subject 条件把信任策略限死在你的仓库上;Google Cloud 侧要开 IAM Credentials、STS 和 Agent Platform(服务名 aiplatform.googleapis.com)三个 API,建 Workload Identity Pool 加 GitHub OIDC provider(issuer 同上)并加限定仓库的属性条件,再建一个只挂 Vertex AI User(即 roles/aiplatform.user)的专用服务账号;Azure 侧注册一个 Microsoft Entra 应用并加一条信任你仓库的 federated identity credential,给它在 Foundry 资源上分配 Azure AI User 角色。
然后是仓库 secret,名字文档给死了:
| Secret | 用于 | 值 |
|---|---|---|
AWS_ROLE_TO_ASSUME | Amazon Bedrock | IAM role 的 ARN |
GCP_WORKLOAD_IDENTITY_PROVIDER | Agent Platform | provider 的完整资源名 |
GCP_SERVICE_ACCOUNT | Agent Platform | 服务账号邮箱 |
AZURE_CLIENT_ID | Microsoft Foundry | Entra 应用的 client ID |
AZURE_TENANT_ID | Microsoft Foundry | Entra tenant ID |
AZURE_SUBSCRIPTION_ID | Microsoft Foundry | Azure 订阅 ID |
APP_ID | 自建 GitHub App | App 的 ID |
APP_PRIVATE_KEY | 自建 GitHub App | .pem 私钥文件的内容 |
云厂商那一页的 workflow 示例里,除了 use_* 那一行,还有两处值得注意:Agent Platform 走的是 env,把项目 ID 从 auth 步骤的输出里取(ANTHROPIC_VERTEX_PROJECT_ID: ${{ steps.auth.outputs.project_id }})再配一个 CLOUD_ML_REGION;Foundry 则是 env: ANTHROPIC_FOUNDRY_RESOURCE: your-resource-name,文档说 Claude Code 用这个名字拼出 endpoint URL,凭证则通过 Azure 默认凭证链取到。示例里出现的 --model us.anthropic.claude-sonnet-4-6、claude-sonnet-5 这类值,只是官方文档当时的示例值,可用模型与版本一直在变,别当清单抄。
还有一条不走云厂商也用得上的:想彻底不存长期 secret,文档给了 workload identity federation 的路子,用 anthropic_federation_rule_id(fdrl_...)、anthropic_organization_id,可选的 anthropic_service_account_id(svac_...)和 anthropic_workspace_id(wrkspc_...),并且强调:即使你传了自己的 github_token,联合交换仍然需要 id-token: write。
以上片段均照抄自官方文档示例;若你要把多个参数组合到一份 workflow 里,那是按官方文档中的参数语义组合的示例,未经实测,以官方文档与 --help 的实际输出为准。
五、边界:哪些地方文档明说不保证
- 公开仓库 + fork PR:GitHub 不会把 secret 交给来自 fork 的 PR 触发的运行,所以文档写明那份评审 workflow 只在同仓库分支的 PR 上跑。
- 公开仓库 + 云厂商:文档给了一段 Warning——任何用户发含触发词的评论都会启动 workflow,而生成凭证的步骤跑在写权限检查之前,也就是说未授权用户会在已经签出 App token、已经登录云账号之后才被拒绝,留下审计日志并消耗 Actions 分钟数。官方建议是在凭证步骤之前自己加一步校验评论者写权限。
- 定时任务:GitHub 只从默认分支运行 scheduled workflow;公开仓库中,仓库长时间无活动后该 schedule 会被停用(文档给的是 60 天,这属于 GitHub 侧行为,以 GitHub 文档为准)。
- 纯文本 prompt 默认没工具:文档写明自动化模式下用纯文本 prompt 时,Claude 没有 shell 也没有 GitHub API 访问,要靠
claude_args里的--allowedTools或settings里的permissions.allow规则显式授予;改用 skill 调用时,才可以使用其allowed-toolsfrontmatter 授予的工具。 - 自动评审会主动跳过一批 PR:草稿、已关闭、它判断不需要评审的(如自动生成或改动琐碎的)、以及已经有 Claude 评论的。
- 版本差异:文档写明 v2.1.229 之前,评审只写进 workflow run 日志;v2.1.187 之前,装完 GitHub App 会直接进入 workflow 选择而没有「Skip for now」这一问。老仓库里的 workflow 未必等价于文档现在描述的行为。
- Windows 侧:需要在本机做的只有
gh auth login和claude setup-token两条命令,官方文档没有给出分平台的写法差异;云厂商页与主页的所有 workflow 示例用的都是runs-on: ubuntu-latest,官方文档没有说明 Windows runner 上的情况。往APP_PRIVATE_KEY里贴.pem内容时注意保留换行,这是通用做法而非该产品官方文档内容。
六、怎么验证配对了
文档给的验证动作很朴素:在 issue 或 PR 评论里 @claude 提一句,然后去仓库的 Actions 里看这次运行;Claude 会在同一条 issue 或 PR 下回评论。
没反应的话,按官方排查清单逐条对:GitHub App 是否装在这个仓库上、仓库的 workflows 是否启用、secret 是否已设、评论里的 @claude 是不是一个完整的词(/claude、@claude-bot 都不算)、评论者是否有写权限。鉴权报错时,文档建议先在本地用 claude 验证这份 key 或 token 本身是否有效,再回头查 workflow。
还有一个症状很像「配错了」其实不是:Claude 推的 commit 没触发 CI。文档写明这是 GitHub 的规则——用默认 GITHUB_TOKEN 产生的 commit 不会触发 workflow。处置是把 github_token: ${{ secrets.GITHUB_TOKEN }} 那行去掉,让它以 Claude GitHub App 身份鉴权,或者改传自建 App 的 token。
最后是收尾。要卸干净,文档列的是三件事分别撤:删掉 .github/workflows/ 下引用 anthropics/claude-code-action 的 workflow 文件(快速安装生成的通常叫 claude.yml,选了评审的还有 claude-code-review.yml);删仓库和组织级的 ANTHROPIC_API_KEY / CLAUDE_CODE_OAUTH_TOKEN——注意文档特意提醒,删掉 secret 并不会让凭证本身失效,要作废 API key 得去 Console 里删;最后才是卸载 GitHub App,且仅当你没在用它跑别的 Claude 功能。配过云厂商的,还要删掉对应的 provider secret 和自建 App 的 APP_ID、APP_PRIVATE_KEY。
本文依据 Claude Code 官方文档(code.claude.com/docs)于 2026-08-17 的公开内容整理。
该产品闭源,本文只复述官方文档写明的机制,不推断其内部实现;
我们没有对文中涉及的功能做过实测,因此不涉及界面外观、操作手感与运行速度的任何描述。
该产品迭代频繁,文中涉及的命令、配置项与默认值随版本变动,请以官方文档最新内容为准。
本文不涉及价格、额度与限流的具体数值,相关信息请以官方定价与用量说明页为准。
安全与合规相关做法请结合自身环境评估,本文不构成安全方案建议。