Download for Mac

Your agent said “done.” Was it?

ThruLine checks your agent’s claims against what actually ran, before you merge.

Apple silicon Mac, macOS 12 or later. The first time you open ThruLine, macOS checks it, which can take up to a minute. After that it opens straight away.

Install · Mac (Apple silicon)

Download ThruLine for Mac
  1. Open the .dmg and drag ThruLine to Applications.
  2. Open ThruLine. It walks you through setup and opens HQ.

macOS on Apple silicon · signed and notarized by Apple · updates itself, after asking

Release notesReleases

ThruLine HQ · Brief The design we’re building
ThruLine HQ, Brief: the claim “Tests pass.” is Not checked on version e71c5b0. The tests passed on 9f2ad3e, checkout/api.py changed after that, and nothing has run on e71c5b0. The six-step chain stops at Since, with Check it again beside it.

The chain · example project

Follow the claim.

One sentence the agent wrote, and six plain questions asked of it. Each answer is a line from the record — the session log your agent already writes on your machine — with the step it came from.

Claude Code said “Checkout total fixed.” “Tests pass.” · step 52 · example project

  1. ① Said

    What did the agent claim?

    "Tests pass." Claude Code · 16:03 step 52
  2. ② Rests on

    What is that claim based on?

    4 passed, 0 failed step 46 cited by the agent
  3. ③ Ran on

    Which version did that actually run on?

    version 9f2ad3e 1 version older
  4. ④ Since

    Needs a re-check

    Did anything it depends on change after it?

    checkout/api.py changed · step 56 after the run
  5. ⑤ Re-checked

    Not reached

    Has anything checked it since?

    nothing on e71c5b0 with checkout/api.py in scope
  6. ⑥ So

    Not checked · version e71c5b0

    So what do we actually know?

    the claim may be entirely true.

What counts as done · accepted

The re-check tests these three statements on e71c5b0. Each says what counts as done. None of them is a verdict.

Not checked yet: Applying a discount code once reduces the total by exactly that discount.
Not checked yet: Applying the same discount code twice does not reduce the total twice.
Not checked yet: Checkout totals with no discount code are unchanged.

Proof stops here

Nothing on e71c5b0 has run with checkout/api.py in scope.

Looked at: 2 finished runs (step 26 on 4b19a0c, step 46 on 9f2ad3e) and step 60, which has no result yet.

pytest -q tests/test_totals.py checkout/on e71c5b0 · asks once for this project

This page replays the example project. Nothing runs in your browser.

Inside HQ

Every claim, its proof, and where it stops.

The video shows v0.2.0. ThruLine 0.3.0 is the Mac app.

The real ThruLine v0.2.0 HQ, running locally.
ThruLine HQ, Explore: every statement in one Change. Four things still need evidence before e71c5b0 can be approved; each row shows its verdict, its six-step chain and where its proof stops, for Claude Code and Codex.
Explore · every statement, and where each one’s proof stops.
ThruLine HQ, Record over time: 64 statements across three projects in 30 days, 41 proven on their version, 17 needed a re-check, 6 with no proof found; a breakdown by agent and a chart of where proof stops most often.
Record over time · how often your agents’ claims hold up, and where they break.

They review the diff.

ThruLine reviews the agent’s claim against the record.

A diff shows which lines changed. The record shows what the agent actually ran, in what order, on which version — and so whether its “done” still holds.

How it compares, with sources

One Change · six stages

Define, prepare, build, verify, review, approve.

A Change is one feature, fix or refactor you are asked to accept. It can span several sessions. Each stage answers one plain question. Under each is the screen that answers it, rebuilt in the product’s own words.

Every stage, in full

01 · Define

What counts as done?

thruline ui · Change · Define

Proposed, checkable statements · accept, edit or drop each

Applying a discount code once reduces the total by exactly that discount.

Accept Edit Drop

Applying the same discount code twice does not reduce the total twice.

