unbiased ai

Review every pull request in CI

Reviews wait on a busy teammate, and small logic bugs slip through. Add one job to your workflow. It takes the pull request’s diff, has a coding agent read it and posts what it found as a comment. Claude Code, Codex and Continue each do it with a base URL, a key and the model name pareto. Pareto is Unbiased’s model: it selects frontier and open models for each request and blends their outputs into one answer.

Review commands tested live with Claude Code 2.1.305, Codex CLI 0.162.1 and Continue CLI 1.5.47Workflow YAML not run in Actions

A replay of our Codex review run on Pareto, recreated from the real output. Not a screenshot, and not a GitHub Actions run.

Tools that do this

Each of these talks to Pareto with a base URL, an API key and the model string pareto. Pick the one you already use.

The recipe: one job, one review command

Each tab is a complete workflow file. All three take the same steps: check out the pull request with full history, run one headless review command against origin/<base branch>, write review.md, and post it. We ran each review command three times on a pull request with a real bug, and every run flagged it. We did not run the workflows in GitHub Actions.

  1. Get an Unbiased API key and store it as a secret

    Choose a plan, then create a key in the Unbiased platform. New accounts are reviewed and approved by a person before the key works. Save it as a repository secret named UNBIASED_API_KEY.

  2. Check out the pull request with full history

    actions/checkout with fetch-depth: 0 fetches every branch, so origin/main exists and git diff origin/main...HEAD shows exactly what the pull request changes.

  3. Point the tool at Pareto in the review step only

    Claude Code: ANTHROPIC_BASE_URL=https://api.unbiased.ai (no /v1), the key in ANTHROPIC_AUTH_TOKEN, ANTHROPIC_MODEL=pareto. Codex: a provider table with https://api.unbiased.ai/v1. Continue: provider: openai with the same base URL. Type pareto by hand: Unbiased does not list models at /v1/models.

  4. Run one headless review and save it

    claude -p --bare --tools "" --setting-sources user, codex review --base or cn -p --readonly. Each prints the review to stdout, which the step writes to review.md. Claude Code has no tools and loads only your user settings, not settings files from the pull request. Continue and Codex can run shell commands: Continue with no sandbox, Codex in a read-only sandbox with no network.

  5. Post the review on the pull request

    The step first checks that review.md does not contain your key. gh pr comment --edit-last --create-if-none then posts one comment and updates it on each new push instead of adding another. The job needs pull-requests: write for that.

Tested on October 20, 2026Claude Code 2.1.305, Codex CLI 0.162.1 and Continue CLI 1.5.47, model pareto. Claude Code (claude -p --bare --tools "" --setting-sources user), Codex and Continue each flagged the inverted expiry check in the pull request and said to return False, 3 runs out of 3 each. With a pull request that added .claude/settings.json pointing ANTHROPIC_BASE_URL at a local server, the --bare-only command sent the step's token to that server; with --tools "" --setting-sources user it sent nothing there. Run record.

Claude Code: claude -p --bare

The diff is piped in, so Claude Code needs no tools to read it. --bare skips hooks, MCP servers, plugin sync and CLAUDE.md files, but on its own it still starts with Bash, Edit and Read. --tools "" turns off every built-in tool. --setting-sources user stops Claude Code from loading .claude/settings.json and .claude/settings.local.json from the checkout, so a pull request cannot change its permissions or set ANTHROPIC_BASE_URL to send your key to its own server.

  • Install: npm install -g @anthropic-ai/claude-code (Node.js 22 or later)
  • Review command tested with Claude Code 2.1.305: 3 of 3 runs flagged the bug, 3 to 6 seconds each
  • With a pull request that adds .claude/settings.json setting ANTHROPIC_BASE_URL to a local server: without the two flags Claude Code sent the key to that server; with them it sent nothing there and started with an empty tool list
  • Claude Code prints a note to stderr that it does not recognize pareto; the run finishes normally
  • The key goes in ANTHROPIC_AUTH_TOKEN. It worked in all our runs, but Claude Code documents only ANTHROPIC_API_KEY and apiKeyHelper for --bare
