关于 droid-control
Droid Control 是用于自动化终端、浏览器和桌面应用的技能,会根据目标和指定方法选择工作流。它将驱动说明拆分为专门的 atoms,并为交付物提供采集、合成和验证阶段。
主要功能
- 01按目标和方法路由工作流
- 02自动化终端、浏览器和桌面任务
- 03采集并合成证据材料
- 04根据承诺验证交付物
- 05协调相互隔离的采集工作者
适用场景
- 01录制终端或浏览器工作流
- 02制作修复前后的回归演示
- 03验证 QA 或演示交付物
- 04自动化原生桌面应用
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ factory-ai/ factory-plugins --skill droid-control安装后在 Claude Code 中输入/droid-control确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
atoms/browser-use/ATOM.mdatoms/capture/ATOM.mdatoms/compose/ATOM.mdatoms/desktop-use/ATOM.mdatoms/droid-cli/ATOM.mdatoms/pty-capture/ATOM.mdatoms/pty-capture/platforms/linux.mdmacos.mdwindows.mdatoms/showcase/ATOM.mdatoms/terminal-use/ATOM.mdatoms/true-input/ATOM.mdatoms/true-input/platforms/linux.mdmacos.mdwindows.mdatoms/verify/ATOM.md详细介绍
Droid Control
自动化终端、浏览器和桌面应用。优先按用户要求的方法进行路由,然后仅加载所需的机制和取证阶段。
基本规则
- 真实应用,真实环境。 非确定性行为(大模型响应、网络延迟、输出变化)是预期情况。使用
wait/wait-idle处理。绝不可用固定数据或模拟数据替代。 - 依据证据恢复。 操作失败或结果不确定后,先观察当前状态,再重试。遵守方法限制和权限边界;拒绝并不意味着可以改用其他驱动或扩大目标范围。
- Atoms 是文件,不是技能。 使用 Read 工具读取每个路由到的 atom,路径为
${DROID_PLUGIN_ROOT}/skills/droid-control/atoms/<atom>/ATOM.md(索引位于 Atoms);Skill 工具无法加载这些文件。在此插件的命令和 atoms 中以粗体显示的 atom 名称均指对应文件。Atom 会使用相对于 atom 文件的路径链接其参考资料;按需读取。Atom 文件不会展开,因此无论何处写有 DROID_PLUGIN_ROOT 变量,都将其替换为此插件根目录:${DROID_PLUGIN_ROOT}(在 shell 命令中将其加引号)。使用桌面应用不需要单独安装 cua skill。 tctl管理录制的终端会话。 它会在 PTY 周围封装asciinema rec;浏览器和桌面驱动各自管理独立的生命周期。绝不要直接调用tuistory launch。仅在终端工作流或工作线程交接时,将TCTL解析为绝对路径。- 隔离每次运行。 多个 droid 可能同时在同一台机器上录制。会话名称和输出路径共用全局命名空间(
/tmp/tctl-sessions/)。每个工作流开始时都要生成运行 ID(RUN_ID=$(date +%s)-$$或类似值),并将其用作所有会话名称的前缀,同时为所有输出文件使用独立的临时目录:
绝不要使用RUN_ID="$(date +%s)-$$" RUN_DIR="$(mktemp -d /tmp/droid-run-${RUN_ID}-XXXXXX)" # Session names: -s ${RUN_ID}-before, -s ${RUN_ID}-after # Output paths: ${RUN_DIR}/before.cast, ${RUN_DIR}/after.cast-s demo、-s before、-s after这类不带前缀的会话名称——它们会与并发运行冲突。 不同的名称和路径无法隔离共享的桌面焦点或键盘输入。可见桌面应只由一个控制器操作。
Atoms
每个 atom 都位于 ${DROID_PLUGIN_ROOT}/skills/droid-control/atoms/<atom>/ATOM.md。
| Atom | 范围 |
|---|---|
| terminal-use | 终端 TUI 驱动:默认使用 tuistory 虚拟 PTY,使用 true-input 获取真实终端证据 |
| true-input | 通过无头 Wayland 合成器或 VM 驱动真实终端模拟器 |
| browser-use | 通过 agent-browser 驱动网页和 Electron 应用 |
| desktop-use | 通过 trycua cua-driver 驱动原生 GUI 应用 |
| droid-cli | Droid CLI 目标模式、快捷方式、模式和启动辅助工具 |
| pty-capture | 从真实终端模拟器获取真实字节序列 |
| capture | 终端和浏览器会话的录制生命周期 |
| compose | 使用 fframes 渲染器组装视频:标题卡、布局、转场、特效和展示润色 |
| verify | 根据承诺验证交付内容 |
| showcase | 视觉润色:窗口边框、动画和品牌背景 |
路由
三项独立查询。完成全部三项,然后读取它们生成的 atom 并集。
1. 目标路由——你要操作什么?
| 目标 | 阅读这些原子指南 |
|---|---|
| 用户明确要求仅使用 CUA、使用原生 GUI 输入或控制桌面(包括 Electron) | desktop-use;方法限制优先于以下默认设置 |
Droid CLI(droid-dev、droid exec) | terminal-use + droid-cli |
| 其他终端 TUI | terminal-use |
| 网页或 Electron 应用 | browser-use |
| 原生桌面 GUI 应用 | desktop-use |
| 原始终端字节序列 | terminal-use + pty-capture |
terminal-use 用于选择 ${DROID_PLUGIN_ROOT}/bin/tctl 背后的终端后端:默认使用 tuistory;需要真实终端渲染或键盘编码证据时,则加载 true-input。desktop-use 包含特定合成器的操作指南;应检查实时 Cua 功能,而不要假设所有 Linux 目标都仅支持 X11,也不要放弃用户选择的方法。
2. 阶段路由——工作流需要哪些阶段?
每个工作流都会经过多个阶段。加载你会用到的各阶段原子指南。
| 阶段 | 原子指南 | 阅读时机 |
|---|---|---|
| 捕获 | capture | 录制、脚本化的多步骤证据,或演示/QA 交付物;常规桌面操作使用驱动程序的观察/验证循环 |
| 编排 | compose | 交付物是生成的成品(视频、带注释的截图、对比图像)时 |
| 验证 | verify | 正式证明、演示或 QA 交付物;即使不经过此阶段,每个操作仍需验证 |
3. 成品路由——编排是否需要润色工具?
仅在加载 compose 时相关。
| 成品需求 | 还需加载 |
|---|---|
| 展示级润色(窗口边框、品牌画框、电影感背景) | showcase |
| 特效和按键叠加层 | (由 compose 处理——它们是 Showcase props JSON 中的字段) |
工作流结构
Command (intent + commitments)
→ Target route (load driver atoms)
→ Capture (record / screenshot / byte-capture)
→ Compose (assemble deliverable, if needed)
→ Verify (check against commitments)
→ Report
命令声明要生成什么。原子指南负责说明如何生成。
默认布局
默认值:single。 一个片段展示目标/最终状态。除非交付物本质上是对比,否则选择此布局。
| 情况 | 布局 |
|---|---|
| 全新功能(没有有意义的先前状态) | single |
| Bug 修复,用单个片段证明工作流程正常 | single |
| 操作讲解 / 教程 / README 主视觉内容 | single |
| 回归证明(修复前与修复后) | side-by-side |
| 保持行为不变的重构(重点是视觉一致) | side-by-side |
| 用户明确要求对比 | side-by-side |
不要为了使用 side-by-side 而编造“修复前”的状态。如果没有真实的基准状态,请使用 single。
委派
简短的交互式桌面任务由父级负责:父级掌管观察、输入、等待用户许可和清理工作。应委派独立的捕获环境或渲染工作,而不是与另一个控制器的输入交错进行单独截图。
委派内容
| 任务 | 是否委派? | 原因 |
|---|---|---|
| 交互式共享桌面 | 否——由父级负责 | 一个控制器负责焦点、快照、输入、等待许可和清理工作 |
| 在隔离的终端/浏览器环境中捕获片段 | 是 | 工作进程负责完整的交互和录制生命周期 |
| 捕获两个片段(对比布局) | 是,但仅限环境相互独立 | 仅凭 worktree 和会话标签无法隔离桌面 |
| Showcase 渲染 | 是 | 只需要 props JSON、片段路径和输出路径。运行 render-showcase.sh(处理 .cast 转换、每次渲染的暂存、保真度配置、最长片段时长和清理) |
| 规划、交互脚本编写 | 否——由父级负责 | 需要 PR 上下文和编辑判断 |
| 布局和属性构建 | 否——由父级负责 | 需要对特效、时机和标签做出编辑决策 |
| 验证 | 否——由父级负责 | 需要提交上下文 |
| 单次 ffprobe / 文件是否存在检查 | 否——在当前任务中执行 | 太简单,不值得承担子 Agent 的额外开销 |
如何委派
**步骤 0:解析路径并生成运行 ID。**工作进程不会继承 ${DROID_PLUGIN_ROOT}。解析一次,并粘贴到所有位置:
TCTL="$(realpath "${DROID_PLUGIN_ROOT}/bin/tctl")"
RENDER="$(realpath "${DROID_PLUGIN_ROOT}/scripts/render-showcase.sh")"
RUN_ID="$(date +%s)-$$"
RUN_DIR="$(mktemp -d /tmp/droid-run-${RUN_ID}-XXXXXX)"
所有输出文件(录制文件、props、渲染后的视频)都使用 ${RUN_DIR}。所有会话名称都使用 ${RUN_ID}- 作为前缀。不要使用 -s before 这样的裸名称或 /tmp/before.cast 这样的硬编码路径。
给工作进程提供确切的命令,并使用已解析的绝对路径——不要给出抽象指令,不要使用 tuistory,也不要使用 ${DROID_PLUGIN_ROOT}。由父进程思考,工作进程执行:
Task prompt for a capture worker:
"Run these commands in order. Report the output file path and any errors.
1. /abs/path/to/bin/tctl launch "droid-dev" -s 1712345678-42-before --backend tuistory \
--repo-root /abs/path/to/baseline/worktree \
--cols 120 --rows 36 --record /tmp/droid-run-1712345678-42-xxxx/before.cast \
--env FORCE_COLOR=3 --env COLORTERM=truecolor
2. /abs/path/to/bin/tctl -s 1712345678-42-before wait ">" --timeout 15000
3. /abs/path/to/bin/tctl -s 1712345678-42-before type "hello world"
4. /abs/path/to/bin/tctl -s 1712345678-42-before press enter
5. /abs/path/to/bin/tctl -s 1712345678-42-before wait-idle
6. /abs/path/to/bin/tctl -s 1712345678-42-before close"
Task prompt for a render worker:
"Run this command. Report the output file path and any errors.
/abs/path/to/scripts/render-showcase.sh \
--props /tmp/droid-run-1712345678-42-xxxx/showcase-props.json \
--output /tmp/droid-run-1712345678-42-xxxx/demo.mp4 \
/tmp/droid-run-1712345678-42-xxxx/before.cast /tmp/droid-run-1712345678-42-xxxx/after.cast"
并行捕获模式(仅适用于对比流程)
仅当 Layout 默认表选择 side-by-side 且捕获环境彼此独立时适用。共享桌面捕获应串行执行。对于单个交互式桌面任务,应由父进程掌控。
对于前后对比演示,同时启动两个捕获工作进程:
1. Parent constructs the interaction script (identical for both branches)
2. Launch worker A: capture the baseline/reference branch with `--repo-root` set to that worktree
3. Launch worker B: capture the candidate/change branch with `--repo-root` set to that worktree
4. Wait for both to complete (TaskOutput)
5. Collect .cast paths from results
6. Continue to compose
共享工具
终端驱动程序使用统一的 tctl 包装器。浏览器使用和桌面使用有各自的 CLI(agent-browser、cua-driver),不使用 tctl。
驱动程序可以组合到同一个工作流中,例如使用 tctl 操作 CLI,并用 agent-browser 操作与之交互的 Web UI。
降级尾部复现步骤(droid TUI)
用于在 droid CLI 中复现降级的对话记录尾部的确定性步骤——工具行卡在执行状态,以及待处理的引导消息——无需等待缓慢的模型轮次。诀窍是:使用缓慢的 PreToolUse 钩子,在需要的时间内将工具固定在执行状态。
-
**临时项目。**创建一个一次性目录(绝不要使用真实仓库——钩子会在每次匹配的工具调用时触发),并在其中创建一个会休眠的项目级钩子:
SCRATCH="$(mktemp -d /tmp/degraded-tail-XXXXXX)" mkdir -p "$SCRATCH/.factory" cat > "$SCRATCH/.factory/settings.json" <<'JSON' { "hooks": { "PreToolUse": [ { "matcher": "TodoWrite", "hooks": [{ "type": "command", "command": "sleep 120" }] } ] } } JSON选择足够长的休眠时间,以便在钩子运行期间进行交互(60–180s),并选择一个提示词必定会触发的工具匹配器(任何多步骤请求都会触发
TodoWrite)。 -
启动时将
--cwd指向临时项目——--repo-root仍指向你的开发工作树,以便droid-dev来源信息仍会记录被测试的代码:$TCTL launch "droid-dev" -s ${RUN_ID}-tail --cwd "$SCRATCH" \ --repo-root /abs/path/to/dev/worktree --record ${RUN_DIR}/tail.cast -
触发钩子,然后在工具行显示正在执行时,让尾部降级:
- 在钩子运行期间中断(
press escape)——使实时工具行卡住:它在对话记录尾部中永远不会变为已完成或已取消状态。 - 在钩子运行期间发送引导消息(
type "..."+press enter)——引导消息会排在正在执行的工具之后,而不是与其交错。
- 在钩子运行期间中断(
**注意事项:**开发范围的钩子设置可能会静默禁用项目钩子。如果工具立即完成,请在会话中运行 /hooks,并检查“Hooks enabled”开关,然后再调试钩子配置本身。
前置条件
| 阶段 | 平台 | 必需 | 可选 |
|---|---|---|---|
| terminal-use (tuistory) | 所有平台 | tuistory、asciinema、agg | tmux |
| true-input | Linux/Wayland | cage、wtype、Wayland 终端、/dev/dri/* | grim、wf-recorder |
| true-input | Windows (KVM) | libvirt、qemu、带 SPICE + SSH 的 KVM VM、DROID_VM_* 环境变量 | virt-manager |
| true-input | macOS (QEMU) | qemu、socat、带 SSH 的 macOS VM、DROID_MAC_* 环境变量 | — |
| browser-use | 所有平台 | agent-browser(以及 agent-browser install) | — |
| desktop-use | 所有平台 | 目标图形会话中的 cua-driver;已批准的操作系统权限 | 已随附文档;无需单独安装 skill |
| compose | 所有平台 | ffmpeg、ffprobe、agg | — |
| showcase | 所有平台 | Rust(stable)、clang/libclang、libx264 | — |
安装命令
# tuistory driver + recording
npm install -g tuistory # virtual PTY driver
pip install asciinema # terminal recording (tctl wraps this)
cargo install --git https://github.com/asciinema/agg # .cast -> .gif converter (compose needs this)
# true-input driver (Linux/Wayland)
sudo apt-get install -y cage wtype # required: headless compositor + keystroke injection
sudo apt-get install -y grim wf-recorder # optional: screenshots + video recording
# agent-browser driver
agent-browser install # one-time: downloads bundled Chromium
# desktop-use: follow its setup instructions only if the binary
# is missing and installation is approved. No separate skill install.
# compose + showcase (video rendering)
sudo apt-get install -y ffmpeg # video processing (includes ffprobe)
sudo apt-get install -y clang libclang-dev libx264-dev # renderer build deps (macOS: xcode-select --install; brew install x264)
cargo build --release --manifest-path ${DROID_PLUGIN_ROOT}/fframes/Cargo.toml # renderer (render-showcase.sh also builds on first use)