Accept Edit Drop
Suggestions start hollow. Nothing counts until you accept it.

02 · Prepare

What exactly will be examined?

thruline ui · Change · Prepare

What will be looked at

  • The project folder: checkout-web
  • Starting from: e71c5b0
  • There are no unsaved changes: this is exactly what is committed.

Only what was actually written down is shown here. Nothing about databases, ports, secrets or outside services is claimed.

It names the exact starting version, and claims nothing the record does not hold.

03 · Build

What changed?

thruline ui · Change · Build

What changed in this version

version e71c5b0

checkout/api.py step 56 · 16:04

Changed after the run at step 46, and after the agent said “Tests pass.”

The edit came after the run the agent cited, so that run no longer covers it.

04 · Verify

What happened when we checked it?

thruline ui · Change · Verify
Check it again

pytest -q tests/test_totals.py checkout/on e71c5b0 · asks once for this project

How a check can end

Passed · Failed · Ran, checked nothing (not a pass) · Cancelled by you · Interrupted · Tool not found

Only a pass reads as a pass. It installs nothing and does not touch the network.

05 · Review

What did review find, and was it addressed?

thruline ui · Change · Review

What review found

No review has been written down for this Change yet, so there is nothing here to read.

Ask for a review

Asking for a review is not something this version of ThruLine can do yet.

An empty stage says it is empty, and says why.

06 · Approve

What exactly am I accepting?

thruline ui · Change · Approve
Ready for approval· e71c5b0
Approve e71c5b0

It does not merge, deploy or tell the agent anything.

Written to .thruline/decisions/e71c5b0.json in your project.

Approval names one version. If the code moves, approving is refused.

Specimens

Where the proof stopped.

Each specimen is one claim, its six questions, and the exact point where the record stops backing it.

Recorded on ThruLine’s checkout-web example project. No customer data.

All five specimens

proof stops at ② rests on

Ran, checked nothing

“Ran, checked nothing. This is not a pass.” A run that exits 0 — the code for success — having checked nothing.

Read the specimen

proof stops at ③ ran on

The run was one version older

The tests passed — on 9f2ad3e, one version (one commit) before the one you are approving.

Read the specimen

proof stops at ④ since

A file changed after the run

checkout/api.py changed at step 56 (16:04), after the run and after the claim.

Read the specimen

From the blog

New ThruLine research 13 min read Your AI agent says “tests pass”. 1 in 5 times, there’s no proof. An open scoreboard for checking AI agents’ “done”, our own tool included. Read the research

The receipt

Deterministic. Tamper-evident. Local. Unmetered.

A check ThruLine runs can end in a receipt — a signed record of exactly what ran. Four things hold for all of it.

Deterministic
The same record gives the same answer, every time. No model decides a verdict.
Tamper-evident
Any change to the record shows. It is hash-chained: each entry carries a fingerprint of the one before, so a changed byte breaks the chain.
Local
The record, the runs and the receipts stay on your disk. The core engine makes no network calls.
Unmetered
No meter: you are not charged per review or per run. Checks run on your machine, and no model call sits behind a verdict.

Here is a real one. The outside is a DSSE envelope — a standard wrapper that carries a signature. Inside is an in-toto statement — a standard format for an attestation, a signed statement of what was done to which code.

receipt.json synthetic project · sample key

DSSE envelope · payloadType application/vnd.in-toto+json

