Your code, your AI provider, your bill.
We're the glue.
LGTM doesn't hold your code, doesn't mark up your LLM tokens, and doesn't lock you into one provider. Connect GitHub once. Add a key from OpenAI, Anthropic, or Google Gemini. Reviews run on the provider you chose, billed directly to you, with no LGTM-side per-token margin.
GitHub App
The only piece that lives on GitHub
Installed once per organisation (or per-account for solo devs). You choose which repos to grant access to — "All repositories" or a specific list, your call. Permissions are auditable from GitHub's Settings → Installed GitHub Apps page; revoke anytime.
LGTM only acts on repos you explicitly connect afterwards from the dashboard — installing the App doesn't auto-enroll every repo.
Install on GitHubBYOK
Bring your own AI provider key
Add an API key from OpenAI, Anthropic, or Google Gemini. We validate it against the provider's API before saving. AES-256-encrypted at rest with a server-side master key that lives in Fly secrets and rotates independently.
Decryption happens only inside the review worker process at the moment a review fires. Never returned to the dashboard, never logged, never sent to anyone other than your AI provider.
Add a keyWhat the GitHub App needs (and why)
Every permission below is the minimum required for a specific feature. We'd prefer fewer — GitHub requires this granularity for the features to work.
Contents
Read
Fetch PR diffs for the review agents and the source bodies the indexer references at review time. Without read, we can't see the code to review.
Pull requests
Read + Write
Read: see PR metadata (title, author, base/head). Write: post review comments + the verdict to the PR. The 'write' is scoped to PR review actions; we can't write to source files.
Checks
Write
Post the LGTM Security blocking gate as a Check Run. GitHub branch protection respects checks; without this we can't gate merges on security findings.
Metadata
Read
Required by GitHub on every App — gets us repo names, visibility, default branch. No code access.
Issues
Read
Read-only — used to cross-link PR review threads with related issues in the dashboard. We never create/edit issues.
Reviewable in GitHub. From any installed account, visit github.com/settings/installations → LGTM → Configure to see and modify exactly which repos LGTM has access to. Revoke at any time; the worst that happens is your reviews stop running.
What GitHub sends us
Webhook subscriptions are how the App knows a PR opened or a push landed. We subscribe to four events; everything else from GitHub is ignored.
pull_requestThe bread-and-butter event. Triggers the review pipeline for repos with auto-review enabled. 'closed' is used to mark the PR as no longer reviewable in the dashboard.
pushTriggers the LGTM Security watchdog to scan default-branch pushes that bypassed PR review (force pushes, admin commits). Only fires on default branch — feature branches don't generate webhooks here.
installationTracks when you install or uninstall the App. On install, we don't auto-enroll repos. On uninstall, all repo connections deactivate and webhook events stop being processed.
installation_repositoriesFires when you grant/revoke App access to specific repos within an installation. We use this to mirror what repos are visible in the 'Connect a repo' picker on the dashboard.
X-GitHub-Delivery) are deduplicated against MongoDB; replays don't re-trigger reviews.Supported AI providers
Three providers today. Adding one is a day's work plus QA — open a request if your team standardised on something else (Cohere, Mistral, AI21, etc.).
OpenAI
GPT-4o family · o-series reasoning
Models
- ·GPT-4o
- ·GPT-4-turbo
- ·GPT-4o-mini
- ·o1 (reasoning)
Key format
sk-proj-XXXX...XXXX or sk-XXXX...XXXXAnthropic
Claude family
Models
- ·Claude Opus (max)
- ·Claude Sonnet (default)
- ·Claude Haiku (fast)
Key format
sk-ant-api03-XXXX...XXXXValidation. When you add a key, LGTM hits the provider's /v1/models endpoint to confirm the key is valid + has model access. We save it only if validation succeeds. Periodic re-validation runs in the background; if a key starts failing (revoked, expired, quota exhausted) you get an in-app notification + a banner under Settings.
Encryption at rest, plaintext only in worker memory
Your provider key is the single most sensitive piece of data we hold. Here's the full lifecycle.
Receive
You paste the key into the dashboard over HTTPS. It hits our API over TLS 1.3.
Validate
API forwards the key to the provider's /v1/models endpoint to confirm it works. Plain text, in memory, ~200ms.
Encrypt
AES-256-GCM with a server-side master key. The encrypted blob (ciphertext + IV + auth tag) goes into MongoDB. The plaintext key never persists to disk.
Master key
The AES master key lives in Fly secrets, not in code or MongoDB. Rotating it is a separate operation from rotating user keys. Compromising the database alone reveals nothing readable.
Decrypt at review time
When a review starts, the worker fetches the encrypted blob, decrypts it in worker memory, makes the LLM call, then GC drops the plaintext when the function returns. No logging, no error report leaks, no debug-dump exposure.
Display
When the dashboard shows your saved keys, only a redacted prefix (sk-...AbCd) is rendered. The plaintext key is never returned by the API after the initial save.
Auditors can verify this by reading the source — server/src/utils/encryption.ts is small, single-purpose, and pinned to the Node crypto module. No third-party crypto libs.
Per-repo model overrides (Pro)
Free users have one global default provider + model. Pro users can override per repo. Useful when different repos warrant different cost / quality tradeoffs.
Example setup
| Repo | Provider | Model | Why |
|---|---|---|---|
| payments-api | Anthropic | claude-opus | High-stakes; deepest reasoning per dollar |
| web-app | OpenAI | gpt-4o | React-specific; broad knowledge |
| rust-core | OpenAI | o1 | Reasoning over lifetimes / borrow checker |
| marketing-blog | Anthropic | claude-haiku | Cheap; just needs grammar + typos |
What we keep
- GitHub username + email (from OAuth)
- GitHub installation ID + connected repos
- Encrypted AI provider keys (AES-256-GCM)
- Default provider + model preferences
- Per-repo settings (focus areas, custom guidelines)
- Reviews (summary + verdict + dedup'd inline findings)
- Symbol-graph index (names + signatures, no source bodies)
- Billing state (Dodo subscription ID, plan, usage counter)
- Webhook delivery IDs for 30 days (idempotency)
What we don't
- ×Source code bodies (parsed, indexed, discarded)
- ×Provider API keys in plain text on disk
- ×Commit messages or full diffs (beyond review-time hunks)
- ×GitHub token in unencrypted form
- ×Card numbers or payment details (handled by Dodo)
- ×IP addresses or device fingerprints (beyond rate-limit windows)
- ×Behavioural analytics or session recordings
- ×Anything from
.gitignorepaths
FAQ
Can I revoke access at any time?
What if my AI provider key gets compromised?
Are you on the AI providers' approved app lists?
Does my BYOK key need 'organisation' access?
Can the same key be used across multiple LGTM repos?
What happens if I disconnect the GitHub App but keep my LGTM account?
What providers are on the roadmap?
Two installs. One review pipeline.
GitHub App + your AI provider key. ~3 minutes end-to-end. Reviews run on your bill, with your provider, on your code.