| name: Claude Code |
| |
| on: |
| issue_comment: |
| types: [created] |
| pull_request_review_comment: |
| types: [created] |
| issues: |
| # only "opened" — an issue's author_association gates the summon below; |
| # "assigned" would gate on the issue author, not the assigner, so a |
| # maintainer assigning an outsider's issue would be wrongly skipped. |
| types: [opened] |
| pull_request_review: |
| types: [submitted] |
| |
| jobs: |
| claude: |
| # Only trusted actors (repo owner/member/collaborator) may summon @claude, so the |
| # write-scoped token and OAuth secret are never issued for an outside contributor's |
| # comment on this public repo. Defense-in-depth on top of the action's own check. |
| if: | |
| (github.event_name == 'issue_comment' && contains(github.event.comment.body, '@claude') && |
| contains(fromJSON('["OWNER", "MEMBER", "COLLABORATOR"]'), github.event.comment.author_association)) || |
| (github.event_name == 'pull_request_review_comment' && contains(github.event.comment.body, '@claude') && |
| contains(fromJSON('["OWNER", "MEMBER", "COLLABORATOR"]'), github.event.comment.author_association)) || |
| (github.event_name == 'pull_request_review' && contains(github.event.review.body, '@claude') && |
| contains(fromJSON('["OWNER", "MEMBER", "COLLABORATOR"]'), github.event.review.author_association)) || |
| (github.event_name == 'issues' && (contains(github.event.issue.body, '@claude') || contains(github.event.issue.title, '@claude')) && |
| contains(fromJSON('["OWNER", "MEMBER", "COLLABORATOR"]'), github.event.issue.author_association)) |
| runs-on: ubuntu-latest |
| permissions: |
| contents: write # allow Claude to push commits/branches when asked |
| pull-requests: write # allow Claude to comment on / update PRs |
| issues: write # allow Claude to comment on / update issues |
| id-token: write |
| actions: read # Required for Claude to read CI results on PRs |
| steps: |
| - name: Checkout repository |
| uses: actions/checkout@v6 |
| with: |
| fetch-depth: 1 |
| |
| - name: Run Claude Code |
| id: claude |
| uses: anthropics/claude-code-action@v1 |
| with: |
| claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }} |
| |
| # This is an optional setting that allows Claude to read CI results on PRs |
| additional_permissions: | |
| actions: read |
| |
| # Sign the bot's commits so they show as "Verified". The action commits |
| # automatically — on a PR comment it pushes to that PR's branch; on an |
| # issue comment it opens a new claude/* branch + PR with the fix. |
| use_commit_signing: true |
| |
| # No custom prompt: Claude performs the instructions in the @claude comment. |
| |
| # Deliberately NO Bash in the tool allowlist. @claude can be summoned on a |
| # fork PR, and this job holds the OAuth secret + a write token. Any build |
| # or interpreter command (python -c, cmake/make custom targets, etc.) run |
| # against attacker-controlled PR content is arbitrary code + network |
| # execution, so no command allowlist can safely contain it. Claude edits |
| # files and the action commits/opens the PR; the resulting commit is |
| # verified by the repo's CircleCI matrix. --max-turns gives room to |
| # investigate + fix. |
| claude_args: '--max-turns 30 --model claude-opus-5' |