// blog/how-parallel-claude-agents-built-a-c-compiler
How Parallel Claude Agents Built a C Compiler


Nicholas Carlini, a researcher on Anthropic's Safeguards team, ran 16 Claude instances in parallel for two weeks and got a working C compiler out of it: 100,000 lines of Rust, produced over nearly 2,000 Claude Code sessions at a cost just under $20,000, capable of building a bootable Linux 6.9 kernel on x86, ARM, and RISC-V. The compiler is the headline. The writeup is more useful because Carlini spends most of it on how to design a harness that keeps autonomous agents productive for weeks without a human in the loop, and where that design stops working.
What "agent teams" means in practice
Carlini describes a standard Claude Code session as assuming an operator. Give it a long, complex problem and it will solve part of it, then stop and wait for input. His fix is deliberately unsophisticated: a bash loop that restarts Claude the moment it exits, forever.
while true; do
COMMIT=$(git rev-parse --short=6 HEAD)
LOGFILE="agent_logs/agent_${COMMIT}.log"
claude --dangerously-skip-permissions \
-p "$(cat AGENT_PROMPT.md)" \
--model claude-opus-X-Y &> "$LOGFILE"
done
If you've seen Geoffrey Huntley's Ralph loop, this is the same idea, and Carlini says so. The prompt tells Claude to break the problem into small pieces, track what it's working on, and keep going until the result is perfect. The loop restarts Claude indefinitely. Carlini notes one exception: an agent once ran pkill -9 bash by accident and killed itself, ending its own loop. Carlini recommends running it in a container.
How 16 agents coordinate without an orchestrator
The multi-agent layer is equally bare. There is no orchestration agent, no message bus, no planner assigning work. The coordination substrate is git.
A bare repository is mounted into each agent's Docker container at /upstream. Each agent clones to /workspace, works, then pulls, merges, and pushes. Task claiming is a lock file: an agent writes current_tasks/parse_if_statement.txt before starting on if-statement parsing, and if two agents race for the same lock, git's synchronization forces the loser to pick something else. Merge conflicts are frequent, and Carlini observes that Claude is smart enough to resolve them.
Each agent independently decides what to do next, which in most cases means picking up what Carlini calls the "next most obvious" problem. When stuck, agents maintain running documents of failed approaches and remaining tasks, which the next fresh agent reads on arrival. The project's git history shows the lock files appearing and disappearing as agents claim work.
This required little coordination machinery, and most of the engineering effort went into the harness.
Why the tests matter
Carlini is direct about where the effort went: "it's important that the task verifier is nearly perfect, otherwise Claude will solve the wrong problem." An agent running unsupervised in a loop will optimize whatever signal you give it indefinitely. If the signal is wrong, you get two weeks of confident progress toward the wrong target.
Building that signal meant collecting high-quality compiler test suites, writing verifiers and build scripts for open-source packages, and watching for the specific mistakes Claude made so new tests could target them. The process was reactive. Near the end of the project, agents started breaking existing functionality every time they added a feature, so Carlini built a continuous integration pipeline with stricter enforcement so new commits couldn't regress old behavior. Regression pressure that a human team absorbs through code review had to be converted into automated enforcement because there was no review.
Designing feedback for a model, not a human
The most transferable section of the writeup covers the ways a test harness written for humans fails when its consumer is a language model. Carlini frames it as putting yourself in Claude's shoes, and he names two specific limitations he had to design around.
Context window pollution. Every agent wakes up in a fresh container with no memory and burns time orienting itself. A test harness that dumps thousands of bytes of output makes that worse. His harness prints a few summary lines, logs everything else to files, and formats errors so grep finds them: the word ERROR with the reason on the same line. Aggregate statistics are precomputed so Claude doesn't spend turns recomputing them.
Time blindness. Claude can't tell time, and left alone it will happily spend hours running tests instead of making progress. The harness prints incremental progress infrequently and ships a default --fast mode that runs a 1% or 10% random sample of the suite. The sample is deterministic per agent but random across containers, so the fleet still covers every file while each individual agent can reliably detect its own regressions.
These harness properties apply directly to Ralph-style loops.
Where parallelism breaks down
For most of the project, parallelism was free. A test suite with hundreds of independent failing tests distributes itself; each agent locks a different failure. Once the suite hit a 99% pass rate, each agent took a different small open-source project to get compiling: SQLite, Redis, libjpeg, MQuickJS, Lua.
Then came the Linux kernel, and the model broke. The kernel is one giant task. Every agent hit the same bug first, fixed it, and overwrote each other's changes. Sixteen agents delivered the throughput of one.
Carlini used GCC as an online known-good oracle: a new test harness compiled most of the kernel with GCC and only a random remainder with Claude's compiler. If the kernel booted, the bug wasn't in that agent's subset of files; if it broke, the harness could re-compile some of those files with GCC to narrow the fault. That decomposed one monolithic task back into many independent ones, letting each agent chase different bugs in different files until Claude's compiler could handle all of them. Delta debugging was needed to find pairs of files that failed together but compiled fine independently.
Agent-team throughput requires decomposable verification. When the task stopped decomposing, Carlini built an oracle that split it into independent tasks again. The writeup does not indicate that this work could have been delegated.
What the specialized agents did
Carlini also assigned agents specialized roles. While most agents worked the main problem, Carlini assigned one to coalesce duplicate code, since LLM-written code frequently re-implements existing functionality. Another worked on the compiler's own performance, a separate one on the efficiency of its generated code, one critiqued the project's design from the perspective of a Rust developer and made structural changes, and one maintained documentation. These roles received a dedicated always-on agent each.
What $20,000 bought
The run used 2 billion input tokens and 140 million output tokens at a cost just under $20,000 across two weeks. It cost far more than the priciest Claude Max plan and far less than having a person build the same thing, let alone a team.
The clean-room artifact has no internet access and depends only on the Rust standard library. It compiles a bootable Linux 6.9 for three architectures, builds QEMU, FFmpeg, SQLite, Postgres, and Redis, passes the GCC torture test suite at 99%, and compiles and runs Doom. Carlini specified the shape up front, including that it should use an SSA intermediate representation to support multiple optimization passes, but not how to build any of it.
The compiler lacks the 16-bit x86 support needed to boot Linux out of real mode and calls GCC for that piece, though the 32-bit and 64-bit x86 compilers are its own. It has no assembler or linker of its own; those were the last components the agents started automating, they're still buggy, and the demo video used GCC's. It builds many projects.
Carlini has run this same project as a benchmark across the Claude 4 series. Earlier Opus 4 models were barely capable of producing a functional compiler at all. Opus 4.5 was the first to pass large test suites, but couldn't compile any real large project. Opus 4.6, with sixteen parallel instances and a carefully built verification environment, compiles the kernel. The harness code remained simple across that whole arc. Opus 4.6 made the kernel feasible, while two weeks of test-infrastructure tuning made it usable.