.github/workflows/pareto-review.yml
name: Pareto review
on:
  pull_request:
    types: [opened, synchronize, reopened]
permissions:
  contents: read
  pull-requests: write
jobs:
  review:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v7
        with:
          fetch-depth: 0
      - uses: actions/setup-node@v7
        with:
          node-version: 22
      - run: npm install -g @anthropic-ai/claude-code
      - name: Review the diff with Pareto
        env:
          ANTHROPIC_BASE_URL: https://api.unbiased.ai
          ANTHROPIC_AUTH_TOKEN: ${{ secrets.UNBIASED_API_KEY }}
          ANTHROPIC_MODEL: pareto
          BASE_REF: ${{ github.base_ref }}
        run: |
          git diff "origin/$BASE_REF...HEAD" | claude -p --bare --tools "" --setting-sources user \
            --append-system-prompt "You are reviewing a pull request. Report real bugs only: file, line, what goes wrong and the fix. If there are none, say LGTM." \
            "Review this diff." > review.md
      - name: Post the review on the pull request
        env:
          GH_TOKEN: ${{ github.token }}
          PR: ${{ github.event.pull_request.number }}
          KEY: ${{ secrets.UNBIASED_API_KEY }}
        run: |
          if grep -qF "$KEY" review.md; then
            echo "review.md contains the API key, not posting it" >&2
            exit 1
          fi
          gh pr comment "$PR" --edit-last --create-if-none --body-file review.md
Try the review command locally
# On the pull request branch, with main fetched
export ANTHROPIC_BASE_URL=https://api.unbiased.ai
export ANTHROPIC_AUTH_TOKEN=your-unbiased-api-key
export ANTHROPIC_MODEL=pareto
export BASE_REF=main
git diff "origin/$BASE_REF...HEAD" | claude -p --bare --tools "" --setting-sources user \
  --append-system-prompt "You are reviewing a pull request. Report real bugs only: file, line, what goes wrong and the fix. If there are none, say LGTM." \
  "Review this diff." > review.md
cat review.md

If ANTHROPIC_API_KEY is set on the runner, remove it from this step so Claude Code sends your Unbiased key. We do not show anthropics/claude-code-action here because its documentation lists no way to set a base URL.

review.md from one of our Codex runs, verbatim
The only functional change makes expired coupons valid, directly breaking the documented purpose of `coupon_is_valid` and enabling expired discounts to be applied.

Review comment:

- [P1] Return True for expired coupons — /private/tmp/uc-smoke/ai-code-review-in-ci/ci/coupons.py:7-8
  The newly added expiry check inverts the intended behavior: when `now` is after `expires_at`, `coupon_is_valid` returns `True`, allowing `apply_coupon` to apply a discount that should have expired. This should return `False` (or the early expiry guard should be removed if not part of the intended change).

The test pull request added an expiry check to coupon_is_valid() that returns True when the coupon has expired. All nine reviews named the file and the lines, said expired coupons now count as valid, and said to return False. Wording and detail varied from run to run.

What it costs on Pareto

A review costs what the agent reads and writes, and that grows with the diff and with how many files it opens. On our two-line test diff, two extra runs of the Claude Code command reported 406 and 525 tokens. That is a floor, not an estimate for your pull requests, so this section shows plan allowances only.

Personal at $10/monthFor one person
50M
tokens a week, 20 requests a minute
Personal Max at $100/monthFor one person
600M
tokens a week, 60 requests a minute

We measured tokens only for the Claude Code command on one two-line diff, so this page makes no per-review estimate. A large pull request can cost many times more. Rates and limits are on Pricing. Run record.

One key for every tool on this page

Pick a monthly allowance, or pay per token on Team.

Personal

