Code review that has read the whole repo

inline reviews every pull request against the codebase around it, runs your suite in a sandbox, and holds the merge when it finds something real.

Reviewsworker live

Every pull request the agent has processed, newest first.

Search title, author, or PR number…
AllSubstantiveTrivialSkipped
Pull requestVerdictFindingsCostWhen
acme/payments-api#4127
Add idempotency keys to the charge endpoint
by priya · nextjs · Opus 5
substantiveHigh risk
4$0.3122m ago
acme/payments-api#4126
Bump stripe SDK to the current major
by dependabot · nextjs · Haiku 4.5
trivial
0$0.0029m ago
acme/ledger#881
Session state machine + per-tenant rate limiter
by tomas · dotnet · Opus 5
substantiveMed risk
2$0.13424m ago
acme/mobile#2310
Retry image uploads on transient 5xx
by jules · expo · Opus 5
substantive
1$0.0981h ago
acme/ledger#879
Document-access audit log
by priya · dotnet · Opus 5
substantive
6$0.6613h ago
acme/web#5502
Fix dimmed rows that never reset after filtering
by karri · nextjs · Opus 5
substantive
2$0.1474h ago
acme/web#5501
Update the onboarding copy
by sam · nextjs · Haiku 4.5
skipped
0$0.0015h ago
acme/etl#640
Backfill tenant ids on historical charge rows
by tomas · python · Opus 5
substantiveHigh risk
3$0.2216h ago
acme/mobile#2309
Cache the session token across cold starts
by jules · expo · Opus 5
substantive
1$0.0768h ago
inlinebotcharges.ts:118
highconcurrencyconf 94%

Idempotency key is written after the charge, not before

Two requests carrying the same key can both pass the existence check before either row lands, so the customer is charged twice. Insert the key first and treat the unique-violation as the replay path.

116const existing = await keys.find(key);
117- const charge = await stripe.charge(amount);
117+ await keys.insert(key); // unique index
fixedresolved by a later push

Your agents already speak to it

inline is an MCP server. Point any agent that speaks the protocol at it and you get the same engine, guidelines, and repo memory the pull-request bot uses, before the pull request exists.

The review,
not a summary

Findings are anchored to a line, carry a severity and a confidence, and have survived a validation pass that discards anything the reviewer cannot defend from the code it read. Haiku triages first, so a dependency bump never pays for an Opus review.

Learn more
acme/payments-api#4127 WalkthroughView PR
substantiveby priya · nextjs · opus 5 · 2m ago
Cost

$0.312

Input tokens

88,402

Cached reads

61,180

Output tokens

9,744

Duration

1m 47s

Summary

This PR adds idempotency keys to the charge endpoint and a replay cache in front of it. The data model is right, but the key is persisted after the charge rather than before it, so concurrent retries can double charge; the replay cache is also keyed without the tenant id, which lets one tenant read another tenant's cached response.

highconcurrencysrc/charges.ts:118fixedconf 94%

Idempotency key is written after the charge, not before

highsecuritysrc/replay-cache.ts:41fixedconf 91%

Replay cache key omits the tenant id (IDOR)

mediumcorrectnesssrc/charges.ts:64conf 78%

Retry budget is never reset between attempts

Included

Two-tier modelstriage every PR, reason deeply on the ones that matter
Validation gateunsupported findings are suppressed, with the reason kept
Dedup fingerprintsthe same defect is raised once
Incremental passesnew commits re-read the whole PR on a fixed cadence
Linters folded insemgrep, gitleaks and eslint, triaged to review quality
Cost per reviewinput, cached reads, output and dollars, per model

It runs your tests
before it says anything

Every review gets a sandbox: dependencies installed, the suite run, and throwaway tests written for changed code nothing covers. You get the terminal trace and the artifacts, not a claim. What the run proves decides whether the merge is held.

Learn more
Evidence collectedacme/payments-api#4127 · 8f4c1ab
214 passed 1 failed 96s compute 74.2s
  1. Install dependencies
    npm ci
  2. Type check
    npx tsc --noEmit
  3. Existing suite
    npx vitest run
  4. Authored tests
    npx vitest run charges.spec.ts
  5. Browser flow
    npx playwright test checkout
$ npx vitest run charges.spec.ts
 
✓ charges > refuses a replayed key 12ms
✓ charges > records the key before charging 9ms
✗ charges > two concurrent retries charge once
 
AssertionError: expected 2 to be 1
→ stripe.charge called twice for key idem_9f
at charges.spec.ts:41:5
 
