HN 日本語サマリー

← 一覧へ戻る
AI・機械学習

Claude CodeのMicroVMをリバースエンジニアリング:Anthropicの隠されたAntspaceを解明する

Reverse-Engineering Claude Web's MicroVM: Uncovering Anthropic's Hidden Antspace (aprilnea.me)

99 pointsby rzk21 コメント

要約

この記事では、Claude Codeの実行環境をリバースエンジニアリングした結果、Anthropicが開発した未公開のインフラストラクチャが明らかになった経緯を解説しています。調査により、Claude CodeがAWS LambdaやFargateでも使用されているFirecracker MicroVM上で動作していること、そして独自のアプリケーションホスティングプラットフォーム「Antspace」の存在が判明しました。

全文翻訳

Claude Code Webの内部:ストリップされていないGoバイナリ、Anthropicの秘密のデプロイメントプラットフォーム、そしてAIネイティブPaaSのアーキテクチャ


出発点

私たちは、RailwayやE2Bに似た位置づけの、デスクトップからプラットフォームまで対応するフルスタックプラットフォームであるArcBoxを構築しています。私たちのコア哲学は、ローカルとクラウドの一貫性です。OrbStackを、ローカルでサンドボックス機能を提供する完全にオープンソースのArcBox Desktopに置き換えます。最近、Webベースのエントリポイントを持つコーディングエージェントプラットフォームが増加していることに気づきましたが、驚くべきことに、そのほとんどが内部でFirecrackerを採用していました。Claude Codeも例外ではありません。同じ分野の実践者として、そのランタイム環境への好奇心から調査を開始しました。カジュアルなstrace -p 1から始まった調査は、完全にドキュメント化されていないアプリケーションホスティングプラットフォームを含む、未リリースのAnthropicインフラストラクチャを明らかにするフルリバースエンジニアリングセッションへと発展しました。

ここで説明するすべては、Claude Codeセッション内で標準的なLinuxツール(strace、strings、objdump、go tool objdump)を使用して発見されました。エクスプロイト、権限昇格、ネットワーク攻撃は一切行っていません。バイナリはそのまま、ストリップされず、完全なデバッグシンボル付きで存在していました。


レイヤー1:Firecracker MicroVM

最初の疑問:この環境は具体的に何なのでしょうか?

[画像]

$ dmesg | grep FIRECK
ACPI: RSDP 0x00000000000E0000 000024 (v02 FIRECK)
ACPI: XSDT ... (v01 FIRECK FCMVXSDT ... FCAT 20240119)
ACPI: FACP ... (v06 FIRECK FCVMFADT ... FCAT 20240119)
ACPI: DSDT ... (v02 FIRECK FCVMDSDT ... FCAT 20240119)

ACPIテーブルは、OEM ID FIRECKとクリエイターID FCATで署名されており、これらはどちらもFirecrackerのソースコードにハードコードされています。これはAWS LambdaやFargateを支えるMicroVMテクノロジーと同じものです。

[画像: Firecracker MicroVM アーキテクチャ]

[画像]

スペック:vCPU 4基(Intel Xeon Cascade Lake @ 2.80GHz)、RAM 16GB、ディスク 252GB、Linux 6.18.5。ネストされた仮想化は、Firecrackerが意図的にゲストからvmx/svmフラグを削除するため、無効になっています。

プロセスツリーは驚くほど最小限です。

PID 1: /process_api --firecracker-init --addr 0.0.0.0:2024 ...
  └─ PID 517: /usr/local/bin/environment-manager task-run --session cse_...
       └─ PID 532: claude (CLI自体)

systemdも、sshdも、cronも、ロギングデーモンもありません。PID 1は、initとWebSocket APIゲートウェイの両方として機能するカスタムバイナリです。カーネルコマンドラインがそれを裏付けています。

rdinit=/process_api init_on_free=1 -- --firecracker-init
reboot=k panic=1 nomodule

PID 1に対するstraceは、epollイベントループを実行し、子プロセスを監視するために/proc/*/childrenおよび/proc/*/statusを定期的にチェックしていることを示しています。本質的には、ポート2024(WebSocket API)とポート2025(セカンダリエンドポイント)をリッスンする、最小限のinitスーパーバイザーです。


