modernci Agent-first CI.

Agent-first CI.

Your agents write the code. ModernCI judges it, merges it, and tells you what each merge cost.

Self-hosted CI built for coding agents. Every move goes on the record. One binary in place of your runner, cache, merge queue, cheap runners and fix bot.

committed→judged→merged
↘ appealed → judged again
appealed: sent back to an agent, which returns with a fix
Set it up today: paste this into your coding agent.
Read https://modernci.dev/llms.txt and set up ModernCI on this repo.

Works with Claude Code, Codex, or any agent that can run commands.

In use on our own repos today. Self-host release: follow the changelog.

Cost per merged change · acme · today
$0.07

38 changes merged. 214 machine minutes, $1.12 of agent spend, 6 minutes of waste. example

Moves · acme/monorepo · today live Example rows
Recent moves, each with its verdict, the work it took and what it cost
MoveVerdictChecksMachineAgentWasteDone to mergeCost
#4402 lane-search→predev merged 2 run · 5 reused 3m 40s warm-2 none 0s 11m $0.03
#4399 lane-billing→predev red 4 run · 3 reused 6m 05s warm-1 1 try · $0.38 0s open $0.44
Verdict red on billing::invoice_rounds_half_up. Appealed: work item wi-0412 sent to agent host mbp-3, attempt 1 of 2.
#4398 lane-docs→predev merged 0 run · 7 reused 0s none 0s 2m $0.00
Docs only. Every check's input key already had a green verdict, so nothing ran and it cost nothing.
#4396 lane-api→predev merged 3 run · 4 reused 4m 12s warm-2 none 1m 02s flake 19m $0.06
#4395 lane-ui→predev waiting 5 run · 2 reused 5m 48s warm-1 none 0s open $0.05
#4390 predev→dev merged 3 run · 4 reused 9m 31s cloud-c7 none 0s 17m $0.11
Two warm slots would miss the 20m deadline, so the router sent the tests to one cloud runner.
Cost per merged changemachine minutes + agent spend ÷ changes merged · today, 38 merged
$0.07
01 · The problem

Your agents open 30 PRs a day. Your CI was built for 3.

We ran our own large Rust monorepo with a fleet of coding agents for months. These are numbers from that log, not a survey.

4,000 / 4,000 min

The Actions minutes cap, hit. A 4-shard matrix, a preflight and a fold job ran on every PR, about 2,000 extra runner-seconds each. Then everything stopped.

8 h

A silent stall. The engine acted only on events. A quiet repo produced none, so nothing merged and nobody knew.

0 lines

A red blamed on the wrong PR. The failing test was a flake. The PR it blocked had not touched it.

8 h

Every agent idle. A weekly usage limit stopped the fleet, and nothing resumed it.

02 · The thesis

Quality is how CI gets cheap.

Quality, speed, cost: a chain, not a trade-off. Each link pays for the next.

When two goals conflict, the earlier link wins. A correct verdict beats a fast one; a fast one beats a cheap one.Waste is a bug. It is measured, named and cut.
03 · The loop

Committed, judged, merged — or appealed.

The agent owns the whole loop. People step in only to answer a question, which becomes a ruling, or when the appeals run out.

  1. CommittedThe agent pushes and calls done over MCP. ModernCI opens the pull request.
  2. JudgedEach check's input key is looked up first; a stored green costs nothing. The rest run on the cheapest backend that finishes before the deadline. The verdict is green or red, and it cites its evidence.
  3. MergedOn a green verdict, the target fast-forwards onto the judged commit.
  4. Red becomes a work itemThe failing check, the smallest log that shows it, the command to reproduce it, the diff and every earlier attempt.
  5. AppealedThe failure ladder sends it to a free agent host. The failing check is judged first; the full move is judged again only if that comes back green.
