Skip to content

Bugbot: learned rules and Autofix

Bugbot is Cursor’s pull request review agent: it checks pull requests for bugs, security issues, and code quality problems, follows rules from .cursor/BUGBOT.md files and rules learned from a team’s past reviews, and can hand findings to a Cloud Agent through Autofix. By default its check reports findings without failing, so it informs the merge gate rather than being one.

This page is for the developer who switches Bugbot on and the tech lead who keeps it useful. A month after rollout the pattern is familiar: Bugbot flags the same generated file on every pull request, half its comments are resolved as “won’t fix”, the review checklist sits in .cursor/rules/ where Bugbot never reads it, and Autofix has pushed to a branch halfway through human review. Each of those is a configuration decision, not a model problem.

  • A root and path-scoped .cursor/BUGBOT.md layout that keeps findings on your team’s real risks.
  • A routine for learned rules: teach, read, and promote the ones you depend on into version control.
  • An Autofix policy per repository, with the reason for each mode and the gates its commits still have to pass.
  • A seeded-defect test and an analytics query that show whether Bugbot catches bugs, not just whether it comments.
  • A clear place for Bugbot in layered pull request review, next to CI, code owners, and the evidence bundle.

Bugbot reads the diff with judgement; it does not decide whether code merges. The check Bugbot publishes on GitHub is named Cursor Bugbot, and a run that finds issues ends with the conclusion neutral unless your organisation has turned on the option to fail on unresolved findings. Requiring the check in branch protection therefore guarantees that Bugbot ran, not that its findings were addressed.

LayerWhat it provesWho or what owns it
Local pre-push reviewThe author’s diff has had one review pass before anyone else sees itThe author, with Agent Review or the /review-bugbot skill
Deterministic CI gatesTypes, lint, tests, and the evidence bundle pass on the head commitCI, from the base branch’s configuration
BugbotLogic errors, missing edge cases, and rule violations a linter cannot expressBugbot, with rules your team maintains
Security reviewInjection, secrets, authorisation, and dependency risksCursor’s Security Agents or your own scanner
Human sign-offIntent, architecture, and high-risk pathsA named code owner reading the evidence and, for high risk, the code
RolloutBehaviour in productionCanaries, flags, and monitors

Three consequences follow. First, Bugbot’s findings feed the standard risk class; they approve nothing. Rollouts and PR Routing & Approval builds approval by rule on CI-computed risk labels instead. Second, if you run /review-bugbot in the editor before pushing, Bugbot records the patch ID of the reviewed diff and skips the pull request review when the same diff arrives, so the pull request carries no fresh Bugbot pass. Third, reviews are incremental by default: after the first review, each push is reviewed only for the changes since the previous one. A bug that needs an early and a late commit together can slip between passes, so turn Incremental Review off where you rely on Bugbot for high-risk paths.

The rules go in before the first automatic review, so the team’s first impression is not a wall of noise.

  1. Connect your source control. In the Cursor dashboard, connect GitHub (including GitHub Enterprise Server), GitLab (including self-hosted), Bitbucket (including Data Center), or Azure DevOps Services. On GitHub, Bugbot then comments as cursor[bot], the account of Cursor’s GitHub app.

  2. Commit a root .cursor/BUGBOT.md before you enable reviews. Start from the file in the next section. A short file with a “do not flag” list does more for signal than a long checklist.

  3. Enable Bugbot on one repository. Open Bugbot under Automations in the Cursor dashboard and enable it for a single, active repository. On team plans, Bugbot then reviews pull requests from every contributor to that repository, whether or not they are on the Cursor team. An individual plan reviews only the pull requests you author.

  4. Choose when it runs. Leave automatic reviews on for the pilot repository. Repository settings offer Incremental Review (on by default), Post PR Summary (in the description, as a comment, or off) and, on usage-based plans, an effort level: Low, Default, High, or Smart, where Smart takes a plain-language instruction such as “High for anything under src/billing/”. Raise effort only where the seeded-defect test below shows misses; it costs more usage. The run-frequency switches sit at three levels:

    • Installation: team admins can set Run only once per pull request.
    • Personal (team and enterprise members): Run only when mentioned, Run only once, and Enable reviews on draft PRs, for their own pull requests.
    • Repository: the Admin API’s manualTriggerOnly (step 7) makes Bugbot run only when triggered.
  5. Prove the rules load. Open a small pull request and comment:

    bugbot run verbose=true

    Bugbot posts a table of every rule included in that run, flags any rule that was truncated or omitted, and gives a request ID for support. cursor review verbose=true does the same. If your BUGBOT.md is not in the table, fix that before going further.

  6. Require the check, then decide on failing. Add Cursor Bugbot to the required checks in your branch protection ruleset so no pull request merges before Bugbot has run. If the option to fail on unresolved findings is available to your organisation, turn it on only after the seeded-defect test and two weeks of low noise; a failing check that the team learns to dismiss is worse than a neutral one.

  7. Roll out beyond the pilot from a script. Once the pilot passes the checks later on this page, a team admin can enable more repositories through Bugbot’s Admin API. manualTriggerOnly: true enables one in manual mode, a safe start for a repository with no BUGBOT.md yet:

    Terminal window
    # Terminal. CURSOR_ADMIN_API_KEY is a team Admin API key read from your secret store.
    curl -sS -X POST https://api.cursor.com/bugbot/repo/update \
    -H "Authorization: Bearer $CURSOR_ADMIN_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{"repoUrl": "https://github.com/acme/orders-api", "enabled": true, "manualTriggerOnly": true}'
    # List every repository with its Bugbot settings, to check the rollout.
    curl -sS https://api.cursor.com/bugbot/repos -H "Authorization: Bearer $CURSOR_ADMIN_API_KEY"