_type
https://in-toto.io/Statement/v1
predicateType
https://thrulinehq.com/attestation/execution-check/v0.2
subject
gitTree 900ad6fa6e8a96db17eae3e2120d42f65d752afc
kind
accepted_requirements
state
verified
check
pytest · argv python3 -m pytest -q
run
acceptance-evt_01M1WRC89HSS5XM6J4R302Z3QD
exit_code
0
counts
passed 2 · failed 0 · skipped 0 · total 2
chain_head
sha256:a2d1ecf0f906d3fc92d2c337180d4c04f83f6249fe7294e1807cbd17449493f8
contract
sha256:a77d28622af5c4acbaa11990af853e0d64650274a59c5d0b48e5fcadf09c290d
producer
sha256:0655f10ef05df654b88672604b3f60f42aaccaa42322851808fa7263528d6b4b
signature
keyid sha256:e0f549f57ffdda1592ba0e7fdbf1b30f3aeec1efb8dbb6a1015442745a411358
envelope sha256
43c845f11e984c56a5180699904317da46a186bb9ff1a9c32dd0208dd45feeef
Real output of ThruLine’s qualification run on a synthetic Python test project, signed with a sample key that is not a production identity.

Check it yourself, offline

thruline verify-receipt receipt.json --key signing.pub --offline --json

Pricing

5 free checks a month. Pro: unlimited checks and approving a version.

Seeing what your agent’s runs prove is always free: recording, every read, every check of your agent’s own runs, withdrawing an approval, exporting your own records.

See pricing

Pro

$15 a month

or $150 a year · one developer

FAQ

Five questions, answered plainly.

Every question
Does ThruLine use an LLM (a large language model) to decide whether my code is correct?

No. The verdict path is deterministic — the same record always gives the same answer, from recorded runs you can re-run. No model decides. A local model can narrate findings in plain English after the verdict, and that is off by default.

How a verdict is reached
What leaves my machine?

Never your code or sessions. ThruLine is local-first: the record, the runs and the receipts stay on your disk. The optional narrator talks only to a model on this machine. Once a day, ThruLine asks GitHub whether a new version exists; you can turn that off in Settings. Two more things can leave, and only when you start them: a licence request when you fetch one, and, if you run thruline reexec, Docker downloading the container image it needs.

What leaves, exactly
How is this different from CodeRabbit, Greptile or Cursor Bugbot?

They review the diff — the lines that changed. ThruLine reviews the agent’s claim against the record of what actually ran, on the version you are approving.

The full comparison
What does “Not checked” mean — is my code broken?

No. It means nothing in the record establishes the claim on this version. The claim may be entirely true.

A specimen: a file changed after the run
Can I use it on a team?

Pro covers one developer. Write to us about licences for multiple developers.

Pricing

Built by one engineer

Check the next “done” before you approve it.

Check my agent’s work

Every email is answered by the person who built ThruLine, within one business day. (Not a bot, not a queue.)

Download for Mac

Your agent said “done.” Was it?

ThruLine checks your agent’s claims against what actually ran, before you merge.

ThruLine HQ · Brief
ThruLine HQ, Brief: Claude Code said “Tests pass.” at step 52. Not checked on version e71c5b0: the tests passed on 9f2ad3e, checkout/api.py changed after that, and nothing has run on e71c5b0. Check it again.
The design we’re building
Check my agent’s work See an example

Apple silicon Mac, macOS 12 or later. The first time you open ThruLine, macOS checks it, which can take up to a minute. After that it opens straight away.

Install · Mac (Apple silicon)

Download ThruLine for Mac
  1. Open the .dmg and drag ThruLine to Applications.
  2. Open ThruLine. It walks you through setup and opens HQ.

macOS on Apple silicon · signed and notarized by Apple · updates itself, after asking

Release notesReleases

A recorded chain · example project

One claim, followed to the record.

Six plain questions. Each answer is a line from the session record, with its step number.

Claude Code said
“Checkout total fixed.” “Tests pass.”
step 52 · example project

1 2 3 5
  1. ① Said

    What did the agent claim?

    "Tests pass."
    Claude Code · 16:03 · step 52

  2. ② Rests on

    What is that claim based on?

    4 passed, 0 failed
    step 46 · cited by the agent

  3. ③ Ran on

    Which version did that actually run on?

    version 9f2ad3e
    1 version older

  4. ④ Since

    Did anything it depends on change after it?

    checkout/api.py changed
    step 56 · after the run

    Proof stops here

  5. ⑤ Re-checked

    Has anything checked it since?

    nothing on e71c5b0
    with checkout/api.py in scope

  6. ⑥ So

    So what do we actually know?

    Not checked· version e71c5b0

    the claim may be entirely true.

