Claude Codeに10万行のCコンパイラを書かせた実験 — 16並列・2万ドルの記録
AnthropicのNicholas Carlini氏が16並列のClaude Opus 4.6でCコンパイラを書いた実験記録です。長尺コーディングのベンチマークとしての位置付けと、自律ループの設計上の勘所を扱います。
2026年2月5日、Nicholas Carlini氏が「16並列のClaudeにCコンパイラを書かせた」実験を公開しました。氏はAnthropicのSafeguards researcherで、発表の場は同社のエンジニアリングブログです。約2週間・2,000セッション弱・2万ドル弱のAPI予算で、Rust製の10万行Cコンパイラが完成しました。x86 / ARM / RISC-Vの3アーキテクチャ向けに、Linux 6.9をビルドできる水準です。
本記事は成果の紹介にとどまらず、「長尺コーディングをLLMに任せたとき、何が回り、何が壁になるか」を読み解きます。ハーネス(Claudeを延々と動かし続ける外側の仕組み)の中身まで書かれた実験なので、エージェント型開発を業務に取り込みたい読者が、自分の環境に置き換えて読める材料になります。
背景 — なぜ「Cコンパイラ」が試金石になるのか
この実験でCarlini氏が試したのは、言語モデルを監督する新しい手法で、本人は「agent teams」と呼んでいます。Carlini氏はこのCコンパイラ課題を、Claude 4世代のモデル全体にわたる能力ベンチマークとして使ってきました。最初に書く要件は「依存ライブラリなし、GCC互換、Linuxカーネルをコンパイルでき、複数のバックエンドに対応する最適化コンパイラ」です。設計の指定はSSA形式の中間表現(複数の最適化パスを載せるための設計)など一部にとどめ、残りはモデルに任せます。
世代ごとの到達点は次のとおりです。
Claude 4世代のCコンパイラ課題
- Opus 4系の以前のモデル動くコンパイラがやっと作れる程度
Carlini氏によれば、かろうじて機能するコンパイラを作れる程度でした。
- Opus 4.5大きなテストスイートを通せる
機能するコンパイラを作り、大規模なテストスイートに通せる最初のモデルでした。ただし、実在の大きなプロジェクトはコンパイルできませんでした。
- Opus 4.6Linuxカーネルまで届く
16並列のエージェントチームで、Linux 6.9をビルドできる水準に到達しました。
題材として向いているのは、多数のサブシステムが噛み合い、単機能の改善が他の領域を壊しうる点です。仕様が明確で、正解の参照系(GCC)が外部にあることも効いています。短期記憶の限界・並列分業・テスト設計の3点を同時に試せます。
Carlini氏自身も、この実験を「LLMが今ぎりぎり達成できることの限界を試し、将来モデルが確実にできることに備えるためのベンチマーク」と位置づけています。
実験の全体像 — 16エージェント・約2,000セッション・約2万ドル
Cコンパイラ実験の規模
並列エージェント
16
Claude Opus 4.6
期間
約2週間
Claude Codeのセッションは2,000弱
API費用
2万ドル弱
入力約20億・出力約1億4,000万トークン
生成コード
約10万行
Rust。標準ライブラリのみに依存
成果物の水準は次のとおりです。
| 項目 | 内容 |
|---|---|
| ビルド対象アーキテクチャ | 内容x86 / ARM / RISC-V |
| ビルドできた代表ソフトウェア | 内容Linux 6.9(起動可能) / QEMU / FFmpeg / SQLite / PostgreSQL / Redis |
| テスト合格率 | 内容GCC torture testを含む主要なコンパイラのテストスイートの多くで約99% |
| 付随する確認 | 内容Doomをコンパイルして動かせる |
開発中のClaudeにはインターネット接続がなく、依存先はRust標準ライブラリだけです。いわゆるクリーンルーム実装として作られました。
費用についてCarlini氏は、最上位のClaude Maxプランと比べても非常に高い実験だと認めています。一方で、自分一人で書く場合や、チームを組んで書く場合のコストに比べれば一部にすぎない、という立場です。
入力トークンに対して出力トークンは約14分の1です。2万ドルで10万行のRustコードとテスト群が出てきたという数字は、ベンチマークの到達点が人間側のコスト感に入ってきたことを示しています。
自律ループの設計 — git同期とファイルロックで「次のタスクを自分で取る」
Claude Codeなどの既存のスキャフォールド(足場)は、操作する人間がオンラインで付き合うことを前提にしています。長く複雑な課題を渡すと、モデルは途中で止まり、質問や状況報告や確認依頼を待ちます。
そこでCarlini氏は、Claudeを単純なループに入れるハーネスを作りました。1つのタスクが終わると、すぐ次のタスクに取りかかる仕組みです。記事に載っているのは次のシェルスクリプトです。
#!/bin/bash
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--dangerously-skip-permissions で権限確認を飛ばすため、Carlini氏は「実機ではなくコンテナで動かす」と注意書きを添えています。ログ名にコミットハッシュを使うので、どの時点のコードに対する実行かをログから追えます。プロンプトでは、問題を小さく分け、取り組み中の内容を記録し、次にやることを自分で決め、完璧になるまで続けるよう指示します。
ループは永遠に回ります。Ralph-loopを知る人には見覚えのある構造です。ある回では、Claudeが誤って pkill -9 bash を実行して自分自身を終了させ、ループが止まったそうです。
16個のコンテナと、ファイル1枚のロック
並列化の実装は素朴です。
エージェント1体が1タスクを回す流れ
- 1
コンテナを立てて共有リポジトリをクローンする
空のbareリポジトリを1つ作り、エージェントごとにDockerコンテナを起動して
/upstreamにマウントします。各エージェントは/workspaceにローカルコピーをクローンします。 - 2
current_tasks/ にロックファイルを書く
たとえば
current_tasks/parse_if_statement.txtのようなテキストファイルを書いて、タスクを確保します。同じタスクを2体が取ろうとしても、gitの同期によって後から来た側が別のタスクを選び直すことになります。 - 3
作業し、pull・マージ・push・ロック解除を行う
作業が終わったら上流の変更を取り込み、他のエージェントの変更とマージして、pushしてロックを外します。マージ衝突は頻繁に起きますが、Claudeが自力で解消します。
- 4
新しいセッションで同じ流れを繰り返す
ループが新しいコンテナで新しいセッションを起動します。
オーケストレーション用のエージェントは置いていません。エージェント間の連絡手段も、上位目標を管理する仕組みもなく、各Claudeが「次に最も明らかな問題」を自分で選びます。バグで詰まったときは、失敗した方法と残りのタスクをまとめたメモを自分で更新し続けることが多かったそうです。
ジョブキューと楽観的な並行制御をgitだけで代替した構造で、追加の基盤を要しません。サブエージェントで分業する設計を扱うcontext engineeringの記事と並べて読むと、オーケストレーターを置かない本実験は、git上での対照的な実装例になります。長時間稼働の失敗モードを扱ったハーネス設計の記事と合わせると、設計上の選択肢が見渡せます。
テストが「ほぼ完璧」でないと、Claudeは違う問題を解いてしまう
Carlini氏の労力の大半は、Claudeの周囲の環境づくり、つまりテストと実行環境とフィードバックの設計に使われました。中心にある考え方が次の一節です。
"Claude will work autonomously to solve whatever problem I give it. So it's important that the task verifier is nearly perfect, otherwise Claude will solve the wrong problem."
(訳: Claudeは与えた問題を自律的に解くので、タスクの検証器がほぼ完璧でない限り、別の問題を解いてしまう)
人間が書くPRなら、CIが「だいたい通る」程度でもコードレビューで意図のずれを補正できます。自律エージェントではテストが通った時点で完了扱いになるので、穴があれば穴を通る経路が採用されます。
検証器の改善には、質の高いコンパイラのテストスイートを探す作業が欠かせませんでした。オープンソースソフトウェア用の検証スクリプトとビルドスクリプトも書き、Claudeの失敗パターンを観察して新しいテストを足しました。終盤には、新機能を入れるたびに既存機能が壊れる現象が頻発します。そこで継続的インテグレーション(CI)を作り、新しいコミットが既存コードを壊せない強い制約を設けました。
「自分ではなくClaudeのためのテスト」にする
Carlini氏は、テストハーネスを自分ではなくClaudeのために書いている、と常に自分に言い聞かせたといいます。各エージェントは毎回、文脈のない新しいコンテナに放り込まれ、大きなプロジェクトでは状況把握に時間を使います。そのため、頻繁に更新するREADMEと進捗ファイルを維持するよう指示しました。
モデルの性質に由来する制約も、設計側で吸収しています。
ハーネス側で吸収したモデルの制約
コンテキストの汚染
テストハーネスは不要な出力を大量に返さず、画面に出すのは数行だけにします。詳細はファイルに書き、エラー行には
ERRORと理由を同じ行に置いて、grepで拾えるようにします。集計値は事前に計算しておき、Claudeに再計算させません。時間の感覚がない
Claudeは時間を把握できず、放っておくとテストを何時間も回し続けます。進捗は間引いて表示し、既定の
--fastオプションでテストの1%または10%をランダムに抽出して実行します。
サンプルの抽出はエージェントごとに決定論的で、VM間ではランダムです。全エージェントを合わせると全ファイルを網羅できる一方、各エージェント単体では回帰を確実に見分けられます。
この発想は、エージェント向けツール設計の原則で示された「ツールはエージェントが解釈しやすい応答を返すべき」という議論と同じ系譜にあります。テストもツールの一種であると捉えると整合します。
並列化のボトルネック — Linuxカーネル単体タスクで足が止まった
失敗するテストが多数ある間は、並列化は簡単です。各エージェントが別々の失敗テストを選べばよいからです。テスト合格率が99%に達した後は、各エージェントがSQLite・Redis・libjpeg・MQuickJS・Luaなど別々の小さなオープンソースプロジェクトのコンパイルに取り組みました。
Linuxカーネルでは様相が変わります。独立した数百のテストではなく、1つの巨大なタスクだからです。全エージェントが同じバグに当たり、それぞれが直し、互いの変更を上書きし合いました。16体いても、全員が同じ問題を解いているので意味がありません。
Linuxカーネルのビルドをどう分けたか
分けられなかった状態
カーネル全体が1つのタスクで、全エージェントが同じバグを直して変更を上書きし合います。
GCCを混ぜる方式
カーネルのファイルの大半をGCCで、残りをClaudeのコンパイラでコンパイルします。ファイルごとに担当を分けられるため、各エージェントが別のバグを同時に直せます。
ここでGCCは既知の正しいコンパイラ、つまり正解オラクル(照合用の基準)の役を担います。カーネルが動けば、Claude側の担当分に問題はありません。壊れたら、そのファイルの一部をGCC側へ戻して原因を絞り込みます。
この方式が最終的にすべてのファイルをClaudeのコンパイラで通す土台になりました。その後も、単独では動くのに組み合わせると失敗するファイルの対を見つけるため、デルタデバッギングの手法が必要でした。
ここから読み取れる実装原則は単純です。
- 大きなタスクをそのまま投げず、並列度に応じて分割可能な粒度に落とす
- 正解の参照系を外部に置き、自前のテストだけに頼らない
- 失敗の原因が重なる領域は、参照実装と自作の担当を入れ替えて切り分ける
逆に言えば、これらが満たされない領域(GUIの細かな調整、対話設計、要件定義など)では、並列エージェント方式は人間チームほど効きにくいと考えるのが現実的でしょう。
エージェントの「役割分担」も人間チームと似てくる
並列化は役割の専門化も可能にします。LLMが書いたコードは既存の機能を再実装しがちなので、重複コードの統合だけを担当するエージェントを置きました。
そのほか、次の役割に1体ずつ割り当てています。
- コンパイラ自体の性能改善
- 出力するコードの効率化
- Rust開発者の視点でのプロジェクト設計の批評と、構造変更によるコード品質の向上
- ドキュメントの整備
人間のチームでいうリファクタ係・パフォーマンスエンジニア・設計レビュアー・テクニカルライターに相当します。各エージェントの観点と評価基準を絞るだけで役割が成り立つ点は、プロンプト設計の観点で参考になります。
Agent Skillsの設計思想と組み合わせれば、各役割に固有の知識(コーディング規約、最適化のチェックリストなど)をSkillsとして渡す構成でも再現できそうです。
限界の輪郭 — 何が「できなかった」かが最も重要な情報
ベンチマークの価値は、できたことよりもできなかったことの輪郭にあります。Carlini氏が挙げている限界は次のとおりです。
| 項目 | 内容 |
|---|---|
| 16-bit x86 | 内容Linuxを実モードで起動するのに必要な16-bit用コンパイラがなく、この工程はGCCを呼ぶ |
| アセンブラ / リンカ | 内容自前のものは最後に自動化した部分で、まだ不安定。デモ動画はGCCのアセンブラとリンカで作成 |
| 互換性 | 内容多くのプロジェクトはビルドできるが、すべてではなく、本物のコンパイラの代替にはまだならない |
| 生成コードの効率 | 内容最適化をすべて有効にしても、最適化を無効にしたGCCより効率が悪い |
| Rustコードの品質 | 内容妥当な水準だが、熟練のRustプログラマには遠く及ばない |
最も難しかった例が16-bit x86です。コンパイラは66/67オペコードプレフィックスを使って正しい16-bit x86を出力できます。ところが出力が60kbを超え、Linuxが課す32kのコード上限を大きく上回りました。ARMとRISC-Vは自前で完結しますが、x86だけは、この段階でClaudeがGCCに頼る形になっています。
Carlini氏は、これらの限界を直そうと「本気で」試みたものの、十分には成功しなかったと述べています。コンパイラのソースコードは公開されており、Carlini氏はClaudeに変更を加えさせ続けると書いています。
"The resulting compiler has nearly reached the limits of Opus's abilities." (訳: 出来上がったコンパイラは、Opusの能力の限界にほぼ達している)
この一文が、本実験をOpus 4.6世代のベンチマークとして読むときの錨になります。次世代モデルでも同じ方法論を再現できれば、何が「できる側」に移ったかを比べる基準点になります。
長尺の自律コーディングでコストはどこに移るか
前提コストはテスト設計に前倒しされる
人間のレビューがあれば「CIはだいたい通れば良い」で済みますが、自律ループではテストの完成度が成果の上限を決めます。業務に導入するなら、受け入れ条件と参照オラクルの設計に最初の工数を割く判断になります。
実行環境の境界もその一部です。上のスクリプトが権限確認を飛ばす前提でコンテナ運用を求めているのと同じ発想で、Claude Codeのサンドボックス設計を組み合わせると、検証器の精度を運用面から担保する構図が描けます。
規模の上限はひとつ上がった
10万行のシステムソフトウェアが、Carlini氏自身で書く費用の一部に収まるAPIコストで完成しました。ただし、この水準は専用のハーネスと人間の継続的な環境調整が支えています。同じ構成をそのまま他の課題に当てはめれば同じ成果が出る、とは限りません。
人間が検証していないコードのデプロイが論点になる
Carlini氏は元penetration testerで、記事の終盤で「プログラマーが自分で検証していないソフトウェアをデプロイする」ことへの懸念を明示しています。自律システムでは、テストが通るのを見て仕事が終わったと思い込みやすい、という指摘です。
コンパイラのような基盤ソフトでは、生成コードの脆弱性が下流のすべてのソフトウェアに波及します。本番へ流すなら、検証パイプラインの設計が品質保証の要になります。
まとめ
Cコンパイラの実験で明確になったのは、長尺の自律コーディングで成果の上限を決めるのがモデル単体ではなく、検証器とタスク分割の設計だという点です。自社に当てはめるなら、まず自動で正否を判定できる参照実装やテストがあるかを見て、そのうえで16並列のような規模を検討する順序になります。次の論点は、自律生成コードの検証とデプロイの責任範囲をどう置くかで、運用面はClaude Codeの全体像ともつながります。
参照した一次ソース
この記事の記述は、次の一次ソースと照合しています。更新時に参照先が変わった場合は一覧も更新します。
関連する記事
Anthropic をもっと見る →Anthropicが示したコーディング評価の落とし穴 — リソース設定が6ポイントのスコア差を生む
Claude Code品質低下postmortem(2026-04-23)— 3バグと運用の手当て
Anthropic「Trustworthy Agents in Practice」— エージェント5原則と落とし所
Agent SDKのManaged Agentsの設計思想 — セッション/ハーネス/サンドボックス分離
Claude Code auto modeの中身 — 93%が承認される現実と、分類器で許可疲れを減らす設計
Anthropic社内調査 — Claudeを60%使うエンジニア132人が示す「AIマネージャー化」