Write a BUGBOT.md that keeps the signal high

Section titled “Write a BUGBOT.md that keeps the signal high”

Bugbot always includes the root .cursor/BUGBOT.md, then any further .cursor/BUGBOT.md files it finds while walking upward from each changed file. Put repository-wide rules at the root and stricter rules next to the code they govern:

orders-api/
.cursor/BUGBOT.md # always included
src/billing/.cursor/BUGBOT.md # included when a billing file changes
migrations/.cursor/BUGBOT.md # included when a migration changes

BUGBOT.md is one of four rule sources. Bugbot merges them into one block in this order: team rules (written by team admins in Bugbot’s settings, applied to every enabled repository), then the project BUGBOT.md files, then learned rules, then manual rules. Put organisation-wide invariants such as “never log a token” in team rules, and mark the ones that matter most as required: over the size cap (below), Bugbot keeps required team rules first, but keep the total under the cap rather than rely on that.

Cursor’s project rules (the .mdc files in .cursor/rules/) do not apply to Bugbot runs. If one rule matters to both the agent and the review, write it in both places.

Write each rule as a condition Bugbot can check in a diff (“a handler that awaits without handling rejection”), not a value (“write robust code”). Ask Bugbot to cite the rule, as Sentry’s public BUGBOT.md for its JavaScript SDK does, so a reviewer can trace a noisy finding to its source. And keep the files short: each rule is truncated at 30,000 characters and the combined rules for one review are capped at 100,000, after which some rules are omitted. A root file for a TypeScript API service:

# Review rules for orders-api
Flag only issues you can tie to a line in this diff. When a finding comes
from this file, say so in the comment and name the section.
## Always flag
- A handler in src/routes/ that awaits a call without handling rejection.
- Money stored or computed as a JavaScript number. Amounts are integer
cents (bigint) or Decimal from src/lib/money.ts.
- A new SQL string built with template literals instead of the query builder.
- Logging of request bodies, tokens, email addresses or card data.
- A feat change with no new or changed test; a fix with no test that fails
without the fix.
- A test whose assertion was loosened (toBeTruthy replacing toEqual, a
removed expect, an added .skip) in the same PR as a code change.
## Do not flag
- Formatting, import order or naming: dprint and oxlint own these.
- Files under src/generated/ and any *.snap file.
- Speculative refactors unrelated to the diff.

And a scoped file for the billing path:

# Billing rules (src/billing/)
- Every state change to an invoice must be idempotent on the webhook event
id. Flag any handler that writes before checking processed_events.
- Currency conversion happens only in src/billing/fx.ts. Flag it anywhere else.
- Treat any change to refund logic as high severity.

Teach Bugbot rules from your review history

Section titled “Teach Bugbot rules from your review history”

