Product · Code Review

6 specialists per PR.
Not 1 generalist guessing.

Every pull request is reviewed by six agents in parallel — each looking for one specific kind of problem — then merged into one verdict with deduped inline comments. 30 to 90 seconds. Bring your own OpenAI / Anthropic / Gemini key.

20 reviews/mo free · No card · Counts roll over

How a review actually runs

One pipeline. Five stages. Streamed live to the dashboard so you watch the agents finish in real time.

Step 1

Webhook received

GitHub fires pull_request opened/synchronize/reopened. Signature verified via X-Hub-Signature-256, idempotency keyed by X-GitHub-Delivery.

Step 2

Diff + context

Diff fetched via App installation token (15s timeout, 3 retries). If the repo is indexed, tree-sitter symbols referenced in the diff get attached to agent prompts.

Step 3

6 agents (parallel)

One BullMQ job per agent. Each gets the diff + relevant context + a system prompt scoped to its role. LLM call runs on YOUR BYOK key with the resolved provider + model.

Step 4

Synthesizer

Receives all six reports + diff + custom guidelines. Outputs the final verdict + summary + dedup'd inline comments mapped to (file, line).

Step 5

Posted to GitHub

Single POST to /repos/{...}/pulls/{pr}/reviews. If GitHub rejects 422 (force-push race), we retry without inline comments, posting just the summary.

Meet the six agents

Each agent has one job. Specialists outperform generalists because they don't spread attention thin trying to check everything at once.

Bugs

Catches what causes incidents

What it catches

  • ·Null derefs and missing await
  • ·Off-by-one and boundary bugs
  • ·Race conditions in async code
  • ·Returning wrong types under edge cases
  • ·Unhandled error paths

Sample finding

`getUser(id)` can return undefined when the cache misses — but line 42 calls `.email` on it without a guard.

Security

OWASP top-10 on the diff hunks

What it catches

  • ·SQL / NoSQL injection
  • ·Cross-site scripting (XSS)
  • ·Broken auth + missing authz
  • ·Secrets in the diff
  • ·Weak crypto / hashing

Sample finding

User-controlled `repoId` flows into `Repo.findOne({ _id: repoId })` without ObjectId validation — Mongoose will accept arbitrary objects.

Performance

Hot-path regressions, not micro-opts

What it catches

  • ·N+1 queries in loops
  • ·Blocking I/O on the request path
  • ·Regex catastrophic backtracking
  • ·Unnecessary re-renders / hook deps
  • ·Missing pagination on unbounded lists

Sample finding

The loop on line 88 hits `User.findById(c.author)` per comment — 1 + N queries. Use a single `find({ _id: { $in: authors } })`.

Readability

Future you will thank present you

What it catches

  • ·Variables named `data` / `result` / `temp`
  • ·Functions over 60 lines or 4 nesting levels
  • ·Magic numbers + strings
  • ·Dead code, unreachable branches
  • ·Clever > clear

Sample finding

`fn(d, t, x)` — what are `d`, `t`, `x`? The body uses them as `diff`, `target`, and `xform` — say that.

Best practices

Language and framework idioms

What it catches

  • ·TS: `any` where a real type is obvious
  • ·React: missing useEffect deps
  • ·Express: middleware order wrong
  • ·Go: error wrapping skipped
  • ·Python: `mut_default = []` in args

Sample finding

`useEffect(() => { fetchPR(); }, [])` — missing `id` in the dep array. PR ID changes won't trigger re-fetch.

Documentation

Stale comments are worse than none

What it catches

  • ·Missing JSDoc on exported functions
  • ·Comments that contradict the code
  • ·Stale TODOs and FIXMEs
  • ·Public API without examples
  • ·README claims vs code reality

Sample finding

The function comment says 'returns null on missing user' but the body now throws. Update the comment or restore the null return.

The merger

One verdict, not six conflicting opinions

After the six agents finish, a synthesizer agent reads all six reports plus the diff plus any per-repo review guidelines you've set. It produces:

  • Overall verdict

    approve · request_changes · comment

  • Executive summary

    2-4 sentences explaining the verdict to a busy reviewer.

  • Confidence score

    0-100 — how certain the model is. Below 50 = manual review recommended.

  • Dedup'd inline comments

    Same bug flagged by Bugs + Security = one comment, not two.

Live verdict in dashboard

request_changes

Confidence 78%

"Adds the new export but doesn't handle the cache-miss case the existing tests exercise — see line 42 in user.service.ts. Suggest pulling the cache check up one frame."

Agents: 6 / 6 · Findings: 3 critical · 5 medium · 2 low · Run time: 47s

Tune it per repo

Different repos want different reviews. A monorepo for a payment API needs paranoia. A side-project Astro blog needs speed.

Focus areas

Pick a subset of the 6 agents. Repo A runs all six; Repo B only runs Bugs + Security. Saves tokens for teams who only care about a slice.

Custom review guidelines

Free-text appended to every review prompt for this repo. Drop your style guide, your no-go list, your 'we prefer X over Y' preferences.

Per-repo provider override (Pro)

Pin GPT-4o on the Rust monorepo. Pin Claude Sonnet on the React app. Different repos can run on different models without changing your default.

Auto-review on every PR (Pro)

opened / synchronize / reopened — Pro fires automatically. Free users keep the manual 'Review' button on the dashboard or `lgtm review --pr <num>`.

Real-time

Watch the agents finish, live

Socket.IO streams every step to the dashboard: review:started, agent:started / completed / failed per agent, synthesizer:started, review:completed. No polling, no spinners that never finish.

If the socket drops the dashboard shows a discreet "reconnecting…" pill — never a frozen UI.

Bugs
Security
Performance
Readability
Best-practices
Documentation

FAQ

Does LGTM store our source code?

No. We persist the parsed diff hunks the reviewers ran against, not the full repo. The tree-sitter context index stores symbol names and signatures, not source bodies. Full source is fetched fresh from GitHub at review time, held in worker memory for 30-90s, then discarded.

Can I block merges based on the verdict?

Yes — the review posts a check_run with status: failure when the verdict is request_changes. GitHub branch protection then refuses the merge. For CI/CD-specific gates (16 deterministic detectors) see LGTM Security.

What if the diff is huge?

Reviews scale linearly until the model's context window. For PRs over ~500 lines we chunk the diff per agent and have the synthesizer merge across chunks. Reviews on 2,000-line refactors still come back, just at the 90-second end of the range.

How does dedup work between agents?

The synthesizer keys findings by (file, startLine, ruleId) and merges descriptions when two agents flag the same spot. A SQL-injection callout from Bugs and Security becomes one comment with both lenses noted.

Which AI providers are supported?

OpenAI (GPT-4o, GPT-4-turbo, GPT-4o-mini, o1), Anthropic (Claude Opus, Sonnet, Haiku), Google Gemini (2.0 Pro, 2.0 Flash). BYOK — we never see your provider tokens unencrypted. Per-repo overrides on Pro.

Can I disable specific agents per repo?

Yes — the focus-areas setting per repo. Set focusAreas: ["security", "bugs"] and only those two agents run. Lower token spend, faster reviews.

Stop reviewing alone

20 reviews/month on Free. No card. Same 6 agents as Pro, same dashboard, same CLI.