Show HN: Open-Source Greptile Alternative Juror AI, an open-source alternative to Greptile, lets developers run multiple frontier AI models in parallel to review pull requests on GitHub Actions, with reports about the same defect collapsed into one and each review printing its own receipt. The tool, which requires no app install or account, runs on the user's own runner and sends code only to the model API, with setup taking about two minutes. It supports up to four provider keys (OpenAI, Anthropic, xAI, Fireworks) and defaults to high recall, with an optional consensus mode for higher-confidence findings. npx juror-ai review --pr 1234 N frontier models review your PR in parallel, each through its own native agent harness. Reports about the same defect collapse into one. Every review prints its own receipt. Three steps, about two minutes. No app to install, no account to create, no repository index to build — it runs on your own GitHub Actions runner, and your code never leaves it beyond the model API call itself. 1 — Drop in the workflow. Save this as .github/workflows/juror.yml : name: Juror on: pull request: types: opened, synchronize, reopened permissions: contents: read pull-requests: write jobs: review: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 with: { fetch-depth: 0 } full history: review policy is read from the base revision - uses: juror-ai/juror@v1 with: github-token: ${{ secrets.GITHUB TOKEN }} env: JUROR OPENAI API KEY: ${{ secrets.JUROR OPENAI API KEY }} JUROR ANTHROPIC API KEY: ${{ secrets.JUROR ANTHROPIC API KEY }} JUROR XAI API KEY: ${{ secrets.JUROR XAI API KEY }} JUROR FIREWORKS API KEY: ${{ secrets.JUROR FIREWORKS API KEY }} 2 — Add at least one provider key. Settings → Secrets and variables → Actions , or from your terminal: gh secret set JUROR OPENAI API KEY one key is enough to start gh secret set JUROR ANTHROPIC API KEY every extra key adds another juror Issue Juror its own provider key rather than reusing an existing one. Review spend then appears as its own line in provider billing, and you can rotate or cap it without touching anything else you run. The unprefixed names OPENAI API KEY , … still work as a fallback, so an existing install keeps running; a prefixed key wins when both are set. Any key you leave out is skipped with a note in the receipt. One key gets you a working single-model review; four gets you the full jury. Degrade, never fail. 3 — Open a pull request. Juror posts a sticky Juror is reviewing… comment right away, then replaces it in place with the findings, the merge score, and the bill. That's the whole setup — .juror.yml is optional, and every default is listed under Configuration configuration . Want to try it on a real PR before committing a workflow file? Same binary, same code path, nothing posted unless you ask: export JUROR OPENAI API KEY=… npx juror-ai review --pr 1234 --repo owner/name prints to your terminal npx juror-ai review --pr 1234 --repo owner/name --post ...and posts it Single-model PR bots have three problems, in order of how much they cost you: Blind spots. Every model misses different bugs. Duplication. Multiple reviewers often describe the same defect in different words. Opacity. You pay per seat or per PR and never see what the inference actually cost. Juror runs several models, uses code-aware similarity plus a conservative referee to deduplicate reports about the same defect, and defaults to high recall: every unique eligible finding is shown. Teams that prefer fewer, higher-confidence findings can switch review.publish mode to consensus and use model agreement as a precision filter. And there is no index and no SaaS. A coding agent doesn't need a prebuilt semantic index: the supported agent harnesses all ship repository read/search tools and will go inspect the callers of the function you changed. You get repo-wide context for the price of a few tool calls, with zero indexing infrastructure, zero staleness, and no code leaving the runner beyond the model API call itself. Non-goals. Not an autofix bot. Not a linter yours is better and free . Not a chat interface. It reviews a diff and posts findings. Each model gets the diff, its own private scratch directory, and read-only access to a clean detached checkout. Their findings then go through five lossless merge stages — cheapest first, with a model call only for possible semantic duplicates: Anchor free — snap every finding to a line the diff actually adds or modifies. Findings landing outside the diff are reported separately, never silently dropped. Block free — group by file, then by overlapping line window. Exact collapse free — normalized identical reports, or identical structured trigger/mechanism/consequence/fix claims, collapse without inference. Similarity + referee cheap — weighted prose/symbol similarity nominates possible duplicates. A small call per block merges them only when the faulty mechanism and fix match and their affected behavior substantially overlaps; extra entry points or effects in one report do not make the same bug new. A malformed partition is retried once, then fails open to separate findings so deduplication can never hide a report. Coverage audit free — prove every raw atomic finding belongs to exactly one final published or explicitly suppressed result. Any accounting failure discards the merge decisions and falls back to lossless singletons. In consensus mode an additional verify stage runs: eligible P0/P1 and eligible single-model findings get an adversarial refutation pass. The verifier is asked to refute , and defaults to refuted when the evidence isn't clear. One sticky summary comment, and inline comments delivered as a single batched review — one notification, not twelve. Roughly: Adds SSE event: error detection to the reasoning stream so mid-stream provider failures retry instead of ending the turn as a silent success. Model votes: GPT-5.6 Terra 4 · Grok 4.5 5 · Kimi K3 4 → median4, capped at4.5by 1 confirmed P2. Severity Location Finding Agreement 1 P1 src/stream/parse.ts:212 Error branch leaves the reader unlocked ●●● 3/32 P2 src/stream/parse.ts:424 Same swallow pattern not ported to the sibling class ●○○ 1/3 2 findings suppressed — below severity floor Location Finding Raised by Why suppressed src/stream/parse.ts:387 chunks emitted hardcoded on error eventsGPT-5.6 Terra, Kimi K3 below severity floor 💸 This review cost $0.91· 3 models · 2m14s Model Harness Input Cached Output Cost Source GPT-5.6 Terra Codex 39.8k 12.1k 8.9k $0.34 estimated Grok 4.5 Grok Build 40.1k 0 5.2k $0.38 reported Kimi K3 Kimi Code 42.0k 10.0k 4.2k $0.19 estimated referee 1 call opencode — — — $0.0011 reported Total122k22.1k18.3k$0.91 Plus a file-by-file overview and an optional sequence diagram of the changed flow. With --post , Juror immediately creates one sticky Juror is reviewing… comment with an animated working indicator and a short progress checklist. The finished summary replaces that same comment in place; failed runs replace it with a terminal error state instead of leaving a spinner behind forever. The workflow file is in Add it to your repo add-it-to-your-repo above. Beyond github-token , every Action input is optional: preset , models , config , cost-target-usd , post set false for a dry run , and pr-number . They are documented with their defaults in action.yml /Juror-AI/juror/blob/main/action.yml . The same binary, the same code path, no CI-only surprises: npm i -g juror-ai juror review --base main review your working branch juror review --pr 1234 --repo owner/name review a PR, print to the terminal juror review --pr 1234 --repo owner/name --post ...and post it Put your keys in a .env beside the repo it is loaded automatically and never committed . Juror copies only committed/staged/tracked working changes into a detached model checkout, so this untracked file is not inside any reviewer read root: JUROR ANTHROPIC API KEY=… JUROR OPENAI API KEY=… JUROR FIREWORKS API KEY=… JUROR XAI API KEY=… Juror drives each model through its native agent harness , so each one greps your repo the way its vendor intended. | Harness | CLI | Models | Reports cost | Sandbox | |---|---|---|---|---| claude-code | claude -p | any Anthropic model | ✅ total cost usd | tool removal | codex | codex exec | any OpenAI model | ❌ → estimated | split filesystem profile kernel | opencode | opencode run | anything on | cost grok-build grok -p total cost usd kimi-code kimi -p generic-openai in-process The opencode harness is the reason adding a model is a config edit rather than a PR. To add DeepSeek V4 Flash to your jury: models: - id: deepseek-v4-flash-0731 harness: opencode harness model: fireworks-ai/accounts/fireworks/models/deepseek-v4-flash-0731 pricing key: accounts/fireworks/models/deepseek-v4-flash-0731 secret: JUROR FIREWORKS API KEY args: { variant: high } Juror ships four jury presets. Models whose provider key is unavailable are skipped, so ultra means every built-in model that can actually authenticate on that runner. | Preset | Jury | Intended use | |---|---|---| fast default | GPT-5.6 Luna via Codex/OpenAI high · DeepSeek V4 Flash via opencode/Fireworks high | Smallest, cheapest jury | balanced | GPT-5.6 Terra via Codex/OpenAI max · Grok 4.5 via Grok Build/xAI high · Kimi K3 via Kimi Code/Fireworks max | Strong provider diversity without the full burn | high | GPT-5.6 Sol via Codex/OpenAI high · Opus 5 via Claude Code/Anthropic · Grok 4.5 via Grok Build/xAI high | Higher-confidence frontier jury | ultra | Every model from the other presets seven total , using their higher reasoning settings | Maximum coverage; highest token and cost use | Select one in config, on the CLI, or in the Action: juror review --preset fast --base main juror review --mode ultra --pr 1234 --repo owner/name - uses: juror-ai/juror@v1 with: preset: high .juror.yml lives at the repo root. Every key is optional; the defaults are what you see below. version: 1 preset: fast consensus: min agreement: all all literal unanimity | majority |