$10/month

  • 50M tokens a week
  • 20 requests per minute
  • For one person
Choose Personal

Personal Max

$100/month

  • 600M tokens a week
  • 60 requests per minute
  • For one person
Choose Personal Max

Team

Pay as you go

  • Prepaid credits at published rates
  • 300 requests per minute
  • No weekly token cap
Get started with Team

Subscriptions are for one person and are not unlimited. New API accounts are reviewed by a person before access turns on, and commercial or production use needs a separate written agreement. Rates and limits are on Pricing.

Questions about this recipe

Does the review run on pull requests from forks?

Not with this workflow. GitHub does not pass repository secrets to pull_request runs from forks, so the review step has no key and fails. It runs on pull requests from branches in your own repository. Avoid switching to pull_request_target to get around this: that trigger has secrets and write access while the job checks out code someone else wrote.

Can the reviewer change my code or run what the pull request adds?

Claude Code, as set up here, gets the diff on stdin and starts with no tools, so it cannot edit files or run commands. With --bare it loads no hooks, MCP servers or CLAUDE.md, and with --setting-sources user it ignores settings files in the checkout. cn --readonly (plan mode) removes the Edit and Write tools but still allows its Bash tool, with no sandbox, so it can run any command, including the pull request’s code. In our runs it ran only git and read files. codex review can also run commands, including the pull request’s code, but inside a sandbox that blocks file writes and network access. In 1 of our 3 Codex runs it imported the changed module with python3 to check the bug. No tool edited a file in our runs.

Did you run these workflows in GitHub Actions?

No. We ran each review command on a local clone with the same environment variables the workflow sets, three times per tool, on October 20, 2026. The checkout, install, secrets and gh pr comment steps follow GitHub’s and each tool’s documentation but were not run. Run record.

Will it catch every bug?

No, and the review is not a test suite. In our runs all three tools caught a planted logic bug every time, but one Codex review also made a wrong side claim about unexpired coupons, and one Continue review cited lines 6 to 7 instead of 7 to 8. Treat the comment as a second reader, not a gate.

Can a pull request get the reviewer to leak the key?

It could try. The key is in the review step’s environment, and Continue’s config file holds it, so text in a pull request could ask the agent to print it into review.md, which is then posted. The post step checks review.md for the key and stops instead of posting if it finds it. That catches the key as written, not an encoded copy, and not a key that cn’s unsandboxed shell sends over the network, so run the review only on pull requests from people you trust and rotate the key if a review ever prints it.

Which plan does a team repository need?

Personal and Personal Max are for one person. A review bot on a company’s repositories is production use: Team is pay as you go, and plan selection does not itself authorize production use, so confirm it in a separate written agreement with Unbiased. See Pricing for the rates.

Do I need an Anthropic or OpenAI account?

No. With these settings Claude Code, Codex and Continue send requests to Unbiased with your Unbiased key, and your Unbiased plan pays for them. Format compatibility is not a promise that every feature of each tool works, so tell us if one doesn’t.

What happens when I hit the weekly allowance?

Requests over your plan’s limits return an HTTP 429 error. Personal includes 50M tokens a week and 20 requests per minute. Personal Max raises that to 600M a week and 60 requests per minute for $100/month. Team uses prepaid pay-as-you-go credits with no weekly token cap.

Do I choose between models?

No. You send every request to one model string, pareto. Pareto selects frontier and open models for each request and blends their outputs into one answer.

Is my code kept?

Personal and Personal Max are not our zero data retention tier: prompts and responses may be kept up to 30 days, as section 5(c) of the Terms explains. For work that must not be kept, ask about the Zero Data Retention API on the Private AI page.

Same key, same model string, different job. See every use case. Or find your tool on Works with.

Product names belong to their owners. Unbiased is not affiliated with or endorsed by the makers of the tools on this page.

Give every pull request a second reader

One workflow file, one secret and the model string pareto. Pareto starts at $10 a month for 50M tokens a week.