CI 10–20× faster than GitHub-hosted runners, and cheaper to run
Your workflows run on our machines with caches already warm, and each change runs only the tests that can reach it.
or paste this into Claude Code, Codex or Cursor
Read https://graphide.com/setup.md and set me up with Graphide.runs-on: graphideTime-lapseExample run on a made-up repository. The same change on GitHub-hosted runners passes after 9m 00s; on Graphide CI, after changing runs-on from ubuntu-latest to graphide, it passes after 37s.
Minutes on GitHub. Seconds on Graphide.
Measured on 10 open-source repositories: the same CI job, the same results.
| Repository and job | On GitHub runners | On Graphide CI | Faster |
|---|---|---|---|
| aquasecurity/trivyGo · Build Test | 24m 53s | 30s | 50× |
| coredns/corednsGo · Test Makefile.release | 17m 42s | 24s | 45× |
| tokio-rs/tokioRust · miri-test | 19m 58s | 50s | 24× |
| rclone/rcloneGo · build (other_os) | 4m 24s | 11s | 24× |
| crossbeam-rs/crossbeamRust · miri (channel) | 18m 37s | 58s | 19× |
| bytecodealliance/wasmtimeRust · Miri (wasmtime-cli) | 21m 42s | 1m 14s | 17.6× |
| bytecodealliance/wasmtimeRust · Miri (component) | 11m 32s | 46s | 15.1× |
| rust-lang/futures-rsRust · cargo miri test | 10m 35s | 52s | 12.2× |
| rust-lang/hashbrownRust · miri | 6m 56s | 36s | 11.7× |
| webpack/webpackJavaScript · test262 | 27m 45s | 2m 25s | 11.5× |
| microsoft/playwrightTypeScript · MCP (firefox) | 29m 54s | 2m 39s | 11.3× |
Moving a job takes one line
Change runs-on: ubuntu-latest to runs-on: graphide. Every test a change leaves out is listed on the run’s page, with the reason.
0 missed failuresin 295,411 test runs we left out. Our own CI, October 2026.
| What | Graphide CI | GitHub-hosted |
|---|---|---|
| Tests a change runs | The ones it can reach, traced through a graph of your code | All of them |
| Who tunes the setup | Our agents, all the time, on our side | You |
| Dependency and build caches | Warm before the job starts | Restored in the job, if you set it up |
| Splitting tests across machines | Done for you | A matrix you write and keep up |
| Cost | Cheaper to run | GitHub’s per-minute price |
Graphide review
A pull request review that shows what a change reaches and what it breaks
An agent reads each pull request with everything it reaches, checks it against your rules, and says how it knows each finding.
22 of 22
findings that a run confirmed were real bugs
Research journal, October 19, 2026.
69%
of known bugs caught on one blind-judged batch of real pull requests
Research journal, October 21, 2026. We did not lead on every batch.
What the agent reads
The diff, plus the callers, routes, tables and services it touches, from our graph of your code, and your rules.
Live environmentBeta
When it suspects a bug, it runs a test on your old code and your new code and puts the run in the comment.
Live data flowsBeta
The same requests go to the old build and the new one; the review shows the first answer that differs.
The page for the approver
One page with the same graph and evidence, for whoever approves the pull request.
SaveUploadedFile now always runs os.Chmod on the destination's parent folder, even when the folder already existed and no permission was passed.
Calls that used to work now fail, or they silently change the permissions of folders the application doesn't own (a breaking change and a security risk).
How it breaks. Before this PR, MkdirAll did nothing to a folder that already existed. Now every call ends up running Chmod(parent, 0o750) or Chmod(parent, perm). …
Proved by a test: head failed 2 of 2 runs, base passed 2 of 2
Expected: If the destination's parent directory already exists and SaveUploadedFile is called with no perm argument, the directory's mode stays as it was (dtrwxrwxrwx, the same as /tmp).
TestScenarioSaveUploadedFileKeepsExistingDirPerm
base · old code
ok github.com/gin-gonic/gin 0.009s
passed 2 of 2
head · new code
expected: "dtrwxrwxrwx"
actual : "drwxr-x---"
failed 2 of 2
Graphide · agent · 92% sure · Open in Graphide
How we know: we ran it
A public pull request we reviewed ourselves on October 24, 2026. The comment was not posted there.
run now packs the whole starting environment, base64-encoded, into one exported variable.
Linux caps a single environment string at MAX_ARG_STRLEN (128 KiB). If the starting environment is larger than about 96 KiB, exec "$bin" fails with E2BIG ('Argument list too long') and grail does not start at all. The script itself documents being started from a dev shell (a Graphide terminal), which is exactly where environments get large.
How it breaks. Startrunfrom anix developshell, or any shell whoseenv -0is over ~98,000 bytes. base64 grows that by 4/3, so GRAIL_DESKTOP_ENV=<~131k bytes> is over the 131072-byte per-string limit, and the finalexec "$bin" "$@"fails. Before this change the same launch worked.
Graphide · agent · 55% sure · in the change · likely · Open in Graphide
How we know: we traced it
The verify stage read the code and judged it real, and rare. Not run: the stages that write a test and run it on old and new code were off for this review.
Graphide’s review of a change to our own code, October 27, 2026.
Every job runs in its own sandbox
On Microsoft Azure, in the western US. The details are in CI security and accounts and access.
One job, one machine, then it’s destroyed
Each job gets a fresh micro-VM (Cloud Hypervisor), or a whole VM for 16 and 32 vCPU runners, and nothing else runs on it.
Walled off
A job’s machine can’t reach other jobs or any private address. Pull requests from forks run on hosts with no trusted machines.
Secrets stay with the job
Secrets reach only the machine running the job, as on any self-hosted runner. Runner registrations are encrypted (AES-256-GCM), with keys in Azure Key Vault. We keep job records and test results, not your logs.
About us
Dan and Ben met in middle school in Cincinnati and have built things together ever since. Graphide is in San Francisco.
Backed by Y Combinator
Dan McGee
CEO, co-founder
Built Matrix, Illumio’s policy simulation platform, then left UC Berkeley to start Graphide.

Benjamin McIntyre
CTO, co-founder
Founded UC’s Linux and FOSS club; studies Computer Engineering and Mathematics at UC.
Questions
Does Graphide CI ever change whether a job passes?
No. If a test fails on our runners, the job fails. Before your jobs move, we check that our run catches every failure your own run catches.
Will the review hold up our merges?
No. Its check turns red only for a rule you marked blocking or a test that newly fails, and holds a merge only if you make it a required check.
Do we need both CI and review?
No. Each works on its own, and one free trial covers both.
How do we start?
Sign up, install the Graphide GitHub App and start your free trial. Review starts on your next pull request. For CI, press Switch to Graphide CI on a repository of your GitHub organization, or ask your coding agent to: one pull request changes its Linux jobs’ runs-on line.
What does it cost?
$20 a month per Graphide org, counted as usage, then pay as you go up to a cap you set. The free trial includes 10 reviews and $10 of CI usage. See pricing.
Where does our code go?
Graphide reads only the repositories you turn on and keeps a copy to check their changes. It never trains a model on your code, never sells it, and collects no telemetry except agent signals: your coding agents tell us when they start, push or merge, never your code. If your agent asks Graphide to test a commit, that commit is sent for the test. Turn signals off in your org’s Settings. More in the privacy policy.
For anything else, write to hello@graphide.com.
Install the GitHub App to start
Review starts on your next pull request. For CI, press Switch to Graphide CI on a repository.