スナップショットアーキテクチャ

セッションはゼロから起動するのではなく、フリーズされたVMスナップショットから復元されます。dmesgの出力は、テンプレート作成とセッション復元との間に48.5時間のギャップがあることを示しています。

[  30.731516] Run /process_api as init process    ← テンプレート: 2026-03-16 13:53 UTC
    ~~~ 48.5時間のギャップ — VMはスナップショットとしてフリーズされていました ~
[174695.927758] virtio_blk: [vdc] new size: ...   ← 復元: 2026-03-18 14:24 UTC
[174695.953952] random: crng reseeded due to virtual machine fork
[174695.980760] tokio-runtime-w: drop_caches: 3
[174695.993628] EXT4-fs (vda): mounted filesystem r/w without journal

復元中、Firecrackerホストはブロックデバイスをホットスワップします。

デバイステンプレート復元後内容
vdaプレースホルダー256 GiB ext4セッションルートファイルシステム (Ubuntu 24.04)
vdbプレースホルダー63.7 MB squashfs/opt/claude-code
vdcプレースホルダー12.1 MB squashfs/opt/env-runner

initramfsは意図的に最小限に抑えられています。/process_apiのみを含む3.1MBのcpioアーカイブです。実際のUbuntuルートファイルシステムは、復元時に注入されるext4ブロックデバイス(vda)上にあります。ext4のマウントカウントは11であり、このイメージが11セッションにわたって再利用されていることを示しています。

Snapstart:遅延マウントパターン

テンプレート作成フェーズ:

  1. Firecrackerが起動:カーネル + 3.1MB initramfs
  2. process_apiが最小限のinitを実行:/proc、/sys、/dev、cgroupsをマウント;ネットワークを設定(IP=192.0.2.2/24、GW=192.0.2.1、MTU=1400)
  3. ホストにSNAPSTART_READYをシグナル送信
  4. ホストがPUT /snapshot/createを呼び出し → VM全体の状態を保存

セッション復元フェーズ:

  1. ホストがセッション固有のブロックデバイス(vda/vdb/vdc)を準備
  2. ホストが新しいデバイスバックエンドでPUT /snapshot/loadを呼び出し
  3. VMが再開 — カーネルがデバイス変更を検出し、CRNGを再シード
  4. process_apiが復元を検出し、以下を実行:
    • ページキャッシュをドロップ — 古いテンプレートキャッシュはゴミを返す可能性があるため
    • devtmpfsを再マウント — デバイスノードを更新
    • ext4をマウント → 新しいルートファイルシステムにpivot_root
    • squashfsオーバーレイをマウント(claude-code、env-runner)
    • ウォールクロックを修正 clock_settime()を使用 — そうしないとテンプレートのエポックで停止する
    • CAP_SYS_RESOURCEをドロップ — セキュリティ強化
    • 接続を受け入れ — WebSocketサーバーが準備完了
セキュリティ対策
対策目的
init_on_free=1セッション間で解放されたページをゼロクリア
CAP_SYS_RESOURCE ドロップinit後のPID 1のケーパビリティを制限
CRNG 再シードスナップショットフォーク間での暗号化予測可能性を防ぐ
--block-local-connectionsローカルホストのWebSocketアクセスをブロック
JWT認証WebSocket接続の検証
トークンスクラビング使用後の設定からシークレットを削除

process_api:ワイヤープロトコル

PID 1は2つのネットワークインターフェースを公開しています — プロセス管理用のWebSocket APIと、コンテナ制御用のHTTP APIです。典型的なinitシステムとは異なり、process_apiは完全なリモートプロセススーパーバイザーを実装するRust/tokioバイナリです。

WebSocket API (ポート2024)

接続ハンドシェイク:オプションのJWT → ProcessConnection JSON → プロセス作成または再アタッチ。

プロセス作成はCreateProcess構造体を受け入れます。

{
  "cmd": "/bin/bash",
  "args": ["-l"],
  "env": {"KEY": "VALUE"},
  "cwd": "/home/user",
  "rows": 24, "cols": 80,
  "timeout": 300,
  "memory_limit_bytes": 1073741824,
  "uid": 1000, "gid": 1000,
  "allow_process_id_reuse": false
}