Proof stops here

Nothing on e71c5b0 has run with checkout/api.py in scope.

Looked at: 2 finished runs (step 26 on 4b19a0c, step 46 on 9f2ad3e) and step 60, which has no result yet.

pytest -q tests/test_totals.py checkout/
on e71c5b0 · asks once for this project

It installs nothing and does not touch the network.

See a real signed receipt

Inside HQ

Every claim, its proof, and where it stops.

The video shows v0.2.0. ThruLine 0.3.0 is the Mac app.

The real ThruLine v0.2.0 HQ, running locally.
ThruLine HQ, Explore: every statement in one Change. Four things still need evidence before e71c5b0 can be approved; each row shows its verdict, its six-step chain and where its proof stops, for Claude Code and Codex.
Explore · every statement, and where each one’s proof stops.
ThruLine HQ, Record over time: 64 statements across three projects in 30 days, 41 proven on their version, 17 needed a re-check, 6 with no proof found; a breakdown by agent and a chart of where proof stops most often.
Record over time · how often your agents’ claims hold up, and where they break.

They review the diff.

ThruLine reviews the agent’s claim against the record.

A diff shows what changed. It can’t show whether the tests ran, on which version, or what changed after they did. The record can.

How it compares, with sources

Six stages of a Change

From your request to one approved version.

A Change is one fix, feature or refactor you are deciding whether to accept. It may span several sessions.

  1. 01 · Define

    What counts as done?

    thruline ui · Define

    Asked

    “the checkout total is wrong when a discount code is applied — fix it”

    Applying a discount code once reduces the total by exactly that discount.

    covers cart/totals.py

    Accept Edit Drop

    4 statements · recorded with who and when

  2. 02 · Prepare

    What exactly will be examined?

    thruline ui · Prepare

    What will be looked at

    cart/ checkout/ tests/

    version e71c5b0

    Only what was actually written down is shown here. Nothing about databases, ports, secrets or outside services is claimed.

  3. 03 · Build

    What changed?

    thruline ui · Build

    What changed in this version

    checkout/api.py

    modify · step 56 · after the run at step 46

    One file changed after the run the agent cited.

  4. 04 · Verify

    What happened when we checked it?

    thruline ui · Verify

    A re-check ends in one of six

    Passed · Failed · Ran, checked nothing (not a pass) · Cancelled by you · Interrupted · Tool not found

    Only a pass reads as a pass.

  5. 05 · Review

    What did review find, and was it addressed?

    thruline ui · Review

    What review found

    No check covers checkout/api.py

    rests on step 56

    A closed conversation is not a fix. A finding is resolved by a run, not by a reply.

  6. 06 · Approve

    What exactly am I accepting?

    thruline ui · Approve

    What has been decided

    Approved e71c5b0

    .thruline/decisions/e71c5b0.json

    It does not merge, deploy or tell the agent anything.

Specimens

Five places the proof stopped.

Recorded on ThruLine’s checkout-web example project. No customer data.

1 2 3 4 5 6

Proof stops at ② Rests on

Ran, checked nothing

The agent cited a run that exited 0, the code for success, having checked nothing. This is not a pass.

[n] skipped, 0 ran · cited by the agent

Read the specimen
1 2 3 4 5 6

Proof stops at ③ Ran on

The run was one version older

The tests passed — on 9f2ad3e, one version before the one you are approving.

version 9f2ad3e · 1 version older

Read the specimen
1 2 3 5 6

Proof stops at ④ Since

A file changed after the run

checkout/api.py changed at step 56 (16:04), after the run and after the claim.

checkout/api.py changed · step 56
after the run

Read the specimen
All five specimens

From the blog

