JavaScript のランタイムでありバンドラー、パッケージマネージャーでもある Bun が、Zig ではなく Rust の上で動くようになりました。そこに至る移植に要したのは、作者が人間のエンジニアを前提に見積もっていた 1 年ではなく、継続的に監督されたエージェントのワークフロー 11 日分です。ジャレッド・サムナー氏がその過程を詳細に記録しました。Bun v1.4 はすでに出荷され、Claude Code と Prisma の Compute ベータがその上で動いており、機械が書いた 100 万行規模のシステムコードを信頼するのに実際どれだけのコストがかかるのかを問うだけの実運用の材料がそろっています。
要点
- 1,448 ファイルにまたがる Zig の 535,496 行を、およそ 50 本の Claude Code ワークフローが移植しました。4 つの git ワークツリーに分割し、各ツリーで 16 個のエージェントインスタンスを走らせ、ピークは毎分およそ 1,300 行、1 時間で 695 コミットに達しています。
- 実装役のエージェントには必ず、敵対的なレビュアー 2 体が組み合わされました。レビュアーは差分だけを見せられ、そのコードは間違っていると想定せよと指示されています。
- Bun v1.4.0 は、最後の Zig リリースである v1.3.14 で今も再現する 128 件のバグを修正しました。一方で HTTP のスループット改善は 2〜5 パーセントにとどまります。
100 万行の差分をかろうじてレビュー可能にしたもの
前提条件は、サムナー氏が数年前に積み上げていた幸運でした。Bun のテストスイートは TypeScript で書かれているため、下層のランタイムがどの言語で実装されていようと気にせず挙動だけを検証します。おかげで移植中ずっと変わらない、100 万を超えるアサーションからなる固定の基準が手に入りました。テストが元の言語で書かれていたなら、この錨は存在しませんでした。
第二は構造上の判断です。1 体のエージェントにコードを書かせて自分の成果を自分で確認させるのではなく、サムナー氏は役割を分けました。実装役が 1 体、別々のコンテキストウィンドウで差分だけを受け取る敵対的レビュアーが 2 体以上、そして指摘を反映する修正役を別に置く構成です。理由として挙げられているのは技術面ではなく振る舞いの話で、コードを書いたモデルは人間の書き手とまったく同じようにそれをマージしたがるため、レビュアーは別の指示を受けた別のインスタンスでなければならない、というものです。公開された例には、libuv がまだポインタを保持しているのに破棄された Box<uv::Pipe>、正しい CSS の color-mix() でパニックした先行評価型の unwrap_or、1970 年より前のファイルタイムスタンプで負のナノ秒を生んだ timespec 変換があります。いずれもコンパイルはきれいに通りました。
第三に、出力が誤っていたときに直すのは成果物ではなくループでした。最初の全体実行から 2 分で、エージェント同士が git stash によって互いの作業を上書きしましたが、対応は壊れたコミットを修復することではなく、ワークフローの指示文を書き直すことでした。およそ 3 時間の計画作業から、Zig のイディオムを Rust に対応づける PORTING.md と、すべての構造体フィールドの意図された生存期間を記録した LIFETIMES.tsv が生まれ、どちらも 1 行も移植する前に敵対的なレビューを受けています。
きれいにコンパイルされた回帰
捕まったものより、すり抜けたもののほうが示唆に富みます。サムナー氏によれば、回帰の大半は両言語で同じに見えて振る舞いが異なる構文から生じました。Zig の assert は関数なので、引数はどのビルドでも評価されます。一方 Rust の debug_assert! はマクロで、リリースビルドでは式全体が消えます。そのアサーションの内側に置かれていた副作用、つまりホットリロードのグラフにファイルを登録する処理が、リリースビルドで静かに実行されなくなり、デバッグビルドは緑のままで React の Fast Refresh が壊れました。
ほかも同じ形です。末尾の奇数バイト 1 つを黙って無視していたヘルパーが bytemuck::cast_slice に移植された結果、そのケースでパニックするようになり、UTF-16 のバイトオーダーマークでプロセスが落ちました。64 のまま残されたプレースホルダー定数ひとつが、インターン済みファイル名の上限を 840 万から 270,272 に引き下げ、実際のプロジェクトがぶつかる制限になりました。Bun の色マーカー整形処理は Zig のコンパイル時評価を失い、置換された引数の内側にあるマーカーまで書き換え始めました。InfoQ はこうした意味上の回帰を 19 件と数え、あわせてセキュリティレビュー 11 巡と、継続的なパーサーのファジングから出たプルリクエスト 15 件を挙げています。このいずれもメモリ安全性の失敗ではありません。借用チェッカーは仕事をしました。すべては意味の失敗であり、それはどのコンパイラも捕まえられない種類のものです。
書き直しで実際に得たもの
性能の数字は控えめで、正直に報告されています。HTTP スループットが 2〜5 パーセント向上し、vite build が 1.69 秒から 1.65 秒になった程度です。本当の見返りはメモリ管理の規律でした。Zig では defer を呼び出し箇所ごとに書く必要がありましたが、Rust の Drop は後始末を自動で走らせます。同じプロジェクトを 1 プロセス内で 2,000 回バンドルするベンチマークは、v1.3.14 ではビルドごとにおよそ 3 MB を上限なく漏らしていたのに対し、いまは頭打ちになります。リンカ最適化と ICU の削減を移植と組み合わせた結果、バイナリサイズは Linux と Windows でおよそ 20 パーセント減りました。Claude Code は 6 月の v2.1.181 以降 Rust ビルドで動いており、Linux の起動が 10 パーセント速くなったものの、サムナー氏の言葉を借りれば、気づいた人はほとんどいませんでした。
Zig 作者からの反論
Zig の作者アンドリュー・ケリー氏は鋭い反論を公開し、この語り口は論点をずらしていると論じました。バグはスタイルガイドと言語機能のどちらを選ぶかではなく、そこにエンジニアリング資源を投じることで消えるのだ、という主張です。さらに切れ味の鋭い問いは一貫性に関するもので、Bun のテストスイートが Zig コードのバグを捕まえるのに十分でなかったのなら、人間がレビューしていない 100 万行の生成された Rust を検証するのに十分だと考える理由は見いだしにくい、というものです。
もっともな指摘であり、正直な答えは、テストスイートが唯一の統制ではなかったということです。敵対的レビュー、CI での Miri、LeakSanitizer、24 時間体制のファジングがその上に重ねられました。この積み重ねがコードに対する人間の理解の代わりになるのかどうかは、まさに未検証のまま残されています。
この事例を注視すべき理由
サムナー氏が公開した費用、すなわちマージまでにキャッシュされない入力トークン 59 億と出力トークン 6 億 9,000 万を使い、API 価格でおよそ 16 万 5,000 ドルという数字は、これまで事実上不可逆だった判断に値札を付け直します。成熟したコードベースの言語選択は一方通行の扉でしたが、いまや予算項目です。2025 年 12 月に Bun を買収しサムナー氏を雇用しているアンソロピックには、その結論に明白な利害があり、本件は今年出荷されたエージェント主導の書き直しのひとつでもあります。残る問いは保守です。誰一人として端から端まで読んでいないコードベースも、これから何年も人間の手で拡張され、デバッグされ、筋道を立てて考えられなければなりません。月間 2,200 万回の CLI ダウンロードを抱える Bun は、業界がその答えを知る場になります。
よくある質問
Bun の Rust コードはすべて AI が監督なしで書いたのですか
いいえ。サムナー氏は 11 日間を通じてワークフローを監視し、出力を手で読み、エージェントが悪い結果を出すたびにループを編集しました。敵対的レビュアーが本物の差異を捕まえているかを確認する形で移植をレビューし、Zig と Rust を並べて相当な分量を自ら読んでいます。
報道では 4 か月とありますが、なぜ移植は 11 日なのですか
11 日は移植そのもの、つまり着手から全プラットフォームでテストスイートが通るまでの期間です。長いほうの数字は追加検証とリリースまでに流れた時間を反映しています。記事は 2026 年 7 月に公開され、安定版の Bun v1.4.0 は 8 月に続きました。
Bun には Zig がまだ残っていますか
残っていません。Bun v1.3.14 が最後の Zig リリースで、v1.4.0 が最初の Rust リリースです。Bun のおよそ 20 パーセントは依然として C++ で、JavaScriptCore や uWebSockets といった組み込みの依存関係が含まれますが、今回の書き直しはそこには手を付けていません。