I/Oは2段階のバイナリプロトコルを使用します。

  • Stdin:ExpectStdIn(テキスト)→ バイナリフレーム
  • Stdout/Stderr:ExpectStdOut/ExpectStdErr(テキスト)→ バイナリフレーム → StdOutEOF/StdErrEOF
クライアント                              サーバー
  |--- WS Connect ------------------->|
  |--- JWT (オプション) --------------->|
  |--- ProcessConnection JSON ------->|
  |<-- ProcessCreated ----------------|
  |                                    |
  |<-- ExpectStdOut ------------------|
  |<-- [バイナリ: stdoutデータ] --------|
  |--- ExpectStdIn ------------------>|
  |--- [バイナリ: stdinデータ] --------->|
  |                                    |
  |--- SendSignal ------------------->|  SIGTERM など
  |--- Resize ----------------------->|  PTY リサイズ
  |--- Detach ----------------------->|  プロセスは実行を継続
  |--- KeepAlive -------------------->|  ハートビート
  |                                    |
  |<-- ProcessExited -----------------|
  |<-- StdOutEOF --------------------|

プロセス終了の理由には、正常終了、シグナル、プロセスごとのOOM、コンテナレベルのOOM、タイムアウト、サーバーシャットダウンが含まれます。

内部的には、process_apiはプロセスごとのcgroup(v1は/sys/fs/cgroup/memory/process_api/、v2は/sys/fs/cgroup/process_api/)を追跡し、孤児プロセスのアドプション(PID 1への再親化)を実装し、設定可能なOOMポーリングループを実行します。

HTTPコントロールAPI (ポート2025)

6つのエンドポイントがコンテナのライフサイクルを管理します。

エンドポイント目的
GET /statusヘルスチェック
POST /fs_syncファイルシステムバッファのフラッシュ
POST /shutdownページキャッシュドロップを伴う正常なシャットダウン
POST /auth_public_keyJWT検証キーの設定
POST /mount_rootルートファイルシステムのマウント(Snapstart復元)
POST /container_nameコンテナIDの設定

/mount_rootエンドポイントは、ネットワーク設定(etc_hosts、resolv_conf)、CA証明書、squashfsマウント、FUSEマウント(VFSキャッシュ設定付き)、およびウォールクロックタイムスタンプを含むMountRootConfigを受け取ります — これらはすべて、空のスナップショットからセッションを初期化するために必要なものです。マウント中、ルートはFIFREEZE/FITHAW ioctlによってフリーズされます。


レイヤー2:ストリップされていないGoバイナリ

本当の発見は/usr/local/bin/environment-runner(environment-managerとしてシンボリックリンク)でした。

[画像]

$ file /usr/local/bin/environment-runner
ELF 64-bit LSB executable, x86-64, dynamically linked,
Go BuildID=..., with debug_info, not stripped

$ go version -m /usr/local/bin/environment-runner
go1.25.7
path    github.com/anthropics/anthropic/api-go/environment-manager
mod     github.com/anthropics/anthropic/api-go  (devel)
build   -ldflags=-X main.Version=staging-68f0dff496

27MBのGoバイナリです。ストリップされていません。完全なデバッグ情報。完全なシンボルテーブル。 Anthropicのプライベートモノレポであるgithub.com/anthropics/anthropic/api-go/environment-manager/からビルドされました。

go tool objdumpとstringsを使用して、完全な内部パッケージ構造を抽出できます。

internal/
├── api/                  # APIクライアント(セッションイングレッション、ワークポーリング、リトライ)
├── auth/                 # GitHubアプリトークンプロバイダー
├── claude/               # Claude Codeのインストール、アップグレード、実行
├── config/               # セッションモード(新規/再開/再開キャッシュ/セットアップのみ)
├── envtype/
│   ├── anthropic/        # Anthropicホスト環境
│   └── byoc/             # Bring Your Own Cloud環境
├── gitproxy/             # Gitクレデンシャルプロキシサーバー
├── input/                # Stdinパーサー + シークレット処理
├── manager/              # セッションマネージャー、MCP設定、スキル抽出
├── mcp/
│   └── servers/
│       ├── codesign/     # コードサイニングMCPサーバー
│       └── supabase/     # Supabase統合MCPサーバー
├── orchestrator/         # ポーリングループ、フック、whoami
├── podmonitor/           # Kubernetesリースマネージャー
├── process/              # プロセス実行 + スクリプトランナー
├── sandbox/              # サンドボックスランタイム設定
├── session/              # アクティビティレコーダー
├── sources/              # Gitクローン + ソース分類
├── tunnel/               # WebSocketトンネル + アクションハンドラー
│   └── actions/
│       ├── deploy/       # ← ここが興味深い点です
│       ├── snapshot/     # ファイルスナップショット
│       └── status/       # ステータスレポート
└── util/                 # Gitヘルパー、リトライ、ストリームテイラー