New ThruLine research Your AI agent says “tests pass”. 1 in 5 times, there’s no proof. An open scoreboard for checking AI agents’ “done”, our own tool included. Read the research 13 min read

The receipt

Deterministic. Tamper-evident. Local. Unmetered.

A receipt is a signed record of exactly what ran. Here is what stands behind one.

Deterministic
The same record always gives the same answer. No model decides the verdict.
Tamper-evident
The record is append-only and hash-chained: each entry carries a fingerprint of the one before, so a changed byte breaks the chain.
Local
The record stays on your machine. The core engine makes no network calls.
Unmetered
No meter: nothing is charged per run or per review, and no model call sits behind a verdict.

Here is a real one: a DSSE envelope (a standard wrapper for signed data) around an in-toto statement (an open format for attestations: signed statements of what was checked, on which code).

receipt.json

DSSE envelope · payloadType application/vnd.in-toto+json

_type https://in-toto.io/Statement/v1

predicateType https://thrulinehq.com/attestation/execution-check/v0.2

subject gitTree 900ad6fa6e8a96db17eae3e2120d42f65d752afc

kind accepted_requirements

state verified

check pytest · argv python3 -m pytest -q

run acceptance-evt_01M1WRC89HSS5XM6J4R302Z3QD

exit_code 0

counts passed 2 · failed 0 · skipped 0 · total 2

chain_head sha256:a2d1ecf0f906d3fc92d2c337180d4c04f83f6249fe7294e1807cbd17449493f8

contract sha256:a77d28622af5c4acbaa11990af853e0d64650274a59c5d0b48e5fcadf09c290d

producer sha256:0655f10ef05df654b88672604b3f60f42aaccaa42322851808fa7263528d6b4b

signature keyid sha256:e0f549f57ffdda1592ba0e7fdbf1b30f3aeec1efb8dbb6a1015442745a411358

envelope sha256 43c845f11e984c56a5180699904317da46a186bb9ff1a9c32dd0208dd45feeef

Real output of ThruLine’s qualification run on a synthetic Python test project, signed with a sample key that is not a production identity.

Check it yourself, offline

thruline verify-receipt receipt.json --key signing.pub --offline --json

Pricing

5 free checks a month. Pro: unlimited checks and approving a version.

Seeing what your agent’s runs prove is always free: recording, every read, every check of your agent’s own runs, withdrawing an approval, stopping a run, linking evidence, exporting your own records and undoing setup.

  • Pro

    $15 a month

    or $150 a year · one developer

See pricing

FAQ

Five questions, answered plainly.

Does ThruLine use an LLM (a large language model) to decide whether my code is correct?

No. The verdict path is deterministic — the same record always gives the same answer, from recorded runs you can re-run. No model decides. A local model can narrate findings in plain English after the verdict, and that is off by default.

How the verdict is reached, on Security
What leaves my machine?

Never your code or sessions. ThruLine is local-first: the record, the runs and the receipts stay on your disk. The optional narrator talks only to a model on this machine. Once a day, ThruLine asks GitHub whether a new version exists; you can turn that off in Settings. Two more things can leave, and only when you start them: a licence request when you fetch one, and, if you run thruline reexec, Docker downloading the container image it needs.

Security
How is this different from CodeRabbit, Greptile or Cursor Bugbot?

They review the diff — the lines that changed. ThruLine reviews the agent’s claim against the record of what actually ran, on the version you are approving.

The full table, on Product
What does “Not checked” mean — is my code broken?

No. It means nothing in the record establishes the claim on this version. The claim may be entirely true.

A specimen: a file changed after the run
Can I use it on a team?

Pro covers one developer. Write to us about licences for multiple developers.

Pricing
Every question, on the FAQ

Built by one engineer

Bring the next change your agent calls done.

It is a Mac app for Apple silicon. Download it, drag it to Applications, and open it.

Install in two steps
Check my agent’s work

Every email is answered by the person who built ThruLine, within one business day. (Not a bot, not a queue.)