逆向 Claude Web 的 MicroVM:揭开 Anthropic 隐藏的 Antspace 平台
Claude Code Web 内部是怎样的:一个未剥离符号的 Go 二进制、Anthropic 的机密部署平台,以及一个 AI 原生 PaaS 的架构
起点
我们正在打造 ArcBox,一个从桌面端到平台端的全栈平台,定位类似 Railway 和 E2B。我们的核心理念是本地与云端一致:用完全开源的 ArcBox Desktop 替代 OrbStack,在本地提供沙箱能力。最近我们发现,越来越多的 Coding Agent 平台开始上线网页入口,而且几乎无一例外,底层都选了 Firecracker。Claude Code 也不例外。作为同领域的从业者,我们好奇它的运行环境,于是顺手挖了挖。本来只是随手敲了个 strace -p 1,结果演变成了一场完整的逆向工程,挖出了 Anthropic 尚未发布的基础设施,包括一个完全没有文档的应用托管平台。
本文所有内容,都是在一个 Claude Code 会话里用标准 Linux 工具(strace、strings、objdump、go tool objdump)发现的。没有漏洞利用,没有提权,没有网络攻击。那个二进制就摆在那里,符号没剥,调试信息一应俱全。
第一层:这是个 Firecracker MicroVM
第一个问题:这到底是什么环境?

ACPI 表的 OEM ID 是 FIRECK,创建者 ID 是 FCAT,两者都硬编码在 Firecracker 的源码里。这正是支撑 AWS Lambda 和 Fargate 的那套 MicroVM 技术。


配置如下:4 个 vCPU(Intel Xeon Cascade Lake @ 2.80GHz)、16GB 内存、252GB 磁盘、Linux 6.18.5。不支持嵌套虚拟化,因为 Firecracker 会刻意从 guest 中移除 vmx/svm 标志。
进程树精简得离谱:
没有 systemd,没有 sshd,没有 cron,没有日志守护进程。PID 1 是一个自定义二进制文件,同时充当 init 和 WebSocket API 网关。内核命令行证实了这一点:
对 PID 1 执行 strace,可以看到它在跑一个 epoll 事件循环,定期检查 /proc/*/children 和 /proc/*/status 来监控子进程。本质上就是一个极简的 init 监管程序,监听 2024 端口(WebSocket API)和 2025 端口(辅助端点)。
快照架构
会话不是从零启动的——它们是从冻结的虚拟机快照中恢复出来的。dmesg 输出显示,模板创建和会话恢复之间隔了 48.5 小时:
恢复过程中,Firecracker 宿主机热插拔块设备:
initramfs 是刻意精简的:一个 3.1MB 的 cpio 归档,里面只有 /process_api。真正的 Ubuntu 根文件系统在 ext4 块设备(vda)上,恢复时才注入。该 ext4 的挂载计数为 11,说明这个镜像已经被 11 个会话复用过了。
Snapstart:延迟挂载模式
模板创建阶段:
-
Firecracker 启动:内核 + 3.1MB initramfs
-
process_api执行最小初始化:挂载/proc、/sys、/dev、cgroups;配置网络(IP=192.0.2.2/24,GW=192.0.2.1,MTU=1400) -
向宿主机发送
SNAPSTART_READY信号 -
宿主机调用
PUT /snapshot/create→ 保存整个虚拟机状态
会话恢复阶段:
-
宿主机准备会话专属的块设备(vda/vdb/vdc)
-
宿主机调用
PUT /snapshot/load,传入新的设备后端 -
虚拟机恢复运行——内核检测到设备变化,重新初始化 CRNG
-
process_api检测到恢复操作,然后执行: - 丢弃页缓存——残留的模板缓存会返回垃圾数据
- 重新挂载 devtmpfs——刷新设备节点
- 挂载 ext4 → 通过
pivot_root切换到新的根文件系统 - 挂载 squashfs 覆盖层(claude-code、env-runner)
- 通过
clock_settime()修正墙上时钟——否则会卡在模板的时间点 - 丢弃 CAP_SYS_RESOURCE——安全加固
-
接受连接——WebSocket 服务器就绪
-
丢弃页缓存——残留的模板缓存会返回垃圾数据
-
重新挂载 devtmpfs——刷新设备节点
-
挂载 ext4 → 通过
pivot_root切换到新的根文件系统 -
挂载 squashfs 覆盖层(claude-code、env-runner)
-
通过
clock_settime()修正墙上时钟——否则会卡在模板的时间点 -
丢弃 CAP_SYS_RESOURCE——安全加固
-
接受连接——WebSocket 服务器就绪
安全措施
process_api:通信协议
PID 1 对外暴露两个网络接口——一个负责进程管理的 WebSocket API,和一个负责容器控制的 HTTP API。和常见的 init 系统不同,process_api 是一个 Rust/tokio 写的二进制程序,实现了一套完整的远程进程管理能力。
WebSocket API(端口 2024)
连接握手流程:可选的 JWT → ProcessConnectionJSON → 创建进程或重新挂载已有进程。
创建进程时接收一个 CreateProcess 结构体:
I/O 采用两阶段二进制协议:
-
Stdin:ExpectStdIn(text) → 二进制帧
-
Stdout/Stderr:ExpectStdOut/ExpectStdErr(text) → 二进制帧 → StdOutEOF/StdErrEOF
进程终止的原因包括:正常退出、信号终止、进程级 OOM、容器级 OOM、超时、以及服务器关闭。
在内部,process_api 会为每个进程维护独立的 cgroup(v1 路径在 /sys/fs/cgroup/memory/process_api/,v2 在 /sys/fs/cgroup/process_api/),实现了孤儿进程接管(重新挂到 PID 1 下),并运行一个可配置的 OOM 轮询循环。
HTTP 控制 API(端口 2025)
六个端点用于管理容器生命周期:
/mount_root 端点接收一个 MountRootConfig,里面有网络配置(etc_hosts、resolv_conf)、CA 证书、squashfs 挂载、FUSE 挂载(带 VFS 缓存配置)以及墙上时钟时间戳——从空白快照初始化一个会话所需的全部内容都在这儿了。挂载期间,root 会通过 FIFREEZE/FITHAW 这两个 ioctl 冻结。
第二层:未 strip 的 Go 二进制
真正的发现是 /usr/local/bin/environment-runner(同时被软链接为 environment-manager):