Learned rules live in Cursor’s dashboard, not in your repository. They come from your team’s GitHub pull request activity (the documentation names only GitHub), a one-off backfill of the repository’s history, and explicit @cursor remember comments. Each learned rule has a Name, the Rule content, and optional Scoped paths such as src/components/**.

  1. Enable learning. In Bugbot’s repository rules, enable learning for your organisation and the pilot repository, and run the backfill from its history. Manual rules, which you write in the same screen, also apply only while learning is enabled for both the organisation and the repository.

  2. Read what Bugbot learned before you trust it. Treat the list like a pull request: delete one-off decisions, scope rules that hold for one directory, and rewrite vague rules as checkable conditions.

  3. Teach inline when a human writes the same comment twice. The second time a reviewer types the same correction, they reply on the pull request instead:

    @cursor remember Background jobs in src/jobs/ must be idempotent: flag any job that inserts a row without an ON CONFLICT clause or a prior existence check.
  4. Review rule analytics monthly. Each rule shows Issues found, PRs reviewed, Accepted issues, and Acceptance rate. A rule with many findings and a low acceptance rate is noise; rewrite or delete it. Pick your own threshold and write it down, for example “below 30% acceptance after 20 findings”.

  5. Promote the rules you depend on into BUGBOT.md. Cursor enables and disables learned rules on its own as it sees more activity. That suits style drift and endangers invariants: a rule about idempotent billing webhooks must not switch off because nobody tripped it for a month. Move a rule that has earned its place into the right BUGBOT.md through a pull request, where it is versioned, reviewed, and owned.

Autofix spawns a Cloud Agent to fix the bugs Bugbot found, pushes the fix, and comments on the pull request with the result. It uses your Default agent model (falling back to the team default), requires on-demand usage and storage to be enabled (not Legacy Privacy Mode), and bills as Cloud Agent usage. When it is on, GitHub may show a separate Cursor Bugbot Autofix check that only reports success or neutral, so it never blocks a merge on its own.

ModeWhat happensUse it when
OffFindings carry Fix in Cursor and Fix in Web links; a person starts the fixRepositories with high-risk paths, or while you are still tuning rules
Create New Branch (Cursor’s recommended mode)The fix lands on a new branch; the author decides whether to take itThe default for most repositories: the fix is visible and optional
Commit to Existing BranchThe fix is pushed to the pull request branch, with at most three attempts per pull requestLow-risk repositories with strong tests, where stale-approval dismissal is on

Provider support differs. GitHub and Cursor’s Origin support both modes; GitLab and Bitbucket support only Commit to Existing Branch; Azure DevOps supports neither. An unsupported personal mode makes Bugbot skip Autofix for that pull request.

The team mode is a default, not a policy. Each developer can override it for their own pull requests (Use Installation Default, Off, or either branch mode), so a team default of Create New Branch does not stop one author from choosing Commit to Existing Branch. The controls that hold for everyone live in your source control: branch protection, required checks, and stale-approval dismissal.

Three limits shape the table:

  • An Autofix commit is agent-written code. It passes CI, the evidence bundle check, and code-owner review like any commit. Never exempt it from branch protection, and keep stale-approval dismissal on.
  • Autofix can clear a finding by changing the test. Put tests in CODEOWNERS and keep the “loosened assertion” rule in BUGBOT.md.
  • Three attempts is a loop limit, not a quality bar. A finding that survives them goes to a person.

Comment volume says nothing about quality. Two measurements do: a seeded-defect test and the share of findings the team acts on.

Run a seeded-defect test. Keep a branch with five planted defects that match your rules: an unhandled promise rejection in a route, money stored as a JavaScript number, a template-literal SQL query, a logged token, and a loosened test assertion. Open a draft pull request from it labelled do-not-merge, comment bugbot run verbose=true (drafts are skipped by automatic review unless enabled), and record which defects Bugbot found. Never merge it, and close it once you have recorded the results. Repeat after every BUGBOT.md or effort-level change. A defect it stops catching is a regression in your review layer, found before a real pull request needed it.

Measure what the team resolves. On Enterprise plans, the Bugbot analytics API returns one item per completed review with the findings count, the billed cost, and each finding’s severity and resolution status. The key needs the read:* scope; keep it in a secret store and read it from the environment:

Terminal window
# Terminal. CURSOR_ANALYTICS_API_KEY comes from your secret store, never the command line.
curl -sS --get https://api.cursor.com/analytics/team/bugbot-reviews \
-u "$CURSOR_ANALYTICS_API_KEY:" \
--data-urlencode "startDate=$(date -d '30 days ago' +%F)" \
--data-urlencode "repo=github.com/acme/orders-api" \
--data-urlencode "pageSize=250" \
--data-urlencode "dryRun=false" \
| jq -r '
([.data[].cost_cents // 0] | add) as $cents
| ([.data[] | (.bugs // [])[]] | group_by(.severity // "unknown")[]
| [ (.[0].severity // "unknown"), length,
(map(select(.resolution_status == "resolved")) | length) ]
| @tsv),
"total_usd\t\($cents / 100)"'

On macOS, replace date -d '30 days ago' +%F with date -v-30d +%F. dryRun=false keeps trial runs, whose findings are never resolved, out of the share. The output is one line per severity with findings and findings resolved (a finding with no severity counts under unknown), then one total_usd line with the period’s spend in dollars. Follow pagination.hasNextPage if a month holds more than 250 reviews.

A falling resolved share at steady volume means noise: narrow the rules. A high resolved share with a missed seeded defect means the rules are too narrow: add the check. To trial Bugbot before announcing it, POST /bugbot/review with "dryRun": true (key scope admin:*) reviews a pull request without posting to it; findings appear only in analytics, and dry runs are billed like normal reviews.

Sign-off does not move to Bugbot. A code owner still approves high-risk paths, and the review layer’s owner (usually the tech lead) owns the rules, the seeded-defect branch, and the monthly numbers.

How does Bugbot compare with Claude Code and Codex review?

Section titled “How does Bugbot compare with Claude Code and Codex review?”

The design on this page carries across tools; the mechanics differ:

Cursor BugbotClaude CodeCodex
Pull request reviewAutomatic on each update, or bugbot run / cursor reviewManaged Code Review (research preview, Team and Enterprise)@codex review and automatic reviews on GitHub (per OpenAI’s docs, checked 2026-08-28)
Local review/review-bugbot skill/code-review/review; codex review from the shell (0.157.1)
Where rules live.cursor/BUGBOT.md, learned, manual, and team rulesCLAUDE.md; managed Code Review also reads a root REVIEW.md (local /code-review does not)AGENTS.md
Fixing findingsAutofix through a Cloud AgentA separate session you startA separate task you start

For the full comparison on noise, configuration, and cost, including third-party bots, see AI code review bots compared. The Claude Code equivalent of this page is review automation with Claude Code. On Team and Enterprise plans Bugbot can also call MCP tools you add in its settings; add one only when a rule needs data outside the diff, such as acceptance criteria.

Copy-paste prompts for Bugbot rules and Autofix

Section titled “Copy-paste prompts for Bugbot rules and Autofix”

Run these in Cursor’s agent from the repository root. The first needs the GitHub CLI (gh) authenticated for the repository.

What breaks when Bugbot reviews your pull requests?

Section titled “What breaks when Bugbot reviews your pull requests?”

Bugbot ignores your review checklist. The checklist is in .cursor/rules/, which Bugbot does not read. Recovery: move the review rules into .cursor/BUGBOT.md and confirm with bugbot run verbose=true that the file appears in the rules table.

A rule you rely on stopped firing. It was a learned rule, and Cursor disabled it, or the combined rules passed the 100,000-character cap and it was omitted. Recovery: check the verbose table for omitted or truncated rules, shorten the files, and promote invariants from learned rules into BUGBOT.md.

The same false positive on every pull request. It matches generated code, snapshots, or a linter-owned pattern. Recovery: add it to “Do not flag” and run the noise prompt above after two weeks.

Required check, green merge, open findings. The Cursor Bugbot check concluded neutral, which branch protection treats as passing. Recovery: if the fail-on-unresolved option is available, turn it on for the repository; otherwise make resolved Bugbot threads part of your evidence bundle check or require conversation resolution in the branch protection ruleset.

A bug shipped that no single push contained. Incremental review looked at each push alone; the defect exists only when two combine. Recovery: turn Incremental Review off for repositories with high-risk paths, so each push gets a full-diff pass, and comment bugbot run on their open pull requests.

Autofix commits land in the middle of a human review. The repository, or the author’s personal setting, uses Commit to Existing Branch. Recovery: switch the team default to Create New Branch, ask the author to set Use Installation Default, and keep stale-approval dismissal on so any fix that still lands needs fresh approval.

Autofix never runs. On-demand usage is off, storage is disabled, the provider does not support the mode, or a personal setting overrides the installation. Recovery: check those four in that order.

No Bugbot review on a pull request you expected it on. The author ran /review-bugbot locally on the same diff, the repository runs only once or in manual mode, or the author’s own settings run Bugbot only when mentioned or skip drafts. Recovery: comment bugbot run, and put the trigger rules in the pull request template.

The bill grows faster than the value. Effort was raised everywhere, or dry runs are used at scale. Recovery: keep High effort for repositories where the seeded-defect test shows misses, and read the total_usd line monthly.