name: Claude Code on: issue_comment: types: [created] pull_request_review_comment: types: [created] issues: types: [opened, assigned, labeled] pull_request_review: types: [submitted] jobs: # Standard Claude trigger - responds to @claude mentions claude: if: | (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' && (github.event.action == 'opened' || github.event.action == 'assigned') && (contains(github.event.issue.body, '@claude') || contains(github.event.issue.title, '@claude'))) runs-on: ubuntu-latest permissions: contents: write # Push branches, create commits pull-requests: write # Create and manage PRs issues: write # Manage labels, close issues id-token: write actions: read # Read CI results on PRs steps: - name: Checkout repository uses: actions/checkout@v4 with: fetch-depth: 1 - name: Run Claude Code id: claude uses: anthropics/claude-code-action@v1 env: NPM_TOKEN: ${{ secrets.NPM_TOKEN }} CRON_SECRET: ${{ secrets.CRON_SECRET }} with: claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }} additional_permissions: | actions: read # Label-triggered Claude - for tool-request pipeline claude-label-trigger: if: github.event_name == 'issues' && github.event.action == 'labeled' && github.event.label.name == 'claude-working' runs-on: ubuntu-latest permissions: contents: write pull-requests: write issues: write id-token: write actions: read steps: - name: Checkout repository uses: actions/checkout@v4 with: fetch-depth: 1 - name: Get prompt from issue comments id: get-prompt uses: actions/github-script@v7 with: script: | const comments = await github.rest.issues.listComments({ owner: context.repo.owner, repo: context.repo.repo, issue_number: context.issue.number, per_page: 100 }); // Find the most recent comment with @claude const claudeComments = comments.data.filter(c => c.body.includes('@claude')); if (claudeComments.length > 0) { const latestComment = claudeComments[claudeComments.length - 1]; core.setOutput('prompt', latestComment.body); core.setOutput('found', 'true'); } else { core.setOutput('found', 'false'); core.setFailed('No @claude comment found in issue'); } - name: Run Claude Code if: steps.get-prompt.outputs.found == 'true' uses: anthropics/claude-code-action@v1 env: NPM_TOKEN: ${{ secrets.NPM_TOKEN }} CRON_SECRET: ${{ secrets.CRON_SECRET }} with: claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }} additional_permissions: | actions: read prompt: ${{ steps.get-prompt.outputs.prompt }} # Allow gh CLI for issue management, npm for publishing claude_args: '--allowedTools "Bash(gh:*)" "Bash(npm:*)" "Bash(pnpm:*)" "Bash(git:*)"'