一个 27MB 的 Go 二进制,没有 strip,带着完整的调试信息和符号表。它编译自 Anthropic 的私有 monorepo,路径是 github.com/anthropics/anthropic/api-go/environment-manager/。
用 go tool objdump 和 strings,就能把完整的内部包结构提取出来:
从二进制里提取出的关键依赖:
第三层:Antspace,Anthropic 隐藏的 PaaS
在 tunnel/actions/deploy/ 包里,能看到两个部署客户端的函数符号:

先看预期之中的 VercelClient:
- CreateDeployment → POST /v13/deployments
- UploadFile → PUT /v2/files,带 x-vercel-digest 请求头
- WaitForReady → 轮询直到 readyState == "READY"
再看意料之外的 AntspaceClient。
从二进制文件中提取相关字符串后,一整套部署协议浮出水面:

阶段一:创建部署
阶段二:上传构建产物
阶段三:流式获取部署状态
在整个公开互联网上搜索"Antspace",一无所获:Anthropic 官网、GitHub、博客、文档、LinkedIn、招聘信息、会议演讲、专利申请——全都查过了,零结果。这个平台从未在任何公开场合被提及。
名字可能来自"Ant"(据说是 Anthropic 员工的内部昵称)加上"Space"(托管空间),跟 Heroku、Vercel 这类平台的命名思路一样。
Antspace vs. Vercel:架构差异
Anthropic 选择从零搭建一套完整的部署协议,而不是简单包装 Vercel 的 API,这说明它是把这件事当战略级平台来做的,不是临时接一下。
第四层:Baku,Web 应用构建器
"Baku"是 claude.ai 上 Web 应用构建功能的内部代号。当你在网页端让 Claude 帮你构建一个 Web 应用时,它会启动一个 Baku 环境。
从二进制文件中提取的内嵌资源来看:
项目模板:
- 源码位置:/opt/baku-templates/vite-template
- 技术栈:Vite + React + TypeScript
- 通过 supervisord 自动管理开发服务器,日志输出到 /tmp/vite-dev.log
Supabase 自动配置:
六个 MCP 工具开箱即用:
- provision_database:按需创建 Supabase 项目
- execute_query:执行 SQL 查询
- apply_migration:版本化 schema 变更,自动生成类型
- list_migrations:列出已应用的迁移
- generate_types:根据数据库 schema 重新生成 TypeScript 类型
- deploy_function:部署 Supabase Edge Functions
自动写入 .env.local 的环境变量:
Stop Hooks(内嵌 shell 脚本):
Baku 环境带有一个 pre-stop hook(停止前钩子),在以下情况会阻止会话结束:
- 存在未提交或未推送的 git 变更
- Vite 开发服务器日志中出现错误
tsc --noEmit报出 TypeScript 类型错误
默认部署目标:Antspace,而不是 Vercel。Vercel 只是备选方案,Baku 的原生部署路径走的是 Anthropic 自家的平台。
内部组织结构:
- 草稿存放于
.baku/drafts/ - 探索性内容存放于
.baku/explorations/ - Git 提交使用
[email protected]作为作者 - 没有配置 git 远端(只做本地版本控制)
第 5 层:BYOC(Bring Your Own Cloud,自带云)
envtype 包中包含两套环境的实现:
anthropic:由 Anthropic 托管(基于 Firecracker MicroVM)byoc:Bring Your Own Cloud,客户自带云
BYOC 让企业客户可以把 environment-runner 跑在自己的基础设施上,而会话仍由 Anthropic 的 API 来编排。关键特性如下:
- 默认会话模式:
resume-cached(重启最快,复用已有状态) - 自定义认证:
containProvideAuthRoundTripper注入容器级凭证 - 智能 git 处理:fetch 之前先检查任务分支是否已存在于远端
- 子类型:
antspace(Anthropic 内部使用)和baku(Vite 项目构建器) - Kubernetes 集成:
podmonitor包实现了租约管理
BYOC 的 API 接口共 7 个:
战略格局
我们眼前的,是一个垂直整合的 AI 应用平台:
这已经不只是 AI 编程助手,而是一个 AI 原生 PaaS 架构——用户从萌生想法到上线生产,整个过程都发生在 Anthropic 自己的基础设施内。
这在竞争层面的影响相当大。Anthropic 由此直接对标:
- 托管与部署领域的 Vercel / Netlify
- AI 应用生成领域的 Replit / Lovable / Bolt
- 托管后端领域的 Supabase / Firebase(通过深度集成)
但它有一项结构性优势,是这些对手都不具备的:Anthropic 掌控着整条技术栈——从理解你意图的大语言模型,到构建代码的运行时,再到托管应用的平台,全在自己手里。
方法
所有发现都是在我自己的 Claude Code 会话里,用标准 Linux 工具拿到的。具体步骤如下:
第 1 步 — 识别 hypervisor。dmesg | grep FIRECK——ACPI 表里带着 OEM ID,一眼就能锁定 Firecracker。
第 2 步 — 识别 PID 1。cat /proc/1/cmdline——可以看到 /process_api 是个自定义 init,而不是 systemd。--firecracker-init 这个参数更坐实了这一点。
第 3 步 — 提取 Go 构建元数据。对 environment-runner 二进制跑 go version -m,能得到 Go 版本、模块路径(github.com/anthropics/anthropic/api-go)、(devel) 单体仓库标记,以及完整的依赖清单。
第 4 步 — 从符号还原包结构。二进制没被 strip(剥离符号),所以 objdump -t 能直接给出带完整包路径的函数名。筛出 environment-manager/internal/ 并提取唯一路径,就能还原出完整的架构树。
第 5 步 — 有针对性的字符串提取。对 Go 二进制直接 strings | grep 噪音很大(链接器会把所有字符串字面量拼在一起)。有两种更靠谱的思路:
- 已知模式搜索:扫特定字节序列(
dist.tar.gz、application/x-ndjson等) - 结构体 tag 提取:Go 会把结构体字段 tag 以字符串字面量嵌入。搜
json:"status"这类模式,能挖出通信协议的格式
第 6 步 — 用符号表反推功能。objdump -t binary | grep 'deploy\.' 能列出每个组件的方法清单——Vercel 和 Antspace 两套客户端连同完整方法签名,就是这么被发现的。
第 7 步 — 运行时观察。strace -p 1 -e trace=epoll_pwait,read,write -f 证实了 epoll 事件循环、子进程监控以及 WebSocket 通信模式。
之所以能这么做,全靠这几点:(1)二进制没被 strip——这是最关键的一条;要是 strip 过,就得上 Ghidra 了。(2)Go 自带的构建元数据等于一份免费的依赖清单。(3)Go 的字符串拼接模型保留了结构体 tag 和错误字符串。(4)VM 里有 root 权限,才能对 PID 1 跑 strace。
写在最后
把一个没做剥离、带着完整调试符号的二进制文件直接发到生产环境……这算是一种「选择」吧。它让这次分析变得毫无难度。通常需要动用 Ghidra、老老实实反编译好几个小时才能搞定的事,用 go tool objdump 加 grep 就完事了。
Antspace 显然还处在早期或内部阶段(版本号前缀是 staging-),但部署协议本身已经相当成熟,达到了生产级别。Anthropic 到底打算把它做成公开产品,还是只当 Claude 网页体验背后的内部基础设施,目前还看不出来。
能确定的是,Anthropic 的野心远不止做一家大语言模型和 AI 智能体公司。他们正在为这样一个世界打地基——应用可以被「说」出来就存在,而他们想把这套技术栈的每一层都握在自己手里。