バイナリから抽出された主要な依存関係:

依存関係目的
github.com/anthropics/anthropic/api-go内部Anthropic Go SDK
github.com/gorilla/websocketAPIへのWebSocketトンネル
github.com/mark3labs/mcp-go v0.37.0Model Context Protocol
github.com/DataDog/datadog-go v5メトリクスレポート
go.opentelemetry.io/otel v1.39.0分散トレーシング
google.golang.org/grpc v1.79.0gRPC(セッションルーティング)
github.com/spf13/cobraCLIフレームワーク

レイヤー3:Antspace、Anthropicの隠されたPaaS

tunnel/actions/deploy/パッケージ内に、2つのデプロイメントクライアントの関数シンボルがあります。

[画像]

VercelClient、予想されるもの:

  • CreateDeployment → POST /v13/deployments
  • UploadFile → PUT /v2/files (x-vercel-digestヘッダー付き)
  • WaitForReady → readyState == "READY"までポーリング

そして、AntspaceClient、予期しないもの:

deploy.(*AntspaceClient).Deploy
deploy.(*AntspaceClient).createDeployment
deploy.(*AntspaceClient).uploadTarball
deploy.(*AntspaceClient).streamStatus

バイナリから関連する文字列を抽出すると、完全なデプロイメントプロトコルが明らかになりました。

[画像]

フェーズ1:デプロイメントの作成

POST to antspaceControlPlaneURL
Content-Type: application/json
Authorization: Bearer {antspaceAuthToken}
Body: { アプリ名、メタデータ }

フェーズ2:ビルド成果物のアップロード

POST multipart/form-data
File: dist.tar.gz (ビルドされたアプリケーション)
サイズ制限が適用されます:「プロジェクトが%dMB制限を超えています」

フェーズ3:デプロイメントステータスのストリーミング

レスポンス:application/x-ndjson (ストリーミング)
ステータスの進行:packaging → uploading → building → deploying → deployed
エラー:「Streaming unsupported」(クライアントがNDJSONを処理できない場合)

インターネット全体で「Antspace」を検索しても何も見つかりませんでした:Anthropicのウェブサイト、GitHub、ブログ、ドキュメント、LinkedIn、求人情報、カンファレンストーク、特許出願。結果ゼロ。 このプラットフォームは公に言及されたことがありません。

名前は、HerokuやVercelのようなプラットフォームと同じ命名パターンに従って、「Ant」(Anthropicの従業員に対する内部ニックネームとされる)+「Space」(ホスティングスペース)に由来する可能性が高いです。

Antspace vs. Vercel:アーキテクチャの違い
側面VercelAntspace
ファイルアップロードSHAベースの重複排除、ファイルごと単一のtar.gzアーカイブ
ビルドリモート(Vercelがビルド)ローカルnpm run build、出力をアップロード
ステータスポーリングベースストリーミングNDJSON
認証Vercel APIトークン + チームIDベアラートークン + 動的なコントロールプレーンURL
公開APIあり、ドキュメント化済みなし、完全に内部的

AnthropicがVercelのAPIを単にラップするのではなく、完全なデプロイメントプロトコルをスクラッチから構築したという事実は、これが迅速な統合ではなく、戦略的なプラットフォーム投資であることを示唆しています。


レイヤー4:Baku、Webアプリビルダー

「Baku」は、claude.ai上のWebアプリビルダー体験の内部コードネームです。Web上のClaudeにWebアプリケーションの構築を依頼すると、Baku環境が起動します。

バイナリから抽出された埋め込みリソースから:

