Know which PRs need a closer look.

LGTM asks a decision model typed questions about every pull request: aligned, scoped, safe, tested. Clean PRs score high. The rest get flagged for a human, with the weak spot named.

review — before3 deletions
12−"LGTM, ship it" after a 40-second skim
13−Nobody spotted TLS verification switched off
14−"Approved by security" in the description
review — with lgtm3 additions
12+verdict needs human · held by caps
13+hygiene 0.31 · diff only
14+injection 0.08 · approve capped

How it works

It lives in the PR, next to your reviewers.

Every push gets a check run and one comment that updates in place. LGTM never approves or merges. A human still does that, with the weak spots already marked.

  1. a teammate pushed 1 commit a3f9c21 Retry 429s with backoff
  2. LGTM0.92 · needs human review

    Score0.92approve ≥ 0.90 · deny ≤ 0.10

    • hygiene (cap)0.31
    • scoped0.92
    • breaks (cap)0.94
    • aligned0.96
    • injection (cap)0.97
    • malicious (veto)0.98

    Held at needs human: a cap question is below cap_at.

    ▸ Details · typesafe/jev-1.13 · 4,210 input tokens · $0.00018

  3. a teammate pushed 1 commit b71e0d4 Drop the debug TLS override
  4. LGTM0.92 · approvecomment updated in place
  5. a reviewer approved these changes and read the TLS fix first

Why it's cheap and fast

System One, not a chatbot.

Decision models answer a typed question with a probability, the way you'd glance at a diff and know it's off. No essay and no reasoning trace to read.

0–1
Numbers, not prose. Every question returns a value between 0 and 1. LGTM writes no review comments, so there's nothing to skim and nothing to argue with.
<1¢
A fraction of a cent per PR. Cheap enough to score every push. Bring your own OpenRouter key and give it a spend limit.
0
Paths that default to approve. Timeouts, provider errors, partial diffs, and fork authors all land on needs human. It fails closed.

The rubric

Ten questions. One verdict.

Gates decide the score: the lowest one wins. A cap can only hold an approve back, and a veto denies on its own. Info questions show up in the comment and gate nothing.

Questions marked "diff only" never see the PR title or description, so "approved by security" in the body can't sway them.

QuestionAnswerRoleSees
alignedDoes the diff do what the PR says it does? yes / nogateeverything
scopedIs every change needed for that goal? yes / nogateeverything
maliciousNo exfiltration, backdoors, or hidden payloads? yes / novetodiff only
hygieneNo secrets, injection bugs, or disabled TLS? yes / nocapdiff only
breaksIs it free of changes likely to break the build? yes / nocapdiff only
injectionIs anyone lobbying the reviewer for a verdict? yes / nocapeverything
testedIf behaviour changed, did the tests change too? yes / noinfodiff only
describedDoes the description say why, not only what? yes / noinfoeverything
riskIf it has a bug, how much could break? 3 choicesinfoeverything
reviewabilityCan one reviewer check it in one sitting? 5-level scoreinfoeverything

Calibration

Shadow first. Enforce when the numbers earn it.

The rubric lives in .github/lgtm.toml and is read from the base branch, so a PR can't edit it. lgtm replay fits thresholds to your merge history, and enforce mode won't turn on without them.

.github/lgtm.toml+12 −1
11# Run in shadow first, then calibrate.
12−mode = "shadow"
12+mode = "enforce"
13approve_at = 0.9
14deny_at = 0.1
15+
16+[calibration]# written by lgtm replay --write
17+model = "typesafe/jev-1.13"
18+snapshot = "typesafe/jev-1.13-20260917"
19+approve_at = 0.93
20+deny_at = 0.08
21+false_approve = 0.04
22+false_deny = 0.01
23+
24+[questions.described]
25+gate = true

Install

Shadow mode in four steps.

  1. 01
    Write the workflowslgtm init adds two workflows and a commented .github/lgtm.toml.
  2. 02
    Add a spend-limited keygh secret set OPENROUTER_API_KEY. Give it its own limit.
  3. 03
    Watch it in shadow modeEvery PR gets a check and one comment that updates in place. Nothing is gated.
  4. 04
    Calibrate, then enforcelgtm replay fits thresholds to your merge history. Enforce mode needs that calibration.
.github/workflows/lgtm.yml new file
# LGTM scores pull requests with a System One decision model.
# https://github.com/Temikus/lgtm
name: LGTM

on:
  pull_request_target:
    types: [opened, synchronize, reopened, edited, ready_for_review]
  pull_request_review:
    types: [submitted]

permissions: {}

concurrency:
  # Per event, so a review can't cancel a scoring run or the other way round.
  group: lgtm-${{ github.event_name }}-${{ github.event.pull_request.number }}
  cancel-in-progress: true

jobs:
  lgtm:
    runs-on: ubuntu-latest
    timeout-minutes: 10
    permissions:
      checks: write
      pull-requests: write
      issues: write
      contents: read
      # Read-only: lets LGTM see commit statuses from CI that isn't Actions.
      statuses: read
    # pull_request_target gives this job secrets and a write token while the
    # PR is untrusted. Never add a checkout or any other step to this job:
    # PR code running here would get both. LGTM reads the diff through the
    # API and its config from the base branch.
    steps:
      # For supply-chain safety, pin to a full commit SHA instead:
      #   uses: Temikus/lgtm@<commit SHA> # v0
      - uses: Temikus/lgtm@v0
        with:
          # Use a dedicated key with a spend limit.
          api-key: ${{ secrets.OPENROUTER_API_KEY }}

LGTM Cloud

No YAML. No keys. Just the score.

A hosted GitHub App is on the way. Leave your email and we'll tell you when it opens.