# Claude Code Github Workflows

> Claude Code GitHub Actions workflow patterns — PR reviews, issue triage, CI/CD integration. Use when creating or modifying workflows that integrate Claude Code.

- Skill: `laurigates/claude-code-github-workflows` (Agent Skill)
- Install (CLI): `npx skillmds@latest add laurigates/claude-code-github-workflows`
- Raw SKILL.md: https://api.skillmd.com/api/skills/laurigates/claude-code-github-workflows/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: DevOps & Infra
- Author: laurigates (https://skillmd.com/u/laurigates)
- Updated: 2026-09-09
- Page: https://skillmd.com/skills/laurigates/claude-code-github-workflows

---


# Claude Code GitHub Workflows

## When to Use This Skill

| Use this skill when... | Use the linked sibling instead when... |
|---|---|
| Designing a new `anthropics/claude-code-action@v1` workflow (PR review, issue triage, CI auto-fix) | Configuring the auth method or hardening permissions — see github-actions-auth-security |
| Choosing trigger events (`issue_comment`, `pull_request`, `workflow_run`) and `if:` guards | Wiring MCP servers and `--allowedTools` patterns — see github-actions-mcp-config |
| Adding path filters, custom trigger phrases, or external-contributor flows | Debugging a failing workflow run — see github-actions-inspection |
| Authoring the `prompt:` block (review focus areas, triage labelling, auto-fix instructions) | Building a self-hosted reusable auto-fix workflow — see github-workflow-auto-fix `--reusable` |

Expert knowledge for designing GitHub Actions workflows that integrate Claude Code for automated code assistance, PR reviews, and issue triage.

## Core Expertise

**Workflow Design Patterns**
- Automated pull request reviews with inline comments
- Issue triage and automated responses
- CI failure auto-fix workflows
- Custom trigger configurations and event handling

**Trigger Configurations**
- Issue comment triggers (`@claude` mentions)
- Pull request events (opened, synchronize, ready_for_review)
- Workflow run triggers (CI failure handling)
- Path-filtered reviews for specific directories

## Display name convention

Every workflow's `name:` follows `<Domain>: <Action> [<target>]` (quoted, since YAML treats `:` as a key separator). Use the `Claude:` domain for Claude Code-driven workflows; use `Auto-fix:` for `workflow_run`-triggered remediation. See `.claude/rules/workflow-naming.md` for the canonical rule and active domains. The example snippets below dogfood the convention.

When a workflow's `on.workflow_run.workflows` lists another workflow's display name, the listed string must match the target workflow's `name:` exactly — update both sides in the same change.

## Essential Workflow Template

```yaml
name: "Claude: @mentions"

on:
  issue_comment:
    types: [created]
  pull_request_review_comment:
    types: [created]
  issues:
    types: [opened, assigned]

jobs:
  claude:
    if: |
      (github.event_name == 'issue_comment' && contains(github.event.comment.body, '@claude')) ||
      (github.event_name == 'issues' && contains(github.event.issue.body, '@claude'))
    runs-on: ubuntu-latest
    permissions:
      contents: write
      pull-requests: write
      issues: write
      id-token: write
      actions: read
    steps:
      - name: Checkout repository
        uses: actions/checkout@v5
        with:
          fetch-depth: 1

      - name: Run Claude Code
        uses: anthropics/claude-code-action@v1
        with:
          anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}
```

## Automation Patterns

### Comprehensive PR Review
```yaml
name: "Claude: PR review"

on:
  pull_request:
    types: [opened, synchronize, ready_for_review, reopened]

jobs:
  review:
    runs-on: ubuntu-latest
    permissions:
      contents: write
      pull-requests: write
      id-token: write
    steps:
      - uses: actions/checkout@v5
      - uses: anthropics/claude-code-action@v1
        with:
          anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}
          track_progress: true
          prompt: |
            Review this PR focusing on:
            1. Code Quality
            2. Security
            3. Performance
            4. Testing
            5. Documentation
```

### CI Failure Auto-Fix
```yaml
name: "Auto-fix: CI failures"

on:
  workflow_run:
    # The string here must match the target workflow's `name:` exactly.
    workflows: ["Test: Suite"]
    types: [completed]

jobs:
  auto-fix:
    if: github.event.workflow_run.conclusion == 'failure'
    runs-on: ubuntu-latest
    permissions:
      contents: write
      pull-requests: write
      actions: read
    steps:
      - uses: actions/checkout@v5
      - uses: anthropics/claude-code-action@v1
        with:
          anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}
          prompt: |
            The CI workflow failed. Please:
            1. Analyze the failure logs
            2. Identify the root cause
            3. Implement a fix
            4. Create a PR with the fix
```

### Issue Triage and Labeling
```yaml
name: "Claude: Issue triage"

on:
  issues:
    types: [opened]

jobs:
  triage:
    runs-on: ubuntu-latest
    permissions:
      issues: write
    steps:
      - uses: anthropics/claude-code-action@v1
        with:
          anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}
          prompt: |
            Analyze this issue and:
            1. Add appropriate labels (bug, feature, documentation, etc.)
            2. Suggest a priority level
            3. Recommend assignment if obvious
            4. Ask clarifying questions if needed
```

### Path-Filtered PR Review
```yaml
name: "Claude: Review backend changes"

on:
  pull_request:
    paths:
      - 'backend/**'
      - 'api/**'

jobs:
  review:
    runs-on: ubuntu-latest
    permissions:
      contents: write
      pull-requests: write
    steps:
      - uses: actions/checkout@v5
      - uses: anthropics/claude-code-action@v1
        with:
          anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}
          prompt: |
            Review backend changes focusing on:
            - API design and RESTful principles
            - Database query optimization
            - Error handling and logging
            - Security vulnerabilities
```

### Custom Trigger Phrase
```yaml
name: "Claude: Custom trigger"

on:
  issue_comment:
    types: [created]

jobs:
  claude:
    if: contains(github.event.comment.body, '/claude-review')
    runs-on: ubuntu-latest
    permissions:
      contents: write
      pull-requests: write
      issues: write
    steps:
      - uses: actions/checkout@v5
      - uses: anthropics/claude-code-action@v1
        with:
          anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}
          trigger_phrase: "/claude-review"
```

### External Contributor Handling

> **Security:** `pull_request_target` runs in the **base** repo context with
> access to secrets and a write-capable token, even for fork PRs. The job below
> checks out untrusted head code (`head.sha`) for review only — do **not** add
> build/test steps that execute that code, and treat the PR title/body/comments
> as untrusted input in the prompt. See `github-actions-auth-security` and
> `.claude/rules/github-actions-security.md`.

```yaml
name: "Claude: Review external contributions"

on:
  pull_request_target:
    types: [opened]

jobs:
  review:
    if: github.event.pull_request.author_association == 'FIRST_TIME_CONTRIBUTOR'
    runs-on: ubuntu-latest
    permissions:
      contents: read
      pull-requests: write
    steps:
      - uses: actions/checkout@v5
        with:
          ref: ${{ github.event.pull_request.head.sha }}

      - uses: anthropics/claude-code-action@v1
        with:
          anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}
          prompt: |
            Welcome first-time contributor! Review this PR for:
            - Code quality and style compliance
            - Test coverage
            - Documentation updates
            - Security concerns

            Provide helpful, constructive feedback.
```

## claude-code-action v1 Gotchas

Hard-won facts that produce silently-broken workflows (each cost real
debugging in production; see laurigates/.github#17–#19):

### Outputs are fixed — counts need `--json-schema`

The action exposes **only** `execution_file`, `branch_name`, `github_token`,
`structured_output`, and `session_id`. Referencing anything else
(`steps.scan.outputs.total`) evaluates to empty with no error — and prompting
Claude to print `TOTAL: <n>` in a comment does **not** create a step output.
Any metric a workflow needs out of a Claude step goes through structured
output:

```yaml
- id: scan
  uses: anthropics/claude-code-action@v1
  with:
    claude_args: >-
      --json-schema '{"type":"object","properties":{"total_issues":{"type":"integer"}},"required":["total_issues"]}'
    prompt: |
      ...analysis instructions...
      Report the count in the structured output field total_issues.

# Read it back — the || '{}' guard is REQUIRED: job outputs evaluate even
# when the step was skipped, and fromJSON('') errors.
outputs:
  issues: ${{ fromJSON(steps.scan.outputs.structured_output || '{}').total_issues }}
```

The same guarded expression works in `if:` gates
(`fromJSON(... || '{}').critical > 0`) — an unguarded comparison against a
missing output silently never fires.

### Bots are blocked by default

`allowed_bots` defaults to empty — **no** bot may trigger the action, so
bot-authored PRs (Renovate, release-please, Dependabot) fail with "Workflow
initiated by non-human actor". Pass `allowed_bots: "renovate[bot]"` (or a
comma-separated list) on workflows where bot PRs are the point, e.g.
dependency audits triggered by lockfile changes. Re-running a failed run does
not help: the replay keeps the original bot `sender`.

### Deprecated inputs (removed in a future version)

`direct_prompt`, `override_prompt`, `custom_instructions`, `max_turns`,
`model`, `fallback_model`, `allowed_tools`, `disallowed_tools`, `mcp_config`,
`claude_env`, `mode` are all deprecated. Use `prompt` plus `claude_args`
(`--model`, `--max-turns`, `--allowedTools`, `--disallowedTools`,
`--mcp-config`, `--system-prompt`) and `settings` (env). A deprecated input
may be silently ignored — a workflow using `direct_prompt` can run with no
prompt at all.

### Budget levers

`claude_args` supports `--max-turns` (turn count) and `--max-budget-usd`
(run-level spend cap); there is **no token-count budget**. Both fail the run
mid-flight when exhausted — they bound waste but don't prevent doomed runs on
oversized diffs; pre-gate on diff size for that. Turn-budget exhaustion is
recognizable by `error_max_turns` in the `execution_file` and by a *rotating*
set of failing AI jobs across re-runs of the same commit.

`--model` and `--effort` are the cost levers, not `--max-turns`. `--model`
takes an alias (`opus`, `sonnet`, `fable`, `best`) or a full id; aliases move
with each model generation, so record the alias you chose next to the effort.
`--effort low|medium|high|xhigh|max` overrides the harness default (`high`);
effort names do not map across model generations, so re-check the level when
the alias's target changes. `haiku` supports no `--effort` at all, so `opus
--effort low` is the cheap tier, not haiku. Every template above should carry
both, e.g.

```yaml
claude_args: |
  --model opus
  --effort medium
```

## Performance Optimization

### Checkout Optimization
```yaml
# Fast checkout for large repos
- uses: actions/checkout@v5
  with:
    fetch-depth: 1          # Shallow clone
    sparse-checkout: |      # Only needed paths
      .github
      src
      tests
```

### Conversation Limits
```yaml
# Control execution time and cost
claude_args: |
  --max-turns 10  # Limit back-and-forth exchanges
```

### Conditional Execution
```yaml
# Skip unnecessary runs
jobs:
  claude:
    if: |
      contains(github.event.comment.body, '@claude') &&
      !contains(github.event.comment.body, 'ignore')
```

## Repository Configuration

### CLAUDE.md Example

Create `CLAUDE.md` in repository root to define coding standards:

```markdown
# Repository Guidelines for Claude Code

## Code Standards
- Use TypeScript strict mode
- Follow Airbnb style guide
- Maintain 90%+ test coverage
- Document all public APIs

## Development Workflow
- Run tests before committing: `npm test`
- Format with Prettier: `npm run format`
- Lint with ESLint: `npm run lint`

## Commit Messages
Follow Conventional Commits:
- feat: New features
- fix: Bug fixes
- docs: Documentation changes
- refactor: Code refactoring

## Testing Requirements
- Unit tests for all functions
- Integration tests for APIs
- E2E tests for critical flows

## Security
- Never commit secrets
- Validate all user inputs
- Use parameterized queries
- Follow OWASP guidelines
```

## Quick Setup

1. **Install Claude GitHub App**: https://github.com/apps/claude
2. **Add API Key**: Repository Settings → Secrets → `ANTHROPIC_API_KEY`
3. **Create Workflow**: `.github/workflows/claude.yml` (use template above)
4. **Test**: Create issue and comment `@claude Hello!`
5. **(Optional)** Add `CLAUDE.md` in repo root for project standards

## Troubleshooting

### Workflow Not Triggering
- Check trigger conditions in `if:` clause
- Verify permissions (contents, pull-requests, issues)
- Check GitHub App installation

### Permission Denied
- Ensure proper permissions in workflow
- Check branch protection rules
- Verify repository access

For advanced configuration including MCP servers, tool permissions, and authentication methods, see the github-actions-mcp-config and github-actions-auth-security skills. For the secure-use baseline these templates follow (least-privilege permissions, script-injection indirection, `pull_request_target` hazards), see `.claude/rules/github-actions-security.md`.