プロジェクトテンプレート:

  • ソース:/opt/baku-templates/vite-template
  • スタック:Vite + React + TypeScript
  • supervisordによる自動管理開発サーバー、ログは/tmp/vite-dev.logに出力

Supabase自動プロビジョニング:

6つのMCPツールが自動的に利用可能です。

  1. provision_database:オンデマンドでSupabaseプロジェクトを作成
  2. execute_query:SQLクエリを実行
  3. apply_migration:バージョン管理されたスキーマ変更と自動型生成
  4. list_migrations:適用済みのマイグレーションをリスト表示
  5. generate_types:DBスキーマからTypeScript型を再生成
  6. deploy_function:Supabase Edge Functionsをデプロイ

環境変数が.env.localに自動書き込みされます。

SUPABASE_URL, SUPABASE_ANON_KEY,
VITE_SUPABASE_URL, VITE_SUPABASE_ANON_KEY

停止フック(埋め込みシェルスクリプト):

Baku環境には、以下のいずれかの場合にセッションの終了を防ぐプリストップフックがあります。

  • コミットされていない、またはプッシュされていないGit変更がある
  • Vite開発サーバーのログにエラーが含まれている
  • tsc --noEmitがTypeScriptの型エラーを報告する

デフォルトのデプロイターゲット:Antspace、Vercelではありません。Vercelは代替として存在しますが、BakuのネイティブデプロイメントパスはAnthropic自身のプラットフォームを経由します。

