1. 项目概述:这个 action 到底解决什么问题
我平时用 Claude Code 在本地改代码已经成了习惯,打开终端敲一句 prompt 等它生成 diff,确实能省不少事。不过时间一长就冒出个念头:人不可能一直守在终端前面,能不能让这玩意直接在 GitHub 上自己跑起来?比如 PR 一提交,它自动帮我审一遍代码;Issues 一进来,先做一轮初步分类;甚至凌晨两点仓库里的例行维护任务,也可以交给它自己去执行。claude-code-action 做的就是这件事——把 Claude Code 装进 GitHub Actions 的 Runner 沙箱里,以非交互方式执行任务,再把结果以评论、标签或 Pull Request 的形式写回仓库。
这个方案解决的核心痛点是自动化闭环。很多人把 AI 编程工具当成“人的副驾驶”,用完还得自己把改动合并、自己提 PR、自己回评论。而把它搬进 CI 之后,AI 就从“交互式工具”变成了“事件驱动的常驻组员”:GitHub 上有事件发生,它就被唤醒,干完活自动产出结果。我见过有人拿它做 PR 自动审查,有人拿它做 Issue 自动分流,也有人拿它定时生成周报草稿。只要是 GitHub 仓库能触发的事件,理论上都能接。
这篇东西不打算写成官方文档复述,而是把我从配置、调试到踩坑的全过程梳理一遍。适合三类人看:一是被 PR 和 Issue 淹没的开源维护者,二是想给团队 CI 加一个 AI 审查环节的开发者,三是纯粹想折腾自动化、把日常重复劳动外包给模型的人。不管你是第一次听说这个 action 还是已经试到一半,下面这些内容应该都能帮你少走几步弯路。
2. 核心原理拆解:无头模式在 Runner 里怎么干活
2.1 Claude Code 的交互模式与无头模式
很多人第一次用 claude-code-action 时会困惑:Claude Code 不是个终端工具吗?我在本地敲claude命令,它会进入一个交互式 REPL,我一句一句跟它聊,它还能调用工具搜索代码、改文件。这个交互式形态在 CI 里根本跑不起来,因为 GitHub Actions 的 Runner 是个一次性虚拟机,任务跑完就销毁,没有任何人坐在终端前持续输入。
所以 claude-code-action 内部用的其实是 Claude Code 的无头模式,也就是命令行直接传 prompt 的方式。在本地你也可以这么测:claude -p "帮我看看当前目录有什么问题",加上-p参数之后,它不会进入交互界面,而是执行完直接把结果打印到标准输出然后退出。如果再配合--output-format json,输出会变成结构化 JSON,方便程序解析。
这里有个细节值得多说一句:无头模式下,Claude Code 一样可以调用工具修改文件、执行命令。因为 CI 场景里没人会在屏幕前按“允许”,action 通常还要处理权限策略,比如让工具调用自动放行。但自动放行是把双刃剑,后面讲安全边界的时候我会专门展开。
2.2 claude-code-action 内部替你做了哪些事
了解了无头模式,再看这个 action 的工作流程就顺理成章了。它本质上是把“准备环境 + 执行 prompt + 回写结果”这三件事封装成了一个复合 action。你可以想象一下自己在本地手动完成这些步骤的样子:先安装 Claude Code CLI,再配置好 API 密钥,然后进入项目目录执行 prompt,等模型跑完把生成的 diff 保存下来,最后切换分支、提交改动、推到远端、创建 PR。
claude-code-action 就是把这一串动作写进了 action 的逻辑里。它在你指定的工作目录里执行 prompt,执行期间生成的任何文件改动都会留在工作区。工作流里如果你把github_token传给它,它就能用这个 token 以仓库身份创建新分支、推代码、开 PR,或者往现有 PR 上提交评论。
我还想强调一个容易被忽略的前提:这个 action 并不负责把项目代码“喂”给模型。它依赖你事先用actions/checkout把仓库代码拉下来。换句话说,你的工作流文件里必须先用 checkout,再轮到 claude-code-action 去干活。一开始我不知道这个依赖,直接跳过 checkout 跑 action,结果 action 执行时目录是空的,Claude 对着空气分析了半天。这个小细节在 README 里一般会写,但真踩过坑才有体感。
3. 实操配置:从零搭一个能跑起来的 PR 审查工作流
3.1 前置准备:Secrets 与 Token 选型
在写 workflow 之前,有两样东西必须先准备好:Anthropic 的 API 密钥,以及一个有写仓库权限的 token。
API 密钥放在 GitHub 仓库的 Settings -> Secrets and variables -> Actions 里,命名建议用ANTHROPIC_API_KEY。这个 key 会在 action 内部作为环境变量传给 Claude Code。生产环境一定要用独立的 key,不要拿本地调试用的 key 直接灌进去,方便后续分别统计用量、单独做轮换。
token 的选择要看你的使用场景,我整理了一个对比表:
| Token 类型 | 权限范围 | 适用场景 | 注意事项 |
|---|---|---|---|
GITHUB_TOKEN | 仅当前仓库,默认只读 | 单仓库内的审查、评论 | 需要在 workflow 里显式提升permissions |
| 经典 Personal Access Token | 按用户授权跨仓库 | 需要操作多个仓库或创建独立机器人身份 | 权限过大,建议用最小的 repo 范围 |
| Fine-grained PAT | 精确到仓库和权限点 | 团队内共享、生产环境 | 可设置过期时间,比经典 PAT 安全得多 |
我的习惯是第一版先用GITHUB_TOKEN跑通流程,确认没问题之后再考虑换独立的机器人账号 PAT。你要知道默认的GITHUB_TOKEN权限相当有限,如果 workflow 忘了写permissions,action 去 push 分支或创建 PR 时会直接报 403。这是第一次接入时最常见的报错之一。
3.2 最小可用工作流示例
下面给一个我实际在用的、最精简的 PR 审查工作流配置。把它存成.github/workflows/claude-review.yml就能用:
name: claude-code-pr-review on: pull_request: types: [opened, synchronize] permissions: contents: write pull-requests: write jobs: review: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: claude-code-action@v1 with: prompt: | 请审查这个 PR 的代码变更,重点关注: 1. 明显的逻辑错误和空指针风险 2. 安全问题(注入、鉴权缺失等) 3. 是否缺少必要的测试 注意:请用中文回复,不要修改任何文件,直接把审查意见作为评论提交。 github_token: ${{ secrets.GITHUB_TOKEN }} model: claude-sonnet-4-5这里我特意设置了pull_request的opened和synchronize两个触发条件,意思是新 PR 第一次打开、以及后续有新 commit 推进时各自触发一次。contents: write是为了让 action 有能力创建分支和提交文件,pull-requests: write是为了让它能发表评论。如果你只需要评论不需要改代码,contents权限可以收紧,尽量减少不必要的授权面。
3.3 高频参数详解与调参心得
用了几次这个 action 之后,我总结出几个高频参数,几乎每个项目都会用到:
| 参数 | 作用 | 我的建议 |
|---|---|---|
prompt | 给 Claude 的任务指令 | 当成代码来写,越具体越好,最好限定输出格式 |
model | 指定模型版本 | 日常审查用 sonnet 类,复杂重构建议换更强模型但注意成本 |
github_token | 用于身份认证和回写 | 默认GITHUB_TOKEN够用,跨仓库再换 PAT |
max_turns | 控制模型工具调用的最大轮数 | 设置过低会过早结束导致结果不完整,建议 20 起步 |
working_directory | 指定在哪个目录执行 | 大仓库里只跑子项目时很有用 |
debug | 是否输出详细日志 | 排查报错时打开,平时关掉避免日志刷屏 |
max_turns这个参数值得多说两句。Claude Code 在无头模式下可能会为了完成一个任务连续发起多轮工具调用:先搜代码、再读文件、然后修 bug、最后跑测试。如果max_turns设得太小,任务没做完它就提前结束了,你只会看到一份半成品的回复。但设得太大的代价是运行时间暴涨,CI 账单也跟着涨。我一般从 20 开始调,如果日志显示“exceeded max turns”就往上加,直到任务能完整跑完为止。
4. 实战案例:提示词工程与典型场景落地
4.1 让 Claude 自动给 PR 提审查意见
PR 自动审查是我用 claude-code-action 的第一个场景,也是我认为收益最高的场景。设想一个开源项目,每天进来三五个 PR,维护者人工看一遍要 20 分钟。挂上 action 之后,每个 PR 一打开,Claude 就会分析变更内容,把意见直接以评论形式贴在 PR 下面,维护者只需要再复核一遍,效率翻倍不止。
我实际用的审查提示词长这样:
你是一个资深代码审查员。请审查当前 PR 的 diff,注意以下几点: - 只做审查,不要修改任何文件,不要执行可能改变文件内容的命令 - 按严重程度输出:必须修复的问题 / 建议改进 / 风格建议 - 每个问题都要给出文件路径和具体行号 - 使用 Markdown 格式回复这里面最关键的一句话是“只做审查,不要修改任何文件”。我开始没加这句限制,结果审查任务跑完之后,action 自动把 Claude 顺手改的代码提交成了一个新分支,还开了一个多余的 PR。审查场景的正确输出应该是一段评论,而不是一堆代码改动。给 AI 划清行为边界,是提示词工程里最基础也最重要的一课。
另外我推荐在输出格式里明确让它按严重程度分层。如果不限制,Claude 会倾向于把 20 条“问题”平铺出来,其中一半是风格建议,真正致命的逻辑错误反而被淹没。分好级之后,哪怕不看正文,光是看小标题就能快速定位优先级。
4.2 用 Issue 事件做自动分类与分流
第二个我常用场景是 Issue 自动分类。仓库里的 Issue 一旦多起来,光靠人工打 label 就够烦了。claude-code-action 可以做这样一件事:每当有新 Issue 创建,让 Claude 读取标题和正文,判断这是 bug、feature request 还是使用问题,输出一个 JSON 格式的分类结果,然后由后续步骤自动打标签。
这个场景的提示词我写得更死板:
请阅读这个 Issue 的内容,输出一个 JSON 对象,不要输出其他任何文字: {"type": "bug|feature|question|other", "summary": "一句话总结", "priority": "high|medium|low"}注意我限定了“不要输出其他任何文字”。模型偶尔会在 JSON 前后加几句废话,比如“好的,我来分析一下”,这些内容一旦混入,后面对 JSON 的解析步骤就会报错。把输出约束得足够死板,机器才好处理。这个思路同样适用于任何需要把 AI 结果接入自动化流程的场景——AI 的输出不是给人看的,而是给下一个 workflow 步骤解析的,所以宁可呆板一点,也不要让它自由发挥。
接了 Issue 场景之后,我又往前走了一步:让 action 在分类的同时,直接在 Issue 下回复一句初始排查建议。比如分类结果是 bug,它就回复“请在描述中补充复现步骤和运行环境”;分类结果是 feature,它就回复“这个需求听起来有价值,请补充使用场景”。这一步不需要额外编程,只是在 prompt 里加一句指令而已,但给用户的响应速度感知提升非常明显。
4.3 高频报错排查速查表
跑 claude-code-action 的过程中,我整理了一张高频报错表,基本上覆盖了大部分人遇到的坑:
| 报错 / 现象 | 常见原因 | 处理方法 |
|---|---|---|
403或Resource not accessible | GITHUB_TOKEN权限不足 | 在 workflow 顶层补充permissions: contents: write, pull-requests: write |
Invalid API Key | Secrets 没传或者 key 不对 | 检查ANTHROPIC_API_KEY是否在 action 的env或输入里正确传递 |
exit code 1且没有任何输出 | prompt 为空或模型调用失败 | 本地先跑claude -p "test"验证 key,再检查 prompt 是否过滤了特殊字符 |
push 时提示already exists | 相同名字的分支之前已经创建过 | 换一个新的分支名,或先删除已有分支后重新跑 |
| Job 卡住直到超时 | max_turns过大,任务一直不结束 | 设置较小的max_turns,同时给 job 加timeout-minutes |
| 目录为空,Claude 什么都没分析 | 忘了actions/checkout@v4 | 在 claude-code-action 之前先 checkout 仓库 |
| 模型输出无法解析 | JSON 前后混入解释文字 | 在 prompt 里严格限定输出格式,并声明“不要输出其他文字” |
这里面最容易被忽视的是分支名冲突。action 每次跑都会尝试把改动提交到一个新分支,如果上一次跑因为某种原因没有成功创建 PR,但分支留在远端了,下一次跑同一名字就会报冲突。解决方法很简单:每次运行前先删除旧分支,或者把分支名带上时间戳。我现在倾向于让 prompt 尽量少改文件,从源头减少需要 push 分支的次数。
5. 工程化落地心得:从“能跑”到“跑得稳”
5.1 把 Prompt 当成代码来管理
第一次写提示词的时候,我直接硬编码在 workflow 的with.prompt里。很快问题就来了:提示词越写越长,YAML 里塞了一大段文本,换行和缩进稍微出错就影响整个 workflow 的语法。后来我改成把所有 prompt 存到仓库的.github/prompts/目录下,一个场景一个文件,workflow 里用prompt_file之类的参数引用。
这样做有三个好处。第一是可版本化,prompt 改动了会走正常的 PR review 流程,团队里谁都能看到改动记录,不会出现“工作流悄悄变了但没人知道”的情况。第二是可复用,审查、分类、周报三个场景的 prompt 互相独立,哪个场景需要调整也不会动到其他部分。第三是可测试,我把 prompt 文件放在本地,先用 Claude Code 的无头模式跑一遍调稳定,确认输出质量之后再同步到 CI 里去跑,等于给 prompt 加了一道“上线前测试”。
5.2 限权、并发与安全边界
在这个 action 上我学到最深刻的一条安全教训是:绝对不要让 AI 拥有修改 workflow 文件本身的权限。Claude 在执行 prompt 的时候如果被要求“修复仓库问题”,它有可能发现 workflow 配置“不够完善”,然后顺手改掉.github/workflows/下面的文件。如果 action 有权限把改动推回仓库并创建 PR,这个 PR 里就包含了对 CI 配置的修改。虽然未必是恶意的,但一旦 AI 被未来某次 prompt 注入诱导,这个权限链就可能被滥用。
我的做法是在 prompt 里明确禁止读取和修改.github/目录。如果模型在处理过程里还想往.github/写文件,就说明它没有认真遵守指令,这时候我们直接看 CI 日志就能发现,及时调整 prompt。
并发问题同样值得提防。如果同一个分支有两个 workflow 实例同时跑,它们都会尝试创建同名分支和 PR,必然有一个会失败。GitHub Actions 提供了concurrency配置,可以在 workflow 顶层加上并发限制,让同一时间只有一个实例在跑:
concurrency: group: claude-${{ github.ref }} cancel-in-progress: false我建议cancel-in-progress不要设成true。因为 AI 任务跑到一半被取消,会浪费掉之前消耗的 token,而且拿不到任何可用结果。让它排队等前一个跑完,虽然慢一点,但至少每个任务都有完整的产出。
5.3 成本控制与资源管理
凡是把大模型接进 CI,成本都是一个绕不开的话题。claude-code-action 每次触发都会消费 Anthropic API 的 token,尤其是在长任务里,每一次工具调用背后都是一次模型推理。跑一晚上定时任务,成本可能会超出你的预期。
我的成本控制思路是“能少跑就少跑”。入口第一道闸是路径过滤。比如 PR 只改了 README 文档,这会触发审查吗?没必要。在on.pull_request下加一条paths,只对src/或app/目录的变更触发 action,能直接砍掉一票无效调用。第二道闸是条件过滤,比如基于 event 的内容再判断一次:如果 PR 标题带[skip ci]之类的标记,就让 job 提前退出,给开发者留一条绕过 AI 的逃生通道。
时长管理也同样重要。我会在每个 job 上设置timeout-minutes: 10,避免某个奇怪任务把 Runner 拖死。max_turns控制在 20 到 30 之间,既给模型足够的执行空间,也给它一个明确的截止边界。我自己跑下来的经验是,多数 PR 审查任务在 10 轮工具调用之内已经能完成,超过 20 轮还没结束的,大概率是模型已经开始在无关文件上反复试探了。
结尾
把 claude-code-action 接入 CI 之后,我明显感觉自己的开发节奏变了。以前盯 PR、回 Issue 是碎片时间里最耗神的事情,现在它成了“给 AI 复核结果”的轻量动作。模型不一定每次都想得全面,但它能保证 24 小时在线、永远不烦,这已经是人类维护者做不到的优势了。
最后再分享一个我自己的调试技巧:每次准备上一个新的 prompt 场景,都先在本地用claude -p "你的提示词" --output-format json跑一遍,确认模型输出稳定、格式正确,再把这段 prompt 同步进仓库的.github/prompts/目录、让 CI 去跑。不要跳过去直接改 workflow 上生产,AI 的输出不可控性比你想象得高,多一步本地验证能省下大量的 workflow 调试时间。等你把这套流程跑顺了,你会和我一样开始思考下一个问题——既然审查和分类都能自动化,还有哪些重复劳动可以顺手丢给它?