PRs pay their own cover.

Outside pull requests wait at the door until their author pays for a thorough AI review, in their own fork, on their own API key. It's not a service. It's a GitHub Action and a gh extension, and you'll never get a bill.

For maintainers

Run init in your project. It opens a pull request that adds one workflow file and one settings file.

$ gh extension install gh-bouncer/gh-bouncer
$ gh bouncer init

Every setting in .bouncer.yml

For contributors

Run the command from the bouncer's comment. It reviews your pull request in your fork, on your key.

$ gh extension install gh-bouncer/gh-bouncer
$ gh bouncer https://github.com/owner/repo/pull/123

See one that passed and one that got bounced

There's nothing to sign up for

Bouncer isn't a hosted product. It's code that runs in places you already have.

  • No account. Nobody to log in to, no dashboard, no seats.
  • No server. The gate runs in your repository's GitHub Actions. The review runs in the contributor's fork.
  • No one holding keys. A contributor's API key goes straight into their own fork's secrets and stays there.
  • No bill. Public repositories get Actions minutes for free. The reviews are paid for by the people asking for your time.

The whole thing is two public repositories, the action and the extension. Read every line.

Your monthly bill

Maintainer of a busy public repository

Subscription$0.00
Servers$0.00
Gate runs$0.00
AI reviews of 214 pull requests$0.00
Evenings spent closing slop$0.00
Total$0.00

How a pull request gets in

  1. An outsider opens a pull request

    It's held as a draft with one command to run. Your team walks straight in.

  2. They run gh bouncer

    A thorough review runs in their fork, on their key, against your rules.

  3. The bouncer checks the signature

    Pass: it's yours to review, report attached. Fail: closed, with the reasons.

3 pull requests1 waiting for you2 bounced
#2: adds a forbidden dependency and fixes nothing it claims to
BOUNCED
#1: fixes the bug, with tests. Review attached.
PASSED
Fix typo in README
#3: cosmetic change, no linked issue
BOUNCED

Your door, your rules

gh bouncer init adds .bouncer.yml to your repository with these defaults. Every key is optional, and contributors can't change any of it.

review:

How thorough the review is. The contributor pays for it.

modelclaude-opus-5-5

The model that runs the review.

efforthigh

low, medium, high, xhigh or max. Higher reads more code and costs the contributor more.

max_turns35

Steps the reviewer gets before it must decide. Defaults by effort: 12, 20, 35, 50, 80.

gate:

Deadlines, retries and who skips the line. Label any pull request bouncer:skip to wave it through.

deadline_hours48

Close the pull request if no signed review arrives in time.

max_attempts3

Bounced rounds before a pull request is closed for good.

close_on_failtrue

Set false to label bouncer:fail and leave it open. Good for a trial run.

fail_confidence0.8

A hard rule only fails a pull request at or above this confidence.

rereview_after_passtrue

New commits after a pass need a new review.

exempt_maintainerstrue

Owners, members and collaborators skip the bouncer.

exempt_prior_contributorstrue

So does anyone who has contributed before.

exempt_users[dependabot[bot], renovate[bot]]

Accounts that always skip it.

pin_review_to_gate_versionfalse

Only accept reviews made by the exact same bouncer version.

checks:

Instant checks with no AI involved.

require_linked_issuetrue

Must reference an open issue, like Fixes #123.

max_changed_lines0

Most lines a pull request may change. 0 means no limit.

max_author_prs_24h0

Most pull requests the author opened anywhere on GitHub in the last day. 0 means no limit.

forbidden_paths[".github/**"]

Paths outsiders may not touch.

guidance:

Plain-language notes for the reviewer: what the project is for and what you never accept. Nothing sharpens verdicts more.

guidance: |
  Zero dependencies, one public function.
  No cosmetic-only changes. New features need an issue first.

rules:

What the reviewer judges, citing file and line. A hard rule can close a pull request; a soft one becomes a note for you. These are the defaults.

solves-linked-issueCan close

Actually resolves the linked issue, not a partial or unrelated fix.

not-duplicateCan close

Not a duplicate, not already fixed, not something you declined before.

correctCan close

No evident bugs, regressions, or calls to APIs that don't exist.

substantiveCan close

Not a cosmetic-only change, unless the issue asks for exactly that.

in-scopeCan close

Fits the project's scope, not a niche one-off.

matches-styleNote

Follows the conventions of the surrounding code.

has-testsNote

Behavior changes come with tests.

Write your own in plain language. Listing rules replaces the defaults, so keep the ones you want.

rules:
  - id: no-new-deps
    hard: true
    description: Adds no new runtime dependencies.

A pass can't be faked

  • Signed by GitHub

    Every review is signed by GitHub as the output of the bouncer's own workflow. Edit the workflow, or run it anywhere but GitHub's runners, and the signature no longer matches.

  • Your settings, not theirs

    The model, effort and rules come from your repository. The contributor supplies a key and nothing else.

  • First review counts

    Every review of the same commit is recorded, and only the earliest one counts. Re-rolling until the model says yes doesn't work.

  • Untrusted text stays data

    Instructions hidden in a pull request aimed at the reviewer are flagged and fail it. The final call is made in code, from verified evidence.