CuaBot 多玩家计算机使用实战:用 Xpra 沙箱让多个 Agent 与人类共享同一桌面
【免费下载链接】cuaScale computer-use 2.0 with open-source drivers, cross-OS fleets, and benchmarks for training, evaluation, and data generation.项目地址: https://gitcode.com/GitHub_Trending/cua/cua
导读
本文围绕 Cua 开源仓库中的 CuaBot 模块,深入讲解"多玩家计算机使用"(Multi-Player Computer-Use)这一核心设计:每个编程 Agent(Claude Code、Gemini CLI、Codex、Aider、OpenClaw 等)在自己的 Docker 沙箱内获得独立桌面、独立彩色光标与独立窗口管理,而人类用户仍可随时在自己的宿主桌面上与这些 Agent 窗口交互。读完本文,你将掌握 CuaBot 的容器 + Xpra 流式窗口 + hairpin 回环(容器→宿主→容器)的完整架构、多会话并行启动方法、computer-use MCP 工具全集,以及 OpenClaw 的集成方式。
CuaBot 界面截图
从"独占桌面"到"多玩家桌面":为什么要重写计算机使用的交互模型
传统计算机使用(Computer-Use)Agent 有一个根深蒂固的前提:操作系统只有一个光标、一个键盘焦点、一个活动窗口——这套假设可以追溯到 Xerox PARC 时代。当 Agent 接管桌面时,你的输入与 Agent 的输入互相冲突,你只能等它跑完才能重新使用自己的电脑。
CuaBot 试图打破这个假设,其核心理念是多玩家:Agent 和人类各自拥有自己的光标、自己的键盘焦点、自己的窗口管理,全部共存于同一块屏幕上。这来自 Cua 社区的高频需求——用户希望把 cua-computer-server 直接跑在宿主机器上,让 Agent 操作真实桌面,但代价是 Agent 一运行,你的屏幕就被接管。CuaBot 给出的答案是:不把 Agent 放进你的桌面,而是为每个 Agent 建一个独立桌面,再以流式窗口的形式"借"给你看。
该方案的设计取向在仓库文档中也有体现:CuaBot 的定位是"给任何编码 Agent 提供协作式计算机使用能力"(见 libs/cuabot/README.md),它把 computer-use 视为通用 Agent 系统中的一件工具,而不是独立的屏幕接管程序。
核心架构:容器 + Xpra 流式窗口 + hairpin 回环
CuaBot 的运行链路由三层组成:
1. Docker 容器内的 X11 桌面
CuaBot 启动一个 Docker 容器(镜像trycua/cuabot:latest),内部运行完整的 X11 Linux 桌面。容器入口脚本 entrypoint.sh 会先拉起 dbus 会话,再以 seamless(无缝)模式启动 Xpra:
dbus-daemon --session --fork --address=unix:path=/tmp/dbus-session exec xpra seamless :100 --sharing=yes --no-daemon --bind-tcp=0.0.0.0:10000 --html=on --dpi=96这里:100是容器内的显示编号,--sharing=yes开启共享会话(这是多玩家得以成立的前提之一),--html=on启用 Xpra 的 HTML5 客户端端点,端口 10000 通过-p hostPort:10000映射到宿主。
2. 宿主上的 cuabotd 服务
宿主机上运行着一个名为cuabotd的 Node.js HTTP/WebSocket 服务(默认端口 7842,见 cuabotd.ts)。它负责:
- 检查 Docker 连接、拉取镜像、创建并启动容器;
- 维护宿主上的 Xpra 客户端进程,把容器内应用窗口"附着"(attach)到宿主桌面;
- 暴露一组计算机使用 API(截图、点击、输入、滚轮、按键、拖拽等),供容器内的 MCP 服务器调用;
- 维护多会话状态(每个命名会话有独立的 PID 文件、端口文件与容器名)。
创建容器时注入的关键环境变量(见ensureContainer逻辑):
| 环境变量 | 值 | 作用 |
|---|---|---|
DISPLAY | :100 | 容器内 X 显示编号 |
CUABOT_HOST | http://host.docker.internal:<serverPort> | 容器内 MCP 服务器回连宿主 cuabotd 的地址 |
CUABOT_TELEMETRY | true/false | 使用遥测开关 |
CUABOT_NAME/CUABOT_COLOR | 会话名 / 派生颜色 | 用于 overlay 光标与窗口标识 |
3. hairpin 回环:容器 → 宿主 → 容器
这是 CuaBot 最巧妙的设计。当容器内的 Agent 调用screenshot()或click(x, y)时,请求链路如下:
容器内 Agent → computer-use MCP 服务器(FastMCP,运行在容器内) → HTTP POST 到 CUABOT_HOST(即宿主上的 cuabotd) → cuabotd 驱动 Playwright 控制的 headless Chromium → Chromium 打开 Xpra HTML5 客户端页面(http://localhost:<containerPort>/?steal=no&sharing=yes) → 操作经 WebSocket 回传容器内的 X11 服务器这条"容器 → 宿主 → 容器"的路径被作者称为hairpin(发夹)。它虽然多绕了一圈,却干净利落地把 Agent 的显示服务器与宿主操作系统隔离开来——这正是多玩家能够成立的根本原因:Agent 的桌面是容器里的虚拟桌面,宿主桌面永远是人类的。
从代码可以印证这一点:cuabotd.ts 中的ensurePlaywrightConnected()会launchPlaywright()启动chromium.launch({ headless: true }),然后page.goto("http://localhost:{containerPort}/?steal=no&sharing=yes"),并轮询页面中是否出现<canvas>来判断 Xpra HTML5 是否就绪。
多玩家:并行 Agent、独立光标、独立窗口
由于每个 Agent 运行在自己的容器、自己的 Xpra 实例中,并行启动多个 Agent 是天然支持的:
cuabot claude # 第一个 Agent:Claude Code cuabot gemini -n second # 第二个 Agent:Gemini CLI,命名会话 second-n, --name <name>是 cuabot.tsx 中解析的会话名参数(parseSessionName支持--name/-n两种写法)。命名会话在源码中有完整的隔离机制:
- 容器名变为
cuabot-xpra-<session>(默认是cuabot-xpra); - 服务 PID 文件与端口文件分别变为
server.<session>.pid与server.<session>.port(存放在~/.cuabot下); - 端口自动避让:
findAvailableServerPort会从首选端口开始向上寻找可用端口,Docker 映射端口也通过findAvailablePort扫描docker ps已占用端口来避让。
每个 Agent 因此拥有:
- 自己的桌面:独立容器 + 独立 Xpra display;
- 自己的光标:颜色由会话名经 utils.ts 的
nameToColor()用哈希 + 黄金比例(0.618033988749895)生成,饱和度为 0.7、亮度 0.5,保证不同会话颜色差异明显; - 自己的窗口集合:Xpra 以 seamless 模式把每个应用窗口作为宿主上的原生窗口展示,并带彩色边框与独立托盘图标。
Overlay 光标:Agent 在"哪里操作"一目了然
为了让人类能看到 Agent 当前的操作位置,容器内运行着一个透明的浮动光标指示器 overlay-cursor.py。它是一个无边框、无任务栏、点击穿透(input_shape_combine_region设为空区域)的 GTK 弹窗,会:
- 按会话名渲染指定颜色的光标图标(
cursor.png按颜色着色); - 用带重力与风力扰动的路径算法模拟类人鼠标移动轨迹(
generate_path中gravity=9.0、wind=3.0、max_v=15.0); - 空闲 15 秒后开始 1 秒淡出;
- 通过 Unix 域套接字
/tmp/cuabot-overlay-cursor.sock接收宿主端命令(move / click / masked / hide / quit)。
宿主的 cuabotd.ts 还会做光标遮挡掩码计算:每 500ms 轮询一次宿主窗口列表(get-windows),对非 Xpra 窗口区域"添加"掩码、对 Xpra 窗口区域"挖洞"(AABB 差集运算 + 合并),当 Agent 光标落入宿主窗口之下时隐藏 overlay 光标,避免画在用户自己的窗口上面——这是多玩家体验里很关键的细节。
Xpra 客户端的附着参数
宿主端 Xpra 客户端由 cuabotd 以 detached 方式拉起(getXpraAttachArgs,见 utils.ts):
xpra attach tcp://localhost:<containerPort> \ --splash=no --notifications=no \ --border=auto,4 --sharing=yes \ --tray-icon=<icon> --window-icon=<icon> \ --session-name=cuabot (<name>)--sharing=yes是关键:它允许 Playwright 的 HTML5 客户端与宿主的原生 Xpra 客户端同时挂接同一个会话,也就是"Agent 在容器里干活、你在宿主上看/插话"并行不悖的技术基础。剪贴板与音频会随 Xpra 会话自动同步。
computer-use MCP 工具全集
容器内通过 computer-use-mcp.py(FastMCP 实现,自包含 uv 脚本)向 Agent 暴露桌面自动化工具。它通过CUABOT_HOST环境变量回连宿主 cuabotd,每个工具最终落到 cuabotd 的 HTTP handler 上:
| MCP 工具 | 参数 | 对应 cuabotd 端点 | 说明 |
|---|---|---|---|
screenshot | save_path? | POST /screenshot | 返回 JPEG;scaleScreenshot会把长边缩到 ≤1280 并记录缩放比,坐标自动换算回原屏幕坐标 |
click | x, y, button=left | POST /click | 支持 left/right/middle;同步驱动 overlay 光标移动并播放点击动画 |
double_click | x, y | POST /doubleClick | 双击 |
type_text | text, delay=50 | POST /type | 按键间隔默认 50ms |
mouse_move | x, y | POST /mouseMove | 移动光标 |
mouse_down/mouse_up | x, y, button=left | POST /mouseDown/mouseUp | 按下/释放鼠标键 |
scroll | x, y, delta_x, delta_y | POST /scroll | 滚轮(deltaY 负值向上) |
key_down/key_up/key_press | key | POST /keyDown/keyUp/keyPress | 组合键与快捷键(如 Enter、Tab、Shift、Control) |
drag | from_x, from_y, to_x, to_y | POST /drag | 拖拽,中间 10 步插值移动 |
MCP 客户端(CLI 侧)对应的完整命令见 cuabot.tsx 的帮助文本:cuabot --screenshot [path]、--click <x> <y> [button]、--doubleclick、--move、--mousedown、--mouseup、--drag <x1> <y1> <x2> <y2>、--scroll <x> <y> <dx> <dy>、--type <text>、--key、--keydown、--keyup。此外还有服务管理命令--serve [port]、--stop、--status、--reset [all|sandbox|settings],以及任意命令执行cuabot --bash <command>和交互式 WebSocket shell(ws://localhost:<port>/?command=...,基于 node-pty 的docker exec -itPTY 会话,支持 stdin 与窗口 resize)。
沙箱内的环境
Agent 一进沙箱就拥有一套可用的开发环境。容器内的系统提示词见 SYSTEM.md:
- 操作系统:Ubuntu 22.04,拥有 sudo 权限;
- 运行时:Node.js 22.x、Python 3.10、pip3、uv(Python 包管理器,可运行带内联依赖的自包含脚本);
- 预装工具:chromium、agent-browser(浏览器自动化 CLI)、agent-device(adb / Android 自动化)、feh、claude-code、x11-apps;
- 预装 Python 库:matplotlib、numpy、pandas、seaborn、plotly。
容器入口还会在后台通过npx skills安装callstackincubator/agent-device与vercel-labs/agent-browser技能(写入挂载到宿主的~/.claude目录,见 entrypoint.sh),使 Agent 具备浏览器与 Android 设备自动化能力。
支持的 Agent 与 OpenClaw 集成
CuaBot 的 Agent 注册表见 settings.ts,开箱支持六种编码 Agent:
| Agent ID | 名称 | 启动命令 |
|---|---|---|
claude | Claude Code | claude --mcp-config /home/user/.mcp.json --append-system-prompt-file /home/user/CLAUDE.md |
gemini | Gemini CLI | npx @google/gemini-cli |
codex | OpenAI Codex | codex |
aider | Aider | aider |
openclaw | OpenClaw | openclaw |
vibe | Vibe | vibe |
注意 Claude 的特殊处理:runAgent会为它显式传入--mcp-config /home/user/.mcp.json(即预配置好的 computer-use MCP)并追加系统提示词文件,其他 Agent 则使用注册表中的命令直接启动。cuabot <任意命令>还能在沙箱中运行任意 shell 命令。
OpenClaw:开箱即用的配合
CuaBot 与 OpenClaw 的集成分两种形态:
- 沙箱内运行:
cuabot openclaw在 CuaBot 沙箱内启动 OpenClaw,computer-use MCP 已预先配置好。OpenClaw 拥有完整桌面环境,窗口流式传输到宿主,你的机器不受影响,无需额外配置; - 无沙箱注入:
cuabot --add-mcp openclaw可将 CuaBot 的 MCP 服务器注入到已有的 OpenClaw 安装中,为未沙箱化的 OpenClaw 补上计算机使用能力。
由于每个 Agent 独立成沙箱、各有光标,你完全可以让一个 OpenClaw 实例处理任务 A、一个 Claude Code 实例处理任务 B——它们在各自的桌面里并行工作,互不干扰。
快速开始:一条命令跑起来
npx cuabot首次运行会进入引导流程(onboarding.tsx,交互式 TUI):检查 Docker 连接、Xpra 客户端、Playwright Chromium 与 Docker 镜像缓存,拉取容器镜像(约 2GB),把cuabot别名写入 shell 配置文件(macOS 写.bash_profile/.zshrc,Linux 写.bashrc,Windows 写 PowerShell profile 并生成cuabot.cmd),然后选择默认 Agent。之后直接输入cuabot即可启动默认 Agent。
运行前提:
- Node.js 18+;
- Docker Desktop(macOS / Windows)或 Docker 守护进程(Linux);
- Xpra 客户端:macOS 需安装到
/Applications/Xpra.app(注意检查com.apple.quarantine隔离属性,被隔离时需sudo xattr -c /Applications/Xpra.app),Windows 在C:\Program Files\Xpra\xpra_cmd.exe,Linux 通过apt install xpra或brew install xpra,见 utils.ts 的XPRA_PATHS与依赖检查逻辑。
依赖检查不通过时会给出明确指引,例如:
- Docker 未安装 / 未运行 → 提示安装并启动 Docker Desktop;
- Xpra 缺失 → 按平台给出安装命令;
- Playwright Chromium 缺失 →
npx playwright install chromium; - 镜像未拉取 →
docker pull trycua/cuabot:latest。
服务日志写入~/.cuabot/server.log,如需彻底重置可执行cuabot --reset all(移除容器、镜像与~/.cuabot配置)。
多玩家进阶:把多个 Agent 与你自己编排到同一屏
综合以上机制,一个典型的多玩家工作流是:
# 终端 1:默认会话跑 Claude Code cuabot claude # 终端 2:命名会话跑 Gemini CLI(独立容器、独立光标颜色) cuabot gemini -n second # 终端 3:随时查看两个会话的服务状态 cuabot --status cuabot --status -n second运行后,你的宿主桌面上会看到两组带彩色边框的原生窗口:一组属于 Claude(默认颜色),一组属于 Gemini(second会话派生颜色)。你可以直接点击任意一组的窗口输入内容、切回自己的工作窗口继续干活,Agent 不会因为你的操作而中断。若启用了遥测(首次引导时可配置),cuabotd 会记录 CLI 调用、MCP 工具调用等事件,并在停止时刷新数据。
未来方向
按照发布文档的规划,CuaBot 后续将推进:
- macOS VM 支持(借助 Lume):为需要 macOS 原生应用的 Agent 提供沙箱化 macOS 环境;
- 跨沙箱的多 Agent 编排:在多个沙箱之上统一调度任务;
- 沙箱上的 RL 训练环境:以沙箱为底座构建 gym 风格的评估循环,用于训练计算机使用模型。
这些方向与 Cua 生态中计算机使用基础设施(如 Lume、cua-sandbox、cua-bench 等模块)一脉相承,读者可在仓库中继续深入。
小结
CuaBot 用"每人一个桌面"取代"大家抢一个桌面":Docker 容器隔离出独立 X11 桌面,Xpra seamless 会话把应用窗口流式呈现到宿主,hairpin 回环让 Agent 的输入经由宿主 Playwright 回流容器,而 overlay 光标与窗口掩码让"谁在操作哪里"一目了然。无论你用的是 Claude Code、Gemini CLI、Codex、Aider 还是 OpenClaw,只需npx cuabot,即可在保住自己机器使用权的同时,让任意多个 Agent 与你共享同一块屏幕并行工作。
【免费下载链接】cuaScale computer-use 2.0 with open-source drivers, cross-OS fleets, and benchmarks for training, evaluation, and data generation.项目地址: https://gitcode.com/GitHub_Trending/cua/cua
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考