GitHub Action that pulls the freshest unresolved Sentry issues for your project and opens a single PR containing a fix (and where practical a regression test) per issue, written by either Claude Code or Codex.
This action pushes a branch and opens a pull request, so the repo must allow GitHub Actions to do both. Enable it once at:
https://github.com/<git-org>/<git-project>/settings/actions
Under Workflow permissions:
- Select Read and write permissions.
- Tick Allow GitHub Actions to create and approve pull requests.
Without this the action will fail with GitHub Actions is not permitted to create or approve pull requests when it tries to open the PR.
name: Daily Sentry fixes
on:
schedule:
- cron: "0 7 * * *"
workflow_dispatch:
jobs:
fix:
runs-on: ubuntu-latest
permissions:
contents: write
pull-requests: write
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- uses: tcds-io/sentry-bugbot@v1
with:
agent: claude
credentials-type: api-key
credentials-token: ${{ secrets.ANTHROPIC_API_KEY }}
sentry-token: ${{ secrets.SENTRY_AUTH_TOKEN }}
sentry-org: my-org
sentry-project: my-project
max-issues: 5Or, with a Claude Pro/Max subscription via OAuth token:
- uses: tcds-io/sentry-bugbot@v1
with:
agent: claude
credentials-type: auth_token
credentials-token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}
sentry-token: ${{ secrets.SENTRY_AUTH_TOKEN }}
sentry-org: my-org
sentry-project: my-project
sentry-url: https://de.sentry.io # optional, for self-hosted / region| input | required | default | description |
|---|---|---|---|
agent |
yes | — | claude or codex |
credentials-type |
yes | — | api-key or auth_token. auth_token is only valid when agent: claude. |
credentials-token |
yes | — | API key or OAuth token for the selected agent. |
sentry-token |
yes | — | Sentry auth token (event:read, project:read, org:read). |
sentry-org |
yes | — | Sentry organization slug. |
sentry-project |
yes | — | Sentry project slug. |
sentry-url |
no | https://sentry.io |
Sentry base URL (for self-hosted or regional). |
max-issues |
no | 5 |
Top-N issues (by event count) attempted per run |
additional-instructions |
no | "" |
Extra free-form instructions appended to the agent prompt (commit message format, test framework, files to avoid, etc.) |
base-branch |
no | repo default | Branch PRs target |
github-token |
no | ${{ github.token }} |
Token for branch push + PR creation |
dry-run |
no | false |
If true, skip push/PR and reset the branch |
The previous camelCase names (
maxIssues,baseBranch,githubToken,dryRun) are still accepted for backward compatibility but emit a deprecation warning. Migrate to the kebab-case names — the camelCase aliases will be removed in a future release.
additional-instructions is appended to the prompt the action builds for the agent. Use it for project conventions the agent would not know about:
- uses: tcds-io/sentry-bugbot@v1
with:
agent: claude
credentials-type: api-key
credentials-token: ${{ secrets.ANTHROPIC_API_KEY }}
sentry-token: ${{ secrets.SENTRY_AUTH_TOKEN }}
sentry-org: my-org
sentry-project: my-project
additional-instructions: |
Use this commit format: SENTRY-{sentry-project}: {title}\n\n{description}
Tests live in tests/ and use vitest.
Never touch files under generated/.credentials-type: api-key—credentials-tokenis set asANTHROPIC_API_KEY(claude) orOPENAI_API_KEY(codex). Billed via the provider's standard API.credentials-type: auth_token—credentials-tokenis set asCLAUDE_CODE_OAUTH_TOKENand binds the run to a Claude Pro/Max subscription. Only supported whenagent: claude.
The sentry-token input must be a Sentry Internal Integration token (Org Settings → Developer Settings → New Internal Integration) or a User Auth Token with sufficient scopes.
Required scopes:
event:read— fetch the latest event for each issue (stack trace, breadcrumbs, request).project:read— list issues for the configured project.org:read— resolve the configured organization slug.
Optional scope (recommended):
event:write— post a back-link comment on each fixed Sentry issue (🤖 sentry-bugbot opened PR …). Without it the run still succeeds, but you'll see onecore.warning(...)in the job log and Sentry won't be annotated.
A token created with only
org:ciis not sufficient — that scope covers CI-related actions but does not grant access to read issues or events. Use the three required scopes above. If any are missing, the action fails with a403 Forbiddenfrom the Sentry API.
Setup:
- In Sentry, go to Settings → Developer Settings → New Internal Integration.
- Set the three permissions above to Read.
- Save, copy the generated token, and store it as a GitHub Actions secret (e.g.
SENTRY_AUTH_TOKEN). - Reference it from your workflow as
sentry-token: ${{ secrets.SENTRY_AUTH_TOKEN }}.
For self-hosted or regional Sentry, also set sentry-url (e.g. https://de.sentry.io).
Instead of paying per-token via the Anthropic API, you can bind the run to a Claude Pro/Max subscription using an OAuth token.
- Run
claude setup-tokenlocally to produce a long-lived OAuth token tied to your subscription. - Store it as a GitHub secret (e.g.
CLAUDE_CODE_OAUTH_TOKEN). - Pass
credentials-type: auth_tokenandcredentials-token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}.
Caveats:
- The token authenticates the human who generated it. Every run consumes that user's subscription quota and shows up in their Anthropic usage.
- Subscription rate limits are enforced per 5-hour window — a noisy day can exhaust the budget for other tools that share the same account.
- Rotation is manual: re-run
claude setup-tokenand update the secret. - Codex has no equivalent env-var-based OAuth flow, so
auth_tokenis rejected whenagent: codex.
- Fetches up to
max-issuesunresolved Sentry issues from the last 24h, ordered by frequency. - Creates a single batch branch
sentry-fix/batch-<utc-timestamp>. - Hands every issue (title, stack trace, breadcrumbs, request) to the selected agent CLI in one session, with instructions to fix each root cause, add a regression test where practical, and commit per fix using
fix(sentry): <SHORTID> <title>. Issues sharing a root cause are coalesced into a single commit referencing every affected shortId, which eliminates duplicate fixes on related errors. - Pushes the branch and opens one PR listing every issue and its outcome.
- Writes a job summary table mapping each issue to its outcome.
For every issue it looks at, the agent writes a note to .bugbot/<project>/<SHORTID>.md with three sections — Findings, Proposed solution, Risks — and commits it alongside the work. These notes are committed to the repo, so on later runs the agent is shown any prior note for the same issue and refines it instead of re-investigating from scratch.
The agent is instructed to apply a code change only when it addresses the root cause. If the only available change would merely silence the Sentry error (swallowing exceptions, blanket guards, broadened catches, event filtering) — or if the fix risk is judged too high (critical paths, broad blast radius, uncertain correctness) — it defers: it writes the note with a recommendation but makes no code change, and marks the issue deferred. Deferred issues still appear in the PR (the note is committed) and get a back-link comment in Sentry, but no patch is proposed. This keeps the bot from trading real bugs for a quiet dashboard.
npm install
npm run typecheck
npm run build # bundles to dist/index.cjs (committed for the action runtime)