.ci/predev.yaml branch file · in your repo
# the verdict a commit on predev needs to enter dev
to: dev
deadline: 20m
checks:
  build:  { run: cargo build --workspace --all-features }
  clippy: { run: cargo clippy --workspace --all-targets -- -D warnings }
  test:   { run: cargo nextest run --workspace, scope: affected }
  gates:  { run: cargo xtask gate --all, baseline: target }
  oracle: { run: bin/oracle replay --strict }
guarded: [ golden/**, "**/tests/**", .ci/** ]
on_green: merge
redwork item wi-0412attempt 1 of 2 · prompt fix→ mbp-3 (claude)
#4399 lane-billing→predev: verdict red on test
check
test · cargo nextest run -p acme-billing
failed
billing::invoice_rounds_half_up (1 of 214 judged; target 214)
log
assertion `left == right` failed
  left: 400
 right: 201
at crates/billing/src/invoice.rs:188
reproduce
modernci ci --from lane-billing --only test
diff
3 files, +41 −12
evidence
red before, green after, measured by ModernCI
sealed
weakening **/tests/** is sealed: only a person's order unseals it
04 · Honest agents

ModernCI takes no agent's word.

Built for agents means built for agents that cut corners. A verdict you can trust means no wrong merge to unwind and no wrong red to chase. A suspected flake gets a second witness, a re-run on another machine, before anyone is blamed.

Per-test truth

"Nothing was judged" is red.

Zero tests, a duration that collapsed because tests skipped, or a count that dropped against the target.

tests judged1,406
on target1,418
disappeared12 · red
Evidence, not claims

Red before, green after.

A fix for a failing test must show both, measured by ModernCI, not reported by the agent.

before the fixred · 0.21s
after the fixgreen · 0.19s
stored asevidence on #4399
Sealed paths

Weakening a test asks first.

Deleting an assertion, skipping a test or editing a golden is sealed: only a human order unseals it. It goes to the owner's Questions queue, not to merge.

editedgolden/billing/invoice.json
resultquestion q-88
mergeheld
05 · The number

One number:
cost per merged change

Machine minutes plus agent spend, divided by changes merged. Everything goes on the record. Measured on our own monorepo, before and after. No projections: until the switch-over is done, this page shows "before" and says so.

BeforeGitHub Actions + homegrown engine
AfterModernCI
Machine minutesper merged change
measuring from the Actions bill
at switch-over
Agent spendper merged change
measuring from host reports
at switch-over
Wasteby class
~2,000 runner-seconds per PR on cold shards rebuilding the same tree
at switch-over
Done to mergemedian
8 h stalls with no alarm
at switch-over
Cost per merged change
measuring
at switch-over

How the number is measured, and what we charge →

06 · Yours to run

One binary. Any forge. Your machines. No cloud required.

Every install is a complete daemon. Machines connect out to it, so nothing needs an open port. Connect to modernci.dev only if you want one view of many daemons.

Agent hosts
  • any laptop or server
  • Claude Code, Codex, anything
  • modernci host join
MCP, outbound
Your daemon
  • the loop · the store · secrets
  • the UI and the operator MCP
  • forges: GitHub, GitLab, Gitea, Forgejo
outbound
Backends
  • this machine, an SSH host, a VM
  • any cloud, priced per minute
  • warm pools sized by workload
Optionalmodernci cloud connect links a daemon to a modernci.dev tenant over one outbound connection. Code, logs and secrets stay home.
07 · Try it

Three commands.

Run the daemon, register a repo, point a machine at it. Your existing workflow files import as they are.

Set it up today: paste this into your coding agent.
Read https://modernci.dev/llms.txt and set up ModernCI on this repo.

Works with Claude Code, Codex, or any agent that can run commands.

Or by hand preview

docker run -p 8080:8080 -v mci:/data modernci/modernci
modernci repo add you/your-repo
modernci host join https://ci.your.lan
Already on GitHub Actions?

modernci import .github/workflows/ci.yml writes the branch file. Then it judges beside your old CI, move by move, and you cut over when the verdicts agree.