GitHub Actions
Run Claude Code inside GitHub Actions with claude-code-action, from @claude mentions on issues and PRs to scheduled jobs and skill-driven reviews.
anthropics/claude-code-action is a GitHub Action that runs Claude Code inside your workflows. Tag @claude on an issue or pull request and it reads the code, makes changes and pushes commits. Give it a prompt instead and it runs unattended on any GitHub event: a cron schedule, a new PR, a release.
Several things share the Claude Code name, so to be clear about scope:
- This page: the workflow integration you configure with YAML in your repo.
- Code Review: managed automatic PR review, no workflow file needed.
- Claude Code on the web: cloud sessions you drive yourself.
- Agent SDK: build your own automation; the action is built on it.
- GitHub Enterprise Server: self-hosted GitHub.
Setup
Either path needs admin access to the repository.
The quick way: /install-github-app
This only works for github.com remotes; on gitlab.com or bitbucket.org it prints a notice and exits (see GitLab CI/CD). Install the GitHub CLI and run gh auth login first.
In the repository, start claude and run:
/install-github-app
It then:
- Installs the Claude GitHub App. (You can choose Skip for now after this step and come back later.)
- Sets up a credential. If Claude Code already has an API key it reuses it, and offers to keep an existing
ANTHROPIC_API_KEYsecret. Otherwise you choose between a long-lived token from your Claude subscription or pasting an API key. The secret is saved asANTHROPIC_API_KEYorCLAUDE_CODE_OAUTH_TOKEN. - Pushes a branch containing the workflows you picked, wired to that secret, and opens GitHub with the PR ready to create.
Merge the PR and @claude works. Press Esc to stop partway; whatever step is running finishes, nothing after it starts, and the closing message lists what was already done.
If you choose the review workflow, Claude posts its review on the PR (inline comments per issue, or a single summary comment when it finds none) and skips some PRs such as drafts. Versions before v2.1.229 only wrote the review to the run log. To upgrade an older generated review workflow, either rerun /install-github-app and choose Update workflow file with latest version (new branch and PR), or add --comment and the claude_args line from the review example below to your existing file by hand.
Quick setup supports the Claude API and Claude subscriptions. For Bedrock, Agent Platform or Foundry, see GitHub Actions with cloud providers.
The manual way
-
Install the Claude GitHub App on the repository. The action uses three of its permissions: Contents, Issues and Pull requests, all read and write.
-
Add one secret:
ANTHROPIC_API_KEY: an API key from the Claude Console; orCLAUDE_CODE_OAUTH_TOKEN: a subscription token (Pro, Max, Team, Enterprise) created locally withclaude setup-token. See authentication.
Pass it via the
anthropic_api_keyorclaude_code_oauth_tokeninput respectively. -
Add a workflow under
.github/workflows/. The action's repository has a ready-madeexamples/claude.yml, or use the one below.
Test by commenting @claude on an issue.
Rolling out across an organisation
- Install the app once at organisation level, for all or selected repos.
- Store the credential as an organisation Actions secret. Use a Console API key here: an OAuth token is tied to whoever ran
claude setup-token. - Add the workflow to each repo, or write it once as a reusable workflow and call it.
To avoid long-lived secrets altogether, use workload identity federation: the action trades the job's GitHub OIDC token for Claude API access via a Console service account. Set:
| Input | Value |
|---|---|
anthropic_federation_rule_id | The rule ID, fdrl_... |
anthropic_organization_id | Your Anthropic organisation ID |
anthropic_service_account_id | Optional, svac_... (the rule already targets one) |
anthropic_workspace_id | Optional, wrkspc_... (needed only if the rule spans several workspaces) |
and grant id-token: write, which the exchange needs even if you supply your own github_token. The Console-side steps are in the action repository's setup guide. For security reviews, see data usage and security.
Removing it
- Delete workflows using
anthropics/claude-code-action(quick setup createdclaude.ymland possiblyclaude-code-review.yml). - Delete the
ANTHROPIC_API_KEYorCLAUDE_CODE_OAUTH_TOKENsecret at repo and org level. Deleting a secret does not revoke it; delete API keys in the Console too. - Uninstall the Claude GitHub App only if nothing else uses it (Code Review and web auto-fix do).
- If you used a cloud provider, remove those secrets (
AWS_ROLE_TO_ASSUME,GCP_*,AZURE_*) and any custom app with itsAPP_IDandAPP_PRIVATE_KEY.
What the app is allowed to do
One Claude GitHub App serves the action, Code Review and cloud auto-fix, so its permission set is wider than the action needs:
| Permission | Access |
|---|---|
| Actions | Read and write |
| Administration | Read |
| Checks | Read and write |
| Contents | Read and write |
| Discussions | Read and write |
| Issues | Read and write |
| Members | Read |
| Merge queues | Read |
| Metadata | Read |
| Pull requests | Read and write |
| Repository hooks | Read and write |
| Statuses | Read |
| Workflows | Read and write |
GitHub only lets you accept the whole set. When the app later asks for a new or wider permission (for example Actions moving from read to write so it can re-run workflows), the account or org owner must approve it, and the install keeps its old permissions until then. If policy demands least privilege, create your own GitHub App with just Contents, Issues and Pull requests (see the action's setup guide). A custom app only covers the action; Code Review and web auto-fix still need the official one.
How it decides what to do
| Mode | When | Output |
|---|---|---|
| Interactive | No prompt input. Waits for the trigger phrase (@claude by default) in an issue or PR comment, a PR review, or a new issue's title or body | A comment on the issue or PR, updated as it works |
| Automation | A prompt input is set. Runs on whatever event fires the workflow | The run log, unless the prompt tells Claude to post and it has a tool to do so |
Who can trigger it
Two checks run before Claude starts; if either fails, the run fails:
- Write access. On issue and PR events the actor needs write access. To allow particular users without it, set
allowed_non_write_usersand pass your owngithub_token. Events with no human author, likeschedule, skip this. - Human actor. Bots are rejected unless listed in
allowed_bots, which prevents loops. This applies to scheduled runs too, which GitHub attributes to whoever last edited the cron; if that was a bot, list it.
Workflows
The examples use an API key. With a subscription token, swap the anthropic_api_key line for claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}.
Answer @claude mentions
name: claude-on-mention
on:
issue_comment:
types: [created]
pull_request_review_comment:
types: [created]
issues:
types: [opened]
jobs:
respond:
if: >
contains(github.event.comment.body, '@claude') ||
contains(github.event.issue.body, '@claude')
runs-on: ubuntu-latest
timeout-minutes: 30
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 }}
claude_args: "--max-turns 15"
Why the non-obvious bits are there:
id-token: writeis needed for the action's default GitHub App authentication.actions: readlets Claude read CI results on PRs.actions/checkoutgives Claude a working copy.- The
ifsaves runner minutes on comments that do not mention Claude (the action double-checks anyway).
Then, on any issue or PR:
@claude the CSV export drops rows with a null region. Add a failing test, then fix it.
@claude why does this migration lock the orders table? Suggest a safer approach.
Run a skill as the prompt
prompt accepts a skill invocation:
- For a skill in the repo's
.claude/skills/, check the repo out first, then use/skill-name. - For a plugin skill, install it with
plugin_marketplacesandplugins(formatplugin-name@marketplace-name, where the marketplace name comes from its manifest, not its URL), then use/plugin-name:skill-name.
This review workflow installs the code-review plugin and runs it on PR activity, the same plugin quick setup uses:
name: pr-review
on:
pull_request:
types: [opened, synchronize, ready_for_review, reopened]
jobs:
review:
runs-on: ubuntu-latest
concurrency:
group: review-${{ github.event.pull_request.number }}
cancel-in-progress: true
permissions:
contents: read
pull-requests: read
issues: read
id-token: write
steps:
- uses: actions/checkout@v6
with:
fetch-depth: 1
- uses: anthropics/claude-code-action@v1
with:
anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}
plugin_marketplaces: "https://github.com/anthropics/claude-code.git"
plugins: "code-review@claude-code-plugins"
prompt: "/code-review:code-review --comment ${{ github.repository }}/pull/${{ github.event.pull_request.number }}"
claude_args: '--allowedTools "mcp__github_inline_comment__create_inline_comment"'
Two lines decide where the review goes:
--commentmakes Claude post on the PR (inline per issue, or one summary when clean). Without it, findings stay in the run log.claude_argswith--allowedToolsmust name the inline comment tool even though the skill's frontmatter already does, because the action only starts that MCP server when--allowedToolsinclaude_argsmentions it.
Claude skips drafts, closed PRs, PRs it judges not worth reviewing (bots, trivial changes) and PRs it has already commented on. On public repos, GitHub withholds secrets from fork-triggered runs, so this only reviews same-repo branches. For zero-maintenance reviews, the managed Code Review is simpler.
Run on a schedule
With a plain-text prompt in automation mode, Claude has no shell or GitHub API access until you grant tools, via --allowedTools in claude_args or a permissions.allow rule in the settings input. A skill prompt can use whatever its allowed-tools frontmatter grants. GitHub runs schedules from the default branch only, and on public repos disables them after 60 days with no activity.
A weekly stale-issue sweep that reads and comments via GitHub MCP tools, so no checkout is needed:
name: weekly-issue-sweep
on:
schedule:
- cron: "30 7 * * 1" # Mondays 07:30 UTC
workflow_dispatch:
jobs:
sweep:
runs-on: ubuntu-latest
timeout-minutes: 20
permissions:
contents: read
issues: write
id-token: write
steps:
- uses: anthropics/claude-code-action@v1
with:
anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}
prompt: |
List open issues with no activity in 30 days. For each, add a short comment
asking the reporter whether it is still relevant. Skip anything labelled "pinned".
claude_args: |
--model claude-sonnet-5
--max-turns 20
--allowedTools "mcp__github__list_issues,mcp__github__add_issue_comment"
Good habits
Put house rules in CLAUDE.md. Style, review criteria and patterns in the repository root are read on every run. Keep it tight, since it is loaded every time. See memory.
Keep credentials in secrets.
Warning: Never commit an API key or OAuth token. Reference secrets, for example
anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}.
Give each workflow the minimum permissions it needs and review Claude's changes before merging. The action's repository has its own security notes.
Watch costs. Each run spends GitHub Actions minutes on hosted runners and model tokens (or subscription usage with an OAuth token). To keep both down:
- write specific requests so fewer turns are needed;
- use issue templates to front-load context;
- cap work with
--max-turns; - set
timeout-minuteson jobs; - use
concurrencygroups to stop pile-ups.
See costs, analytics and monitoring.
Cloud providers
By default the action calls the Claude API. To run inference in your own cloud account, set one of:
| Provider | Input |
|---|---|
| Amazon Bedrock | use_bedrock: "true" |
| Google Cloud's Agent Platform | use_vertex: "true" |
| Microsoft Foundry | use_foundry: "true" |
All three authenticate with OIDC federation, so no static cloud keys live in the repo. Full walkthroughs are in GitHub Actions with cloud providers.
Inputs reference
The commonly used with: inputs:
| Input | Purpose | Required |
|---|---|---|
prompt | Plain text or a skill invocation. Omit for interactive mode | No |
claude_args | Any Claude Code CLI arguments | No |
anthropic_api_key | Claude API key | For the Claude API, unless you use an OAuth token or federation; not for cloud providers |
claude_code_oauth_token | Subscription token from claude setup-token | No |
github_token | Token for GitHub operations; defaults to the Claude GitHub App | No |
plugin_marketplaces | Newline-separated marketplace Git URLs | No |
plugins | Newline-separated plugins to install | No |
settings | Claude Code settings as JSON or a path to a JSON file | No |
trigger_phrase | Defaults to @claude | No |
use_bedrock / use_vertex / use_foundry | Route through a cloud provider | No |
The full list is in the action repository's usage docs.
Useful claude_args:
| Argument | Effect |
|---|---|
--max-turns | Cap the number of turns |
--model | Choose a model, e.g. claude-sonnet-5; otherwise the Claude Code default |
--mcp-config | Path to an MCP config |
--allowedTools (or --allowed-tools) | Comma-separated tools to allow |
--debug | Verbose debug output |
Troubleshooting
@claude gets no response.
- Is the app installed on this repo, and are Actions enabled?
- Is the secret set?
- Is it exactly
@claudeas a whole word (not/claudeor@claude-bot)? - Does the commenter have write access (or appear in
allowed_non_write_users)?
CI does not run on Claude's commits. GitHub does not trigger workflows for commits made with the default GITHUB_TOKEN. If you pass github_token: ${{ secrets.GITHUB_TOKEN }}, remove it so the action uses the Claude GitHub App, or supply a custom app token. Also check your CI triggers include push or pull_request.
Authentication errors. Test the key or token locally with claude first. For cloud providers, see the cloud provider troubleshooting.
The action repository also has a FAQ.
Upgrading from @beta
- Change
anthropics/claude-code-action@betato@v1. - Delete the
modeinput; mode is detected automatically. - Rename
direct_prompttoprompt. - Move CLI options such as
max_turnsandmodelintoclaude_args.custom_instructionsbecomes--append-system-prompt.