前置条件
- 你是目标 repo 的 admin
- 已有 Anthropic API Key(或 AWS Bedrock 凭证)
- 申请 Anthropic API Key 可以使用
claude setup-token 命令,得到一个 sk 开头的 key
方式一:安装官方 Claude App(最快)
- 打开 https://github.com/apps/claude,点击 Install
- 选择你要授权的 repo(建议只勾选需要的 repo,不要 All repositories)
- 确认安装
安装完成后跳到下面的「配置 Secrets 和 Workflow」章节。
方式二:创建自定义 GitHub App(完全掌控权限)
适用场景:组织策略不允许装第三方 App、需要更严格的权限控制、使用 AWS Bedrock / Vertex AI。
A)快速创建(推荐)
- 从 https://github.com/anthropics/claude-code-action/blob/main/docs/create-app.html 右键「另存为」下载
create-app.html - 用浏览器打开这个文件
- 个人账号:点击「Create App for Personal Account」
- 组织账号:输入组织名称,点击「Create App for Organization」
- GitHub 会展示 App 配置预览 → 确认名称 → 点击 Create GitHub App
- 创建后自动跳转到 App 设置页,往下滚到 Private keys → 点 Generate a private key → 下载
.pem 文件(妥善保管) - 跳到下面的「安装 App 到 Repo」步骤
B)手动创建
- 打开 https://github.com/settings/apps(个人)或组织的 Settings → Developer settings → GitHub Apps
- 点 New GitHub App,配置以下权限:
| 权限类别 | 权限项 | 级别 |
|---|
| Repository permissions | Contents | Read & Write |
| Repository permissions | Issues | Read & Write |
| Repository permissions | Pull requests | Read & Write |
| Account permissions | 无 | — |
- 「Where can this GitHub App be installed?」选 Only on this account
- 点 Create GitHub App
- 创建完成后,滚到 Private keys → Generate a private key → 下载
.pem 文件
安装 App 到 Repo
- 进入你刚创建的 App 设置页
- 左侧菜单点 Install App
- 选择要安装的 repo,确认
配置 Secrets 和 Workflow
第一步:添加 Repository Secrets
进入 repo → Settings → Secrets and variables → Actions → New repository secret
| Secret 名称 | 值 |
|---|
ANTHROPIC_API_KEY | 你的 Anthropic API Key(sk-ant- 开头) |
CLAUDE_CODE_OAUTH_TOKEN(可选,替代上一条) | 用 claude setup-token 生成的 OAuth Token |
APP_ID(自定义 App 才需要) | App 设置页里的 App ID |
APP_PRIVATE_KEY(自定义 App 才需要) | .pem 文件的完整内容 |
⚠️ 绝对不要把 API Key 写在代码里,只通过 Secrets 引用。
ANTHROPIC_API_KEY 和 CLAUDE_CODE_OAUTH_TOKEN 二选一即可,下面示例以 API Key 为主,OAuth 用法是把 anthropic_api_key: 换成 claude_code_oauth_token:。
第二步:创建 Workflow 文件
在 repo 中创建 .github/workflows/claude.yml:
如果用官方 Claude App:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54
| name: Claude Assistant on: issue_comment: types: [created] pull_request_review_comment: types: [created] pull_request_review: types: [submitted] issues: types: [opened, assigned]
permissions: contents: write pull-requests: write issues: write id-token: write actions: read
jobs: claude-response: if: | github.actor == '你的用户名' && ( (github.event_name == 'issue_comment' && contains(github.event.comment.body, '@claude')) || (github.event_name == 'pull_request_review_comment' && contains(github.event.comment.body, '@claude')) || (github.event_name == 'pull_request_review' && contains(github.event.review.body, '@claude')) || (github.event_name == 'issues' && (contains(github.event.issue.body, '@claude') || contains(github.event.issue.title, '@claude'))) ) runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 with: fetch-depth: 1
- uses: anthropics/claude-code-action@v1 with: anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }} include_comments_by_actor: "你的用户名" claude_args: | --max-turns 30 --allowedTools "WebFetch,WebSearch,Edit,Write,Read,Glob,Grep,TodoWrite,Bash(git:*),Bash(gh:*),Bash(npm:*),Bash(pnpm:*),Bash(yarn:*),Bash(npx:*),Bash(node:*),Bash(curl:*),Bash(jq:*),Bash(rg:*),Bash(fd:*)"
|
如果用自定义 GitHub App:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45
| name: Claude with Custom App on: issue_comment: types: [created] pull_request_review_comment: types: [created] pull_request_review: types: [submitted] issues: types: [opened, assigned]
permissions: contents: write pull-requests: write issues: write id-token: write actions: read
jobs: claude-response: if: | github.actor == '你的用户名' && ( (github.event_name == 'issue_comment' && contains(github.event.comment.body, '@claude')) || (github.event_name == 'pull_request_review_comment' && contains(github.event.comment.body, '@claude')) || (github.event_name == 'pull_request_review' && contains(github.event.review.body, '@claude')) || (github.event_name == 'issues' && (contains(github.event.issue.body, '@claude') || contains(github.event.issue.title, '@claude'))) ) runs-on: ubuntu-latest steps: - name: Generate GitHub App token id: app-token uses: actions/create-github-app-token@v1 with: app-id: ${{ secrets.APP_ID }} private-key: ${{ secrets.APP_PRIVATE_KEY }}
- uses: anthropics/claude-code-action@v1 with: anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }} github_token: ${{ steps.app-token.outputs.token }} include_comments_by_actor: "你的用户名" claude_args: | --max-turns 30 --allowedTools "WebFetch,WebSearch,Edit,Write,Read,Glob,Grep,TodoWrite,Bash(git:*),Bash(gh:*),Bash(npm:*),Bash(pnpm:*),Bash(yarn:*),Bash(npx:*),Bash(node:*),Bash(curl:*),Bash(jq:*),Bash(rg:*),Bash(fd:*)"
|
Public Repo 安全清单
-
if 用 actor 白名单(github.actor == '你的用户名'),不要只用”排除 bot”的黑名单 -
if 再叠一层 contains(<事件正文>, '@claude') 判断——没有触发词直接 skip,省 Action 额度也避免被误触 -
include_comments_by_actor 同步设置用户白名单(注意:它只过滤评论,不一定覆盖 issue body / PR description,所以上面两条 if 校验是必须的纵深防御) - 顶层
permissions: 块按需最小化授权——只读场景 contents/pull-requests/issues 都给 read 即可;要提 PR 才给 write -
claude_args 里 Bash 不要裸开——用 Bash(git:*),Bash(gh:*),... 这种命令前缀白名单收紧 -
allowed_bots 保持默认空值(不要设 *) -
show_full_output 保持默认 false - API Key / OAuth Token 只通过
${{ secrets.XXX }} 引用,不硬编码 - 定期轮换 API Key
- 意识到一旦 actor 校验被绕过,攻击者拿到的就是 workflow
permissions 里授予的全部能力——所以前两条最关键
验证
配置完成后,在 issue 里评论 @claude 你好,如果一切正常,Claude 会在几秒内回复。
参考文档:https://github.com/anthropics/claude-code-action