Tests 1 failed | 214 passed (215)
Checksacme/payments-api#4127
build
Build and type check
42s
test
Unit tests
1m 12s
inline / review
2 unresolved findings block this merge
1m 47s
Merging is blockedblock on high
  • Idempotency key is written after the chargethread resolved
  • Replay cache key omits the tenant idcode changed by 8f4c1ab
  • Retry budget is never reset between attemptsawaiting a reply

Included

Real executioninstall, build, unit tests, browser flows
Authored testswritten and re-run until they hold, or reported as failed
Merge gateoff, report only, or block on a severity you pick
Self-clearinga finding clears when its thread resolves or the code changes

Read the change
in the order it was built

Every reviewed pull request gets a hosted walkthrough: the diff reorganized into ordered layers, each with a note on why it exists, and a chat grounded in that exact diff so a reviewer can ask instead of guess.

Learn more
Change stack4 layers · 21 files
  1. 1Schema
    idempotency_keys table
  2. 2Persistence
    key insert + unique index
  3. 3Endpoint
    charge path rewiring
  4. 4Tests
    replay + concurrency cases
src/charges.ts
114 async function charge(req: ChargeRequest) {
115 const key = req.headers['idempotency-key'];
116 const existing = await keys.find(key);
117- const charge = await stripe.charge(req.amount);
117+ await keys.insert(key); // unique index
118+ const charge = await stripe.charge(req.amount);
119 return charge;
Why this layer

The key has to land before the money moves, so a concurrent retry loses the unique-index race instead of charging twice.

It gets better
at your repo

When a pull request closes, inline harvests what happened to each finding: reactions, resolved threads, and whether the flagged code actually changed. Repeated dismissals become proposed rules you approve, and a per-repo profile carries what it has learned into the next review.

Learn more
Learningsproposed from dismissals
Stop flagging `any` in generated clients
dismissed 6× in acme/web
accepted
Treat `// @ts-expect-error` in tests as intentional
dismissed 4× in acme/ledger
accepted
Prefer `Result<T>` over thrown errors in services
from a maintainer reply
proposed
Do not suggest `useMemo` under 50 rows
dismissed 3× in acme/web
proposed
Acceptance rate · 30d81%
Codebase profileacme/payments-api
Money paths

Every charge goes through `src/charges.ts`; nothing calls the Stripe SDK directly.

Tenancy

Rows carry `tenantId`; a query without it is a bug, not a style choice.

Error shape

Services return `Result<T>`; only route handlers throw.

Fragile files

`replay-cache.ts` has caused three incidents; treat changes there as high risk.

distilled by Haikuupdated after every substantive review

The review your agent
can ask for

Ask for a review from inside your agent and get one against your uncommitted tree. Or have the agent post a plan first, with wireframes and open questions, and wait for a human to sign it off before a single file is written.

Learn more
Terminal~/acme/payments-api
$ claude mcp add inline --transport http \
https://inline.dev/api/mcp
Added MCP server “inline”.
 
> review my working tree before I open the PR
 
⏺ inline · review_changes
reading 14 changed files, 812 added lines
repo memory: acme/payments-api
2 high · 1 medium · 3 suppressed
 
charges.ts:118 idempotency key written after
the charge; concurrent retries double charge.
Visual planIdempotent charges · awaiting sign-off
2 open questions4 steps7 files
Request
Key store
Stripe
insert key → charge → return
  • Does the replay cache need the tenant id in the key?
  • Should a lost race return 409 or the original charge?
  • Unique index on (tenant_id, key), agreed

Included

Per-user keysnamed, revocable, with cost tracked per key
Pre-PR reviewsthe working tree, no push required
Visual planspinned comments on wireframes, then an approval
Feedback queuethe agent polls for decisions and implements

It knows
what calls what

A symbol, call and import graph of your default branch is built per commit. A review resolves the pull request head to the nearest indexed ancestor, overlays the diff, and can walk the real dependency closure of the change instead of grepping for it.

Learn more
Code graphacme/payments-api · 8f4c1ab
18,402 symbols41,190 edgesindex fresh
Dependency closure of the diff
  • charge()src/charges.tschanged
  • keys.insert()src/keys.tscalled by
  • replayCache.get()src/replay-cache.tscalled by
  • POST /v1/chargessrc/app/api/charges/route.tsimports
  • refundJob()src/jobs/refund.tsimports

Advisories, judged
against your code

inline matches advisories to your lockfiles, then asks whether the vulnerable path is reachable from anything you ship. What survives that gets a remediation pull request, patched and verified in a sandbox before a human sees it.

Learn more
Alertsfeed live

Advisories matched to your lockfiles, then assessed for reachability in your code.

Search package or advisory…
OpenConfirmedAll
PackageSeverityStatusAssess cost
fast-jwt@3.3.1npmCVE-2026-21841
Signature bypass on ES256 tokens
acme/payments-api
criticalconfirmed$0.041
Newtonsoft.Json@12.0.3nugetGHSA-5crp
Deeply nested payloads exhaust the stack
acme/ledger
highconfirmed$0.038
postcss@8.4.31npmCVE-2026-11097
Parser confusion in source maps
acme/web
mediumnot affected$0.009
tar-fs@2.1.1npmGHSA-pq67
Path traversal when extracting archives
acme/mobile
highopen$0.012
urllib3@2.0.6pypiCVE-2026-30820
Redirect leaks the Authorization header
acme/etl
mediumdismissed$0.007
Remediation PR openedverified

feature/inline-fix-cve-2026-21841

Bump fast-jwt to 4.0.2 and pin the ES256 curve

  • Reachable from POST /v1/charges
  • Patch applied and the suite re-run in a sandbox
  • No behavior change outside token verification
+18−63 files

Included

Reachability triagethree tiers, so noise stops before the expensive pass
Remediation PRsthe patch, the re-run suite, and the diff
Red teaman offensive run that proves an exploit in a sandbox
Threat feedadvisories matched the hour they publish

The rest of it,
on the same rail

The pull request is where inline starts, not where it stops. Cloud posture, CI health, runtime errors, prompt quality and vendor coverage all land in one console, triaged by the same models and grounded in the same repositories.

Learn more
ComplianceBAA coverage
Vendors

65

Uncovered

4

Expiring

2

Analytics SDK receives PHI in event props
no agreement on file
uncovered
Transcription API called from the intake service
BAA expires in 21 days
expiring
Email provider handles member names
BAA countersigned 2026-02-11
covered
Error tracker scrubs PHI before send
reviewed, no PHI leaves the process
covered
CI alertsGitHub Actions
Failing

2

Flaky

5

p95 build

6m 12s

e2e-chrome times out waiting for the login form
acme/web · main · failed 4× today
flaky
Docker build fails on the arm64 leg
acme/ledger · release/prod
failing
Integration suite got 3m slower this week
acme/payments-api · main
duration
Cache restore misses on every PR run
acme/mobile · pull_request
cost
Issuesacme-web · production
Unresolved

12

Events 24h

8,104

Users

431

TypeError: cannot read 'tenantId' of null
1,204 events · 88 users · P1
root cause
AbortError: signal is aborted without reason
612 events · 140 users · P2
regressed
PrismaClientKnownRequestError P2002
88 events · 12 users · P2
triaged
ChunkLoadError: loading chunk 42 failed
41 events · 39 users · P4
noise
Cloud postureAzure · 2 subscriptions
Findings

37

P1

3

Spend / mo

$18.4k

Storage account allows public blob access
prd-rg · sainlineprd
P1
SQL server has no private endpoint
prd-rg · scu-prd-sql1
P1
Key vault soft-delete purge unprotected
dev-rg · kv-inline-dev
P2
App Service running an unsupported runtime
dev-rg · scudevinline
P3
Prompt evals7 prompts discovered
Graded

142

Mean

3.8/5

Failing

9

review/system-prompt.ts
48 cases · faithfulness 4.4 · safety 4.9
4.6
triage/classify.ts
31 cases · precision 3.1 on edge inputs
3.4
walkthrough/layers.ts
24 cases · ordering drifts on big diffs
3.9
memory/distill.ts
39 cases · no adversarial failures
4.4

Every finding has to survive a second pass before anyone sees it.

Validation gateConfidence floorDedup fingerprints

Suppressed is not deleted. The reason is kept, and you can read it.

Suppress reasonsCost per modelFull audit log

Agents are principals
too

Permissions are a module and action statement resolved over platform, organization and repository scopes. An agent key carries its own scopes, intersected with its owner's permissions and re-resolved on every call, so delegating work never widens what can be reached.

Learn more
Rolesacme · 42 people, 3 agents
Owner
everything, including billing and platform
2
Admin
configure review, security, and connections
6
Member
their own pull requests and reviews
34
Agent · release-bot
reviews:read ∩ owner's permissions
2 repos

An agent's authority is its own scopes intersected with its owner's permissions, resolved per call and per repository.

Put it on one repository

Connect GitHub, enable a repo, and the next pull request opened gets a review.