Attested CI runs your checks where the code already is, on your laptop or your coding agent's machine. Each result is signed against the exact git tree and written to a ledger nobody can edit. GitHub just reads the verdict. No queue, no runner outage, no Actions bill for work you already did.
Actions queued for 40 minutes? Runners degraded? The checks already ran on your machine before git push finished. When GitHub's API is down, results still land in the ledger and post to the PR the moment it recovers.
Most CI re-runs what the author just ran locally. With Attested, Actions runs only for commits nobody checked locally and for a random ~10% spot check of local results. The dashboard shows the minutes and dollars you didn't spend.
A result is bound to the tree, the check definition from the base branch, the lockfiles and the platform. Change any of those and it's a different result. A PR can't weaken its own checks.
$ git push
▸ lint npm run lint
✓ lint pass 3.1s · ledger #18231 · github:maya
▸ typecheck npm run typecheck
✓ typecheck pass 9.8s · ledger #18232
✓ unit already attested (ledger #18190)
PR #412 · checks
✓ attested / lint tier 1 · github:maya
✓ attested / typecheck tier 1 · github:maya
✓ attested / unit tier 2 · spot-checked
0 Actions minutes
You don't migrate CI by hand. Sign in, create your workspace's GitHub App in one click, install it, and paste the prompt from the dashboard into Claude Code, Codex or Cursor.
GitHub creates it under your account or org. You own it, and you can remove it any time.
It reads your workflows, moves the hermetic checks into .attested.json, and adds the fallback workflow. Shadow mode: nothing is removed.
When both agree, a second prompt removes the duplicate Actions jobs and pins the required checks to your App.
Three parts. The ledger is the source of truth. GitHub is one reader of it.
A pre-push hook exports the committed tree, runs the checks your base branch defines, and signs an in-toto attestation with a 10-minute key tied to your GitHub identity.
Every result is a row in a hash chain. Database triggers refuse edits. Every 5 minutes a signed checkpoint goes into Sigstore's public Rekor log, so a rewrite of history shows up.
On every PR the App works out the keys for the head tree and posts check runs. Pin your required checks to the App and nobody can set a status by hand.
A signature proves who vouched for a result, not that the work happened. So we close the gap in tiers, and you pick per check.
If someone fakes 20 results at a 10% sample rate, the chance they're never caught is 12%. At 50 fakes it's 0.5%. New contributors and repeat offenders are sampled more. Mismatches are re-run before anyone is flagged, because flaky tests look like fakes.
| Tier | What it means |
|---|---|
| 1 · Signed | Run on a dev machine, signed with a short-lived key bound to their GitHub login. Faking is an attributable, permanent act. |
| 2 · Spot-checked | Your own Actions re-run a weighted random sample. A mismatch opens an incident, and a red re-run turns the check red. |
| 3 · Fleet-run | Run on your Actions runners, proven with GitHub's OIDC token. For checks that need secrets, edits to check definitions, or people without a local setup. |
The ledger is public. Private repos show only hashes. One command replays the whole chain, checks every signature, and checks each checkpoint against Rekor.
Open the live ledger →$ acli verify
✓ chain: 18232 rows replay to head 4be1c09a…
(9104 signatures checked, 9128 private rows hash-only)
✓ checkpoints: 1712 signed, 1712 confirmed in Rekor
Attested CI is free while we build it with our first teams: unlimited repos, private included, no card. Your fallback and spot-check runs use your own Actions minutes, about a tenth of what you use today.
Start free