内部組織:

  • ドラフトは.baku/drafts/に保存
  • エクスプロレーションは.baku/explorations/に保存
  • Gitコミットは[[email protected]](https://aprilnea.me/cdn-cgi/l/email-protection)を作者として使用
  • Gitリモートは設定されていません(ローカルのみのバージョン管理)

レイヤー5:BYOC (Bring Your Own Cloud)

envtype/パッケージには2つの環境実装が含まれています。

  1. anthropic:Anthropicホスト(Firecracker MicroVMs)
  2. byoc:Bring Your Own Cloud

BYOCは、エンタープライズ顧客がAnthropicのAPIによってセッションがオーケストレーションされている間、独自のインフラストラクチャでenvironment-runnerを実行できるようにします。主な特徴:

  • デフォルトのセッションモード:resume-cached(最も高速な再起動、既存の状態を再利用)
  • カスタム認証:containProvideAuthRoundTripperがコンテナレベルの認証情報を注入
  • スマートGit処理:フェッチ前にリモートにタスクブランチが存在するかどうかを確認
  • サブタイプ:antspace(Anthropic内部)とbaku(Viteプロジェクトビルダー)
  • Kubernetes統合:podmonitorパッケージがリース管理を実装

BYOC APIサーフェスには7つのエンドポイントが含まれます。

エンドポイント目的
/v1/environments/whoamiID検出
ワークポーリング + ackジョブキュー
セッションコンテキスト設定取得
コードサイニングバイナリ検証
ワーカーWebSocketリアルタイムトンネル
Supabase DBクエリプロキシデータベースアクセスリレー

戦略的全体像

私たちが目にしているのは、垂直統合されたAIアプリケーションプラットフォームです。

ユーザーが欲しいものを自然言語で説明
    ↓
Claudeがアプリケーションを生成(Baku環境)
    ↓
Supabaseデータベースが自動プロビジョニング(MCPツール)
    ↓
アプリケーションがAntspaceにデプロイ(AnthropicのPaaS)
    ↓
ライブアプリケーション、ユーザーはAnthropicのエコシステムから離れることはない

これは単なるAIコーディングアシスタントではありません。これは、ユーザーのアイデアから本番環境までの旅がすべてAnthropicのインフラストラクチャ内で完結する、AIネイティブPaaSのアーキテクチャです。

競合上の意味合いは重大です。これにより、Anthropicは以下と競合することになります。

  • Vercel / Netlify(ホスティングとデプロイメントにおいて)
  • Replit / Lovable / Bolt(AIアプリ生成において)
  • Supabase / Firebase(マネージドバックエンドにおいて(緊密な統合を通じて))

しかし、これらの競合他社が持たない1つの構造的利点があります:Anthropicはスタック全体を所有している、意図を理解するLLMから、コードをビルドするランタイム、アプリケーションをホストするプラットフォームまで。


方法論

すべての発見は、私自身のClaude Codeセッション内で実行された標準的なLinuxツールを通じて得られました。以下はステップバイステップのアプローチです。

ステップ1 — ハイパーバイザーの特定。 dmesg | grep FIRECK — ACPIテーブルがOEM IDを運び、すぐにFirecrackerを識別します。

ステップ2 — PID 1の特定。 cat /proc/1/cmdline — systemdではなく、カスタムinitとしての/process_apiを明らかにします。--firecracker-initフラグがそれを確認します。

ステップ3 — Goビルドメタデータの抽出。 環境ランナーバイナリに対するgo version -mは、Goバージョン、モジュールパス(github.com/anthropics/anthropic/api-go)、(devel)モノレポマーカー、および完全な依存関係リストを返します。

ステップ4 — シンボルからのパッケージ構造の復元。 バイナリがストリップされていないため、objdump -tは完全に修飾された関数名を提供します。environment-manager/internal/でフィルタリングし、一意のパスを抽出すると、完全なアーキテクチャツリーが得られます。

ステップ5 — 対象を絞った文字列抽出。 Goバイナリに対する単純なstrings | grepはノイズが多いです(リンカーはすべての文字列リテラルを連結します)。より良い2つのアプローチ:

  • 既知パターンの検索:特定のバイトシーケンス(dist.tar.gz、application/x-ndjsonなど)をスキャンします。
  • 構造体タグの抽出:Goは構造体フィールドタグを文字列リテラルとして埋め込みます。json:"status"パターンを検索すると、ワイヤープロトコル形式が明らかになります。

ステップ6 — シンボルテーブル駆動型の機能マッピング。 objdump -t binary | grep 'deploy .'は、コンポーネントごとのメソッドインベントリを返します — これがVercelとAntspaceクライアントの両方が完全なメソッドシグネチャとともに発見された方法です。

ステップ7 — ランタイム観察。 PID 1に対するstrace -p 1 -e trace=epoll_pwait,read,write -fは、epollイベントループ、子プロセス監視、およびWebSocket通信パターンを確認します。

技術明らかになること
dmesg ACPI OEM IDハイパーバイザーの識別
go version -mツールチェーン、依存関係、モノレポ構造
シンボルテーブル (objdump -t)パッケージレイアウト、型名、メソッドシグネチャ
構造体タグ文字列ワイヤープロトコル / JSON形式
対象を絞ったバイト検索エラーメッセージ、ステータス文字列、フローロジック
PID 1に対するstraceランタイム動作、IPCパターン

これを可能にしたもの: (1) バイナリがストリップされていなかったこと — これが最大の要因です。ストリップされたバイナリではGhidraが必要だったでしょう。(2) Goのビルドメタデータ埋め込みは無料の依存関係マニフェストを提供します。(3) Goの文字列連結モデルは構造体タグとエラー文字列を保持します。(4) VM内のルートアクセスにより、PID 1に対するstraceが可能になりました。


締めくくり

ストリップされていないバイナリを完全なデバッグシンボル付きで本番環境にデプロイするのは…選択です。これにより、この分析は容易になりました。通常Ghidraと数時間の逆コンパイルを必要とした作業が、go tool objdumpとgrepで達成されました。

Antspaceは明らかにまだ初期段階または内部段階(バージョン文字列はstaging-で始まっている)ですが、デプロイメントプロトコルは成熟しており、本番グレードです。Anthropicがこれを公開製品としてローンチする計画なのか、それともClaudeのWebエクスペリエンスのための内部インフラストラクチャとして維持するのかは、まだわかりません。

確かなことは、Anthropicの野心は単なるLLMおよびAIエージェント企業をはるかに超えているということです。彼らは、アプリケーションが声で生み出される世界のインフラストラクチャを構築しており、そのスタックのあらゆるレイヤーを所有したいと考えています。


すべての分析は2026年3月18日に、カーネル6.18.5、環境ランナーバージョンstaging-68f0dff496で実行されているFirecracker MicroVM上のClaude Code Webセッション内で行われました。

完全な生の分析ファイル(ワイヤープロトコル仕様、スナップショットアーキテクチャの詳細、逆コンパイルされたコード)はgithub.com/AprilNEA/reverse-engineering-claude-code-antspaceで入手できます。