{"slug": "show-hn-open-source-greptile-alternative", "title": "Show HN: Open-Source Greptile Alternative", "summary": "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.", "body_md": "\n\n```\nnpx juror-ai review --pr 1234\n```\n\n**N frontier models review your PR in parallel, each through its own native agent\nharness. Reports about the same defect collapse into one. Every review prints its own\nreceipt.**\n\nThree 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.\n\n**1 — Drop in the workflow.** Save this as `.github/workflows/juror.yml`\n\n:\n\n```\nname: Juror\non:\n  pull_request:\n    types: [opened, synchronize, reopened]\npermissions:\n  contents: read\n  pull-requests: write\njobs:\n  review:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v4\n        with: { fetch-depth: 0 }   # full history: review policy is read from the base revision\n      - uses: juror-ai/juror@v1\n        with:\n          github-token: ${{ secrets.GITHUB_TOKEN }}\n        env:\n          JUROR_OPENAI_API_KEY:    ${{ secrets.JUROR_OPENAI_API_KEY }}\n          JUROR_ANTHROPIC_API_KEY: ${{ secrets.JUROR_ANTHROPIC_API_KEY }}\n          JUROR_XAI_API_KEY:       ${{ secrets.JUROR_XAI_API_KEY }}\n          JUROR_FIREWORKS_API_KEY: ${{ secrets.JUROR_FIREWORKS_API_KEY }}\n```\n\n**2 — Add at least one provider key.** *Settings → Secrets and variables → Actions*, or from\nyour terminal:\n\n```\ngh secret set JUROR_OPENAI_API_KEY      # one key is enough to start\ngh secret set JUROR_ANTHROPIC_API_KEY   # every extra key adds another juror\n```\n\nIssue Juror its **own** provider key rather than reusing an existing one. Review spend then\nappears as its own line in provider billing, and you can rotate or cap it without touching\nanything else you run. The unprefixed names (`OPENAI_API_KEY`\n\n, …) still work as a fallback,\nso an existing install keeps running; a prefixed key wins when both are set.\n\nAny 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.\n\n**3 — Open a pull request.** Juror posts a sticky *Juror is reviewing…* comment right away,\nthen replaces it in place with the findings, the merge score, and the bill.\n\nThat's the whole setup — `.juror.yml`\n\nis optional, and every default is listed under\n[Configuration](#configuration).\n\n**Want to try it on a real PR before committing a workflow file?**\n\nSame binary, same code path, nothing posted unless you ask:\n\n```\nexport JUROR_OPENAI_API_KEY=…\nnpx juror-ai review --pr 1234 --repo owner/name          # prints to your terminal\nnpx juror-ai review --pr 1234 --repo owner/name --post   # ...and posts it\n```\n\nSingle-model PR bots have three problems, in order of how much they cost you:\n\n**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.\n\nJuror runs several models, uses code-aware similarity plus a conservative referee to\ndeduplicate reports about the same defect, and defaults to high recall: every unique\neligible finding is shown. Teams that\nprefer fewer, higher-confidence findings can switch `review.publish_mode`\n\nto `consensus`\n\nand use model agreement as a precision filter.\n\nAnd 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.\n\n**Non-goals.** Not an autofix bot. Not a linter (yours is better and free). Not a chat\ninterface. It reviews a diff and posts findings.\n\nEach 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:\n\n**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.\n\nIn `consensus`\n\nmode an additional **verify** stage runs: eligible P0/P1 and eligible\nsingle-model findings get an adversarial refutation pass. The verifier is asked to\n*refute*, and defaults to refuted when the evidence isn't clear.\n\nOne sticky summary comment, and inline comments delivered as **a single batched review** —\none notification, not twelve. Roughly:\n\nAdds SSE\n\n`event: error`\n\ndetection to the reasoning stream so mid-stream provider failures retry instead of ending the turn as a silent success.\n\nModel votes: GPT-5.6 Terra`4`\n\n· Grok 4.5`5`\n\n· Kimi K3`4`\n\n→ median4, capped at4.5by 1 confirmed P2.\n\nSeverity Location Finding Agreement 1 P1 `src/stream/parse.ts:212`\n\nError branch leaves the reader unlocked `●●●`\n\n3/32 P2 `src/stream/parse.ts:424`\n\nSame swallow pattern not ported to the sibling class `●○○`\n\n1/3## 2 findings suppressed — below severity floor\n\nLocation Finding Raised by Why suppressed `src/stream/parse.ts:387`\n\n`chunks_emitted`\n\nhardcoded on error eventsGPT-5.6 Terra, Kimi K3 below severity floor\n\n💸 This review cost $0.91· 3 models · 2m14s\n\nModel Harness Input Cached Output Cost Source `GPT-5.6 Terra`\n\nCodex 39.8k 12.1k 8.9k $0.34 estimated `Grok 4.5`\n\nGrok Build 40.1k 0 5.2k $0.38 reported `Kimi K3`\n\nKimi Code 42.0k 10.0k 4.2k $0.19 estimated `referee (1 call)`\n\nopencode — — — $0.0011 reported Total122k22.1k18.3k$0.91\n\nPlus a file-by-file overview and an optional sequence diagram of the changed flow.\n\nWith `--post`\n\n, Juror immediately creates one sticky **Juror is reviewing…** comment with an\nanimated working indicator and a short progress checklist. The finished summary replaces\nthat same comment in place; failed runs replace it with a terminal error state instead of\nleaving a spinner behind forever.\n\nThe workflow file is in [Add it to your repo](#add-it-to-your-repo) above. Beyond\n`github-token`\n\n, every Action input is optional: `preset`\n\n, `models`\n\n, `config`\n\n,\n`cost-target-usd`\n\n, `post`\n\n(set `false`\n\nfor a dry run), and `pr-number`\n\n. They are documented\nwith their defaults in [ action.yml](/Juror-AI/juror/blob/main/action.yml).\n\nThe same binary, the same code path, no CI-only surprises:\n\n```\nnpm i -g juror-ai\n\njuror review --base main                         # review your working branch\njuror review --pr 1234 --repo owner/name         # review a PR, print to the terminal\njuror review --pr 1234 --repo owner/name --post  # ...and post it\n```\n\nPut your keys in a `.env`\n\nbeside the repo (it is loaded automatically and never committed).\nJuror copies only committed/staged/tracked working changes into a detached model checkout,\nso this untracked file is not inside any reviewer read root:\n\n```\nJUROR_ANTHROPIC_API_KEY=…\nJUROR_OPENAI_API_KEY=…\nJUROR_FIREWORKS_API_KEY=…\nJUROR_XAI_API_KEY=…\n```\n\nJuror drives each model through its **native agent harness**, so each one greps your repo\nthe way its vendor intended.\n\n| Harness | CLI | Models | Reports cost | Sandbox |\n|---|---|---|---|---|\n`claude-code` |\n`claude -p` |\nany Anthropic model | ✅ `total_cost_usd` |\ntool removal |\n`codex` |\n`codex exec` |\nany OpenAI model | ❌ → estimated | split filesystem profile (kernel) |\n`opencode` |\n`opencode run` |\nanything on\n|\n\n`cost`\n\n`grok-build`\n\n`grok -p`\n\n`total_cost_usd`\n\n`kimi-code`\n\n`kimi -p`\n\n`generic-openai`\n\n*(in-process)*The `opencode`\n\nharness is the reason adding a model is a config edit rather than a PR. To add\n**DeepSeek V4 Flash** to your jury:\n\n```\nmodels:\n  - id: deepseek-v4-flash-0731\n    harness: opencode\n    harness_model: fireworks-ai/accounts/fireworks/models/deepseek-v4-flash-0731\n    pricing_key: accounts/fireworks/models/deepseek-v4-flash-0731\n    secret: JUROR_FIREWORKS_API_KEY\n    args: { variant: high }\n```\n\nJuror ships four jury presets. Models whose provider key is unavailable are skipped, so\n`ultra`\n\nmeans every built-in model that can actually authenticate on that runner.\n\n| Preset | Jury | Intended use |\n|---|---|---|\n`fast` (default) |\nGPT-5.6 Luna via Codex/OpenAI (`high` ) · DeepSeek V4 Flash via opencode/Fireworks (`high` ) |\nSmallest, cheapest jury |\n`balanced` |\nGPT-5.6 Terra via Codex/OpenAI (`max` ) · Grok 4.5 via Grok Build/xAI (`high` ) · Kimi K3 via Kimi Code/Fireworks (`max` ) |\nStrong provider diversity without the full burn |\n`high` |\nGPT-5.6 Sol via Codex/OpenAI (`high` ) · Opus 5 via Claude Code/Anthropic · Grok 4.5 via Grok Build/xAI (`high` ) |\nHigher-confidence frontier jury |\n`ultra` |\nEvery model from the other presets (seven total), using their higher reasoning settings | Maximum coverage; highest token and cost use |\n\nSelect one in config, on the CLI, or in the Action:\n\n```\njuror review --preset fast --base main\njuror review --mode ultra --pr 1234 --repo owner/name\n- uses: juror-ai/juror@v1\n  with:\n    preset: high\n```\n\n`.juror.yml`\n\nlives at the repo root. Every key is optional; the defaults are what you see below.\n\n```\nversion: 1\npreset: fast\n\nconsensus:\n  min_agreement: all             # all (literal unanimity) | majority | <number>\n  verify_solo_findings: true     # adversarially refute eligible solo findings\n  # verify_model/referee_model default to a model included in the selected preset\n\nreview:\n  publish_mode: all              # all (higher recall) | consensus (higher precision)\n  severity_floor: P3             # include every severity by default\n  max_inline_comments: 15\n  paths_ignore: [\"**/*.lock\", \"dist/**\", \"**/*.generated.*\"]\n\nbudget:\n  target_cost_usd_per_pr: 5.00   # planning target; actual spend remains in the receipt\n  on_exceed: partial             # affordable subset | skip\n\noutput:\n  sequence_diagram: true\n  cost_receipt: true\n  suppressed_findings: collapsed # collapsed | hidden | inline\n```\n\nAn explicit `models:`\n\nlist replaces the preset completely and creates a custom jury; it is\nnever merged with built-ins. `--models a,b`\n\nis different: it only narrows the selected preset\nor custom jury for one run. `--preset`\n\nand its `--mode`\n\nalias override the config selection.\n\nPublication is controlled independently from deduplication.\n\n`publish_mode: all`\n\n*(default, higher recall)*publishes every unique cluster at or above`severity_floor`\n\n(also P3 by default). Agreement is still shown, but it does not hide a finding.`publish_mode: consensus`\n\n*(higher precision)*applies the configured agreement and verification rules. The default`consensus.min_agreement: all`\n\nmeans every model must raise the finding.\n\nWith `min_agreement: all`\n\n, publication requires literal unanimity. If users deliberately\nchoose `majority`\n\nor a numeric threshold, serious findings retain the safety exceptions:\n\n```\npublish if  agreement >= configured min_agreement\n        or (agreement >= 2 and severity in {P0,P1})\n        or (agreement == 1 and severity in {P0,P1} and survived refutation)\n```\n\nAnything filtered out lands in the collapsed **suppressed** block with the reason. Nothing\nis thrown away — that transparency is what makes the optional precision filter trustworthy.\n\nReplacement decisions can be evaluated with a manually adjudicated corpus:\n\n```\njuror benchmark --file benchmarks/platform-10359.json\n```\n\nThe report compares P0–P2 recall, overall recall, precision, duplicate rate, measured cost,\nand latency for every reviewer. See [the benchmarking protocol](/Juror-AI/juror/blob/main/docs/benchmarking.md); the\nbundled PR #10359 case is a seed, not a sufficient replacement benchmark by itself.\n\nNot a model opinion — a deterministic function of published findings, with the votes shown so the arithmetic is auditable.\n\n```\nbase    = median(each model's self-reported merge confidence)\npenalty = 2·P0 + 1·P1 + min(1, 0.5·P2)     (confirmed, published findings only)\nscore   = clamp(round(min(base, 5 - penalty)), 1, 5)\n```\n\n`min(base, 5 - penalty)`\n\nis the load-bearing part: models cannot vote away a confirmed\nblocker, and a clean diff still can't reach 5 if the models were individually unsure.\n\nThe differentiator, and the thing that must never be wrong.\n\n**Never fabricate.** Every figure is labeled`reported`\n\n(provider-computed) or`estimated`\n\n(tokens × list price). A harness that returns neither prints, and the total is marked as a lower bound. We do not guess.`unknown`\n\n**Long-context tiers are cliffs, not slopes.** GPT-5.6 Sol reprices the*entire request*at 2× input above 272k tokens; Grok 4.5 does the same above 200k. A flat per-token config silently underbills exactly the large-diff reviews that cost the most. When a harness only exposes aggregate multi-turn usage, Juror reports the standard-tier subtotal as a lower bound instead of guessing which individual requests crossed the cliff.**Cache writes are not free.** On GPT-5.6 and later they bill at 1.25× the uncached input rate. Anthropic bills them too. Juror models a review as write-once, read-many: the first model to see a diff pays the write premium, and re-reviews on later pushes get cheap.**Codex** Normalizing naively overbills a cache-heavy Codex run by up to an order of magnitude. There is a regression test pinned to a real`input_tokens`\n\nincludes cached tokens; Claude's and opencode's do not.`turn.completed`\n\npayload for exactly this. A Codex turn can contain several provider requests, so its aggregate is never treated as one request when deciding whether a long-context price cliff applies.**Kimi K3 runs through Fireworks.** Kimi Code exposes token usage but not provider USD, so Juror multiplies those measured tokens by the versioned Fireworks list price and labels the row`estimated`\n\n.\n\n`src/cost/pricing.json`\n\nis versioned, dated, and every entry carries a source URL.\n\n`budget.target_cost_usd_per_pr`\n\nis deliberately a planning target, not a promise that every\nprovider can enforce a hard cap. Juror estimates only models whose keys are present and, in\n`partial`\n\nmode, runs the subset estimated to fit. Claude also receives a native spend limit.\nActual usage can still cross the target on providers without that facility; the receipt and\nreview warnings report the overage instead of relabeling the estimate as a ceiling.\n\nThis is a bot that pipes attacker-controlled text into an agent and then writes to your PR. It is designed for that.\n\n**No model process ever sees** Every child environment is rebuilt from an allowlist with exactly one provider credential. Publishing starts only after all jurors exit. Prompt injection can at worst produce a bad review comment — never a push or merge.`GITHUB_TOKEN`\n\n.**Default trigger is** Fork PRs get no secrets and no review, by design.`pull_request`\n\n, not`pull_request_target`\n\n.**The repository is read-only to every juror.** Codex uses a kernel-enforced split filesystem profile that exposes only runtime files, the sealed checkout, and Juror scratch; its model-controlled shells inherit no process environment or shell snapshot, so the provider credential remains available to the Codex client but not to commands it runs. Claude, Grok Build, opencode, and Kimi receive read/search tools only. Generic OpenAI resolves symlinks and may write only one exact report path outside the repository. Claude, Codex, and Kimi start from private temporary directories so PR-controlled hooks, MCP, settings, and`AGENTS.md`\n\nare not auto-loaded. Every run reads a detached checkout that excludes untracked operator files such as`.env`\n\n; after trusted base policy is loaded, Juror also removes the worktree's pointer back to credential-bearing git metadata. A workspace guard remains as defense in depth for direct library callers.**Keys are passed per harness**, never to all of them. Each model process gets an environment containing only its own provider key.** Injection is a finding.**Each model is told the diff is untrusted data and to report embedded instructions as a P0. Several independent models make a uniform injection substantially harder.**Repository rules come from the base revision.** Juror places the root`AGENTS.md`\n\nand every applicable nested`AGENTS.md`\n\ndirectly in reviewer and verifier prompts. A PR can update those files for future work, but cannot rewrite the policy used to review itself. If the base object is unavailable locally, Juror warns and refuses to treat any workspace copy as policy; use a full checkout (`fetch-depth: 0`\n\n) so the trusted rules can be loaded. The GitHub PR title and description are also included as explicitly untrusted intent context, so reviewers can recognize documented staged migrations without treating author claims as proof or executable instructions.**Execution configuration also comes from the base revision.** A pull request cannot redirect a provider endpoint, select`GITHUB_TOKEN`\n\nas a model secret, or enable a new harness while it is being reviewed. If the base object is unavailable, secure defaults win.**Everything posted is redacted** for secret-shaped strings first.\n\n- Cost for Codex is\n**estimated**, not reported — the CLI exposes tokens but no dollar figure. - Cost for Kimi Code is\n**estimated** from its private session usage records and the versioned Fireworks rate. If those records are unavailable, it falls back to`unknown`\n\n. - Grok Build's headless JSON shape is parsed defensively and marked\n`unknown`\n\nwhen the fields aren't there, rather than guessed at. - Agreement filtering needs ≥2 models to mean anything. With one key configured, the default all-findings mode still gives you a complete single-model review and an honest receipt, but there is no cross-model precision signal.\n- Findings anchored outside the diff are surfaced in the summary but not posted inline, because GitHub can't attach them.\n- The spend target is estimate-based for providers without native budget enforcement. Actual spend is always shown and can be slightly higher than the target.\n- The 30-day rolling receipt is shown only when Juror has persistent local/self-hosted state; GitHub-hosted runners omit it instead of presenting a one-run ledger as a monthly total.\n\n```\nnpm ci\nnpm run typecheck\nnpm test\nnpm run build\nnode dist/cli.js review --base main\n```\n\nLayout follows the pipeline: `src/diff`\n\n→ `src/harness`\n\n→ `src/merge`\n\n→ `src/cost`\n\n→\n`src/render`\n\n→ `src/github`\n\n. `src/types.ts`\n\nis the only shared vocabulary.\n\nJuror reviews its own pull requests. Every PR in this repo carries a public cost receipt.\n\nMIT.", "url": "https://wpnews.pro/news/show-hn-open-source-greptile-alternative", "canonical_source": "https://github.com/Juror-AI/juror", "published_at": "2026-08-10 14:17:13+00:00", "updated_at": "2026-08-10 16:25:28.049240+00:00", "lang": "en", "topics": ["ai-tools", "developer-tools", "artificial-intelligence", "large-language-models"], "entities": ["Juror AI", "Greptile", "GitHub Actions", "OpenAI", "Anthropic", "xAI", "Fireworks"], "alternates": {"html": "https://wpnews.pro/news/show-hn-open-source-greptile-alternative", "markdown": "https://wpnews.pro/news/show-hn-open-source-greptile-alternative.md", "text": "https://wpnews.pro/news/show-hn-open-source-greptile-alternative.txt", "jsonld": "https://wpnews.pro/news/show-hn-open-source-greptile-alternative.jsonld"}}