{"id":51524365,"url":"https://github.com/boxlite-ai/pr-review-agent","last_synced_at":"2026-07-08T19:30:42.418Z","repository":{"id":369823480,"uuid":"1291663434","full_name":"boxlite-ai/pr-review-agent","owner":"boxlite-ai","description":"AI PR code review in an isolated BoxLite microVM — a showcase of BoxLite managed agents.","archived":false,"fork":false,"pushed_at":"2026-07-07T05:31:07.000Z","size":48,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-07-07T06:16:59.872Z","etag":null,"topics":["ai-agent","ai-code-review","boxlite","claude","code-review","github-action","microvm","pr-review"],"latest_commit_sha":null,"homepage":"https://boxlite.ai","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/boxlite-ai.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-07-07T02:02:17.000Z","updated_at":"2026-07-07T05:31:11.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/boxlite-ai/pr-review-agent","commit_stats":null,"previous_names":["boxlite-ai/pr-review-agent"],"tags_count":3,"template":false,"template_full_name":null,"purl":"pkg:github/boxlite-ai/pr-review-agent","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/boxlite-ai%2Fpr-review-agent","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/boxlite-ai%2Fpr-review-agent/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/boxlite-ai%2Fpr-review-agent/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/boxlite-ai%2Fpr-review-agent/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/boxlite-ai","download_url":"https://codeload.github.com/boxlite-ai/pr-review-agent/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/boxlite-ai%2Fpr-review-agent/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":35276517,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-07-08T02:00:06.796Z","response_time":61,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["ai-agent","ai-code-review","boxlite","claude","code-review","github-action","microvm","pr-review"],"created_at":"2026-07-08T19:30:41.764Z","updated_at":"2026-07-08T19:30:42.402Z","avatar_url":"https://github.com/boxlite-ai.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# BoxLite PR Reviewer\n\nA GitHub Action that reviews every pull request inside a [BoxLite](https://boxlite.ai)\nmicroVM using Claude Code. The model runs **read-only** in a throwaway single-kernel\nsandbox — untrusted PR code never touches your CI runner — and a trusted runner-side step\npublishes the result as **inline review comments**, **one sticky summary**, and **one\ncheck run**.\n\nIt is a **consumer of app.boxlite.ai**, not part of it: GitHub Actions triggers the run,\nthe review boots on your own BoxLite org, and your keys stay in your own GitHub Secrets.\nBoxLite never custodies your credentials.\n\n## Quick start\n\n1. Add secrets (repo or org → Settings → Secrets and variables → Actions):\n   - `BOXLITE_API_KEY` — your app.boxlite.ai org key (`blk_live_…`)\n   - **one** Claude credential:\n     - `ANTHROPIC_API_KEY` — an Anthropic Console API key (`sk-ant-api…`), or\n     - `CLAUDE_CODE_OAUTH_TOKEN` — a Claude Pro/Max subscription token from\n       `claude setup-token` (`sk-ant-oat…`). Draws on your subscription's limits;\n       the box runs genuine Claude Code, so this is a sanctioned use.\n2. Add `.github/workflows/boxlite-review.yml` (see [`examples/caller-workflow.yml`](examples/caller-workflow.yml)):\n\n   ```yaml\n   name: boxlite-review\n   on:\n     pull_request:\n       types: [opened, synchronize, reopened, ready_for_review]\n     issue_comment:            # optional: `@boxlite review` re-runs on demand\n       types: [created]\n   jobs:\n     review:\n       if: ${{ github.event_name != 'issue_comment' || contains(github.event.comment.body, '@boxlite review') }}\n       runs-on: ubuntu-latest\n       permissions: { contents: read, pull-requests: write, checks: write }\n       steps:\n         - uses: boxlite-ai/pr-review-agent@v1\n           with:\n             boxlite-api-key: ${{ secrets.BOXLITE_API_KEY }}\n             anthropic-api-key: ${{ secrets.ANTHROPIC_API_KEY }}\n   ```\n\nOpen a PR — inline comments and a summary appear in a minute or two. Push a commit and the\nreview refreshes in place. Comment `@boxlite review` to re-run.\n\n## What you get\n\n- **Inline comments** on the changed lines — a severity badge (🛑 blocker / ⚠️ warning /\n  🧹 nit) and, where it applies, a one-click committable ` ```suggestion `. Posted as a\n  single review (one notification), not a comment storm.\n- **A sticky summary** — a one-line verdict and a compact call-graph of the change\n  (file → symbol → ±LOC → note). Findings that fall outside the diff collapse into it.\n- **A check run** — `success` when clean, `neutral` when there are findings (it never\n  blocks merges), with the findings as annotations.\n\n## Branded bot (optional, one-click install)\n\nBy default comments post as `github-actions[bot]`. To post as your own `your-app[bot]`:\n\n1. Register a GitHub App (Settings → Developer settings → GitHub Apps). Permissions:\n   **Pull requests: Read \u0026 write**, **Checks: Read \u0026 write**, **Contents: Read**,\n   **Metadata: Read**. Generate a private key.\n2. Install it on the target repos (this is the one-click experience).\n3. Store the App id and private key as secrets (`BOXLITE_REVIEWER_APP_ID`,\n   `BOXLITE_REVIEWER_APP_PRIVATE_KEY`) and pass them:\n\n   ```yaml\n   - uses: boxlite-ai/pr-review-agent@v1\n     with:\n       boxlite-api-key: ${{ secrets.BOXLITE_API_KEY }}\n       anthropic-api-key: ${{ secrets.ANTHROPIC_API_KEY }}\n       app-id: ${{ secrets.BOXLITE_REVIEWER_APP_ID }}\n       app-private-key: ${{ secrets.BOXLITE_REVIEWER_APP_PRIVATE_KEY }}\n   ```\n\nThe Action mints a short-lived, repo-scoped installation token from the App key via\n[`actions/create-github-app-token`](https://github.com/actions/create-github-app-token).\n\nThe App private key is *your* master credential — with `app-private-key` it lives in the\nsecrets of repos/orgs **you** control. To let it stay yours while **anyone** installs the\nbot, use the broker below instead.\n\n### Public `@boxlite` bot (anyone can install)\n\nTo let *anyone* install the bot and have reviews post as `@boxlite[bot]` — without handing\nyour App key to every caller — run the token broker in [`broker/`](broker/README.md): a\ntiny Cloudflare Worker that holds the App key and vends a per-repo, least-privilege token\nafter verifying each run's GitHub OIDC claim. Callers then just install `@boxlite` and add\n`broker-url:` (with `id-token: write`) — no App key in their repo:\n\n```yaml\npermissions: { contents: read, pull-requests: write, checks: write, id-token: write }\nsteps:\n  - uses: boxlite-ai/pr-review-agent@v1\n    with:\n      boxlite-api-key: ${{ secrets.BOXLITE_API_KEY }}\n      anthropic-api-key: ${{ secrets.ANTHROPIC_API_KEY }}\n      broker-url: https://boxlite-token-broker.\u003cyou\u003e.workers.dev\n```\n\n## How it works\n\n```\nPR opened / pushed / `@boxlite review`\n      │  GitHub fires the workflow (your Actions minutes)\n      ▼\nGitHub-hosted runner  ── trigger + publisher (this Action)\n   holds for this job only: GH token (App or github.token) + your 2 secrets\n      │  JsBoxlite.rest(app.boxlite.ai, your BOXLITE_API_KEY)\n      ▼\nBoxLite microVM  ── booted in YOUR org, isolated single-kernel sandbox\n   clone PR → `claude -p` reviews the diff (read-only tools, no write token)\n   → prints structured findings JSON\n      │  findings travel back over the exec channel\n      ▼\nrunner publishes: inline review + sticky summary + check run\n      │\n      ▼\nrunner deletes the box → compute back to zero\n```\n\nThe box only reads and reasons; **every GitHub write happens on the runner**. Secrets\nreach the box **per-exec** — never baked into the box image or persisted in box env. The\nin-box entrypoint is pure Node ([`payload/pr-review/review.mjs`](payload/pr-review/review.mjs));\nthe publisher is [`lib/publish.mjs`](lib/publish.mjs).\n\n## Security model\n\n- **No custody.** Your BoxLite and Anthropic keys live in your GitHub Secrets and reach\n  the box per-exec. Nothing is stored on a BoxLite-run service.\n- **Isolation.** Each review runs in its own microVM kernel — a throwaway VM, so untrusted\n  PR code is isolated from your CI runner and host.\n- **The box makes no GitHub writes.** The clone token is scrubbed from `.git/config`\n  before the model starts, and Claude runs read-only (`Read`, `Grep`, `Glob`, and\n  `git diff/log/show` only) without the write token. The runner does all posting.\n- **Fork PRs.** `pull_request` runs from forks don't receive secrets (GitHub policy), so\n  this reviews same-repo PRs. Reviewing fork PRs needs the hosted-App path.\n\n## Repository configuration\n\n`payload/pr-review/prompt.md` is the base review policy. For per-repo tuning, add\n`.boxlite-review.yml` at the repo root:\n\n```yaml\npath_filters:                 # globs; `!` excludes. Findings under excluded paths are dropped.\n  - \"src/**\"\n  - \"!**/*.lock\"\n  - \"!dist/**\"\npath_instructions:            # extra guidance for matching files\n  - path: \"**/*.test.ts\"\n    instructions: \"Focus on edge-case coverage.\"\nfocus: \"security and concurrency\"   # extra emphasis for the whole review\nlanguage: \"zh-CN\"             # language for the review prose (default: English)\nprofile: \"lean\"               # lean = high-signal · strict = also flag nits\n```\n\n## Local dry run\n\nTest the whole pipeline from a laptop against a real microVM, no GitHub App:\n\n```bash\nnpm install --no-save @boxlite-ai/boxlite yaml\nexport BOXLITE_API_KEY=blk_live_…\nexport ANTHROPIC_API_KEY=sk-ant-…            # or: export CLAUDE_CODE_OAUTH_TOKEN=sk-ant-oat…\nexport REPO=owner/repo PR_NUMBER=\u003cn\u003e GH_TOKEN=$(gh auth token) BASE_REF=main\nexport HEAD_SHA=$(gh pr view $PR_NUMBER --repo $REPO --json headRefOid -q .headRefOid)\nnode orchestrate.mjs\n```\n\nInline comments + a sticky summary on the PR mean the pipeline works.\n\n## Tests\n\nPure logic is unit-tested (no network, no microVM):\n\n```bash\nnode --test test/*.test.mjs\n```\n\nCovers the findings contract (`lib/findings.mjs`), diff-mapping and rendering\n(`lib/publish.mjs`), config globs (`lib/config.mjs`), the sticky-comment upsert\n(`lib/comment.mjs`), prompt assembly (`payload/pr-review/review.mjs`), and Claude\ncredential selection (`lib/credential.mjs`).\n\n## Inputs\n\n| Input | Required | Default | Notes |\n|---|---|---|---|\n| `boxlite-api-key` | yes | — | Boots the review box in your org |\n| `anthropic-api-key` | one of | — | Anthropic Console API key |\n| `claude-code-oauth-token` | one of | — | `claude setup-token` subscription token |\n| `boxlite-url` | no | `https://app.boxlite.ai/api` | REST base URL |\n| `boxlite-image` | no | curated node image | Box image (must be curated) |\n| `model` | no | Claude Code default | Explicit model id; empty tracks the latest |\n| `trigger-phrase` | no | `@boxlite review` | Comment phrase that re-runs a review |\n| `app-id` / `app-private-key` | no | — | Set both for the branded bot |\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fboxlite-ai%2Fpr-review-agent","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fboxlite-ai%2Fpr-review-agent","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fboxlite-ai%2Fpr-review-agent/lists"}