Review GitHub pull requests with agents, then post each finding to GitHub yourself — one comment at a time, edited how you want it.
- Pick a PR. The panel lists a repo's open pull requests, filtered by who was asked to review: Asked me, Asked my team (any of them, or one you pick), or All open.
- Review it. Press Review this PR. A BB thread runs the review skills you
configured against the change and writes structured findings to a JSON file,
then submits them with
bb code-review submit. - Skim the issues. The review screen is a plain list: severity, title, and a three-line gist. Nothing else, plus one button through to the PR on GitHub.
- Open an issue for the detail — background, problem, suggested fix — and
below it, every file the issue points at, stacked, each showing just the
cited lines with their real line numbers. That includes files the finding
only mentioned in passing:
src/thing.ts:42in its prose becomes a snippet. Any file header links to that file's place in the PR diff on GitHub. - Act on it: post the comment verbatim, edit it first, discuss it with an agent in a side tab, or dismiss it.
The panel remembers the repo and filter you were on, so re-opening the tab resumes where you left off. Nothing reaches GitHub until you press Post.
Reviewing happens across both surfaces — some comments here, some in GitHub's own diff view — so they go into the same pending review:
- A review already open on GitHub: the button reads Add to my review and the comment joins it as a draft, beside the ones you wrote there. GitHub allows only one pending review per person per PR, and refuses standalone comments while one is open, so this is also the only thing that can work.
- No review open: Post comment publishes immediately, and Start a review opens the shared draft instead — the same split GitHub's own UI offers. Later comments, from either surface, join it.
A draft is labelled Draft comment and says to submit the review on GitHub to publish, because nobody else can see it until you do.
GitHub only anchors an inline comment to a line inside the diff. A finding whose range overhangs one is narrowed to the part that is in it, and the panel says so; a finding entirely outside the diff can only be a general pull request comment, and the panel says that too — before you press the button. The review agent is told in as many words not to post, approve, request changes, or touch the PR.
The GitHub CLI is the only transport, and it runs server-side, so whatever
gh auth can see on this machine, the plugin can:
gh auth login
gh auth refresh -s read:org # so `Asked my team` can list your teamsThen, in Settings → Plugins → Code Review:
| Setting | What it does |
|---|---|
| Repositories | Extra owner/repo lines to track. Repos whose checkouts are BB project sources are discovered automatically from their origin remote. |
| Review skills | Skill names the review agent runs, one per line. Defaults to code-review. Empty means a generic review. |
| Extra review instructions | Appended to every review prompt — house rules, things to always check, things to never comment on. |
| Findings directory | Where the agent writes its findings JSON, relative to the checkout. Defaults to .bb/code-review. |
| Default BB project | Where review threads spawn for repos not attached to a BB project. |
| Teams | org/team lines, if you would rather not grant read:org. |
Settings do not auto-reload: run bb plugin reload code-review after changing
one.
GitHub's own review-requested:@me quietly folds in requests made to teams you
belong to, so it cannot tell "someone asked me" apart from "someone asked a
team I'm in". This plugin reads each PR's actual review requests and filters
them itself, so the two are separate:
- Asked me — a review request naming you.
- Asked my team — a request naming one of your teams, with a picker to narrow to a specific one.
- All open — every open PR in the repo.
When a review starts, the plugin fetches the PR — description, discussion,
inline review comments, changed files, and the full diff — and stores it. The
review agent reads that snapshot over the bb code-review CLI instead of
running gh itself. Three reasons:
- The agent sandbox usually cannot reach
gh. Its filtering proxy terminates TLS, andgh(a Go binary) rejects the interception withx509: OSStatus -26276.curlandgittrust it;ghdoes not. The plugin runs in the BB server, which is not sandboxed, so itsghalways works — and the CLI reaches it over loopback, which the sandbox permits. - The agent's environment may have no
ghauth at all, even where the server does. - The snapshot is pinned to the head commit the review started from, so the line numbers in the findings match the diff the agent actually read, even if the PR moves underneath it.
bb code-review context --review owner/repo#123 [--json] # description, discussion, files
bb code-review diff --review owner/repo#123 [--file <path>]
bb code-review files --review owner/repo#123
bb code-review schema # the findings schema
bb code-review submit --review owner/repo#123 --file <path>A diff too large for one CLI response (the host caps a result at 1 MiB and
rejects an over-large one outright) makes diff list the files instead, to be
read one at a time with --file.
The review agent writes a JSON file and submits it. That contract is
documented for agents in skills/pr-review/SKILL.md.
Each finding carries five things, deliberately kept apart:
| Field | Purpose |
|---|---|
file, startLine, endLine, side |
Where the comment anchors. No line anchor still works — it posts as a general PR comment. |
background |
What the code does, for a reader who has not been in this file. |
problem |
What is actually wrong and why it matters. |
suggestedFix |
How the agent would fix it. |
suggestedComment |
Posted to GitHub verbatim, unless you edit it first. |
A single malformed finding is dropped with a warning and the rest are imported;
submit reports the warnings but still succeeds.
Re-running a review replaces the findings you have not acted on and keeps the ones you have — posted comments are history, and a dismissal is a decision you should not have to make twice.
npm install
npm test # vitest
npm run typecheck # tsc --noEmit
bb plugin dev # rebuild + reload on saveThe pure logic — the findings contract, the prompt, PR filtering, patch
splitting, and the gh api argv for posting a comment — lives in
review-core.ts and is unit-tested without a server. server.ts is the
registrations and the gh plumbing; app.tsx is the panel.