mcpField
S
serve-sim

serve-sim

github.com/evanbacon测试与质量2.9k1.1k 次安装5 天前更新
代码仓库

关于 serve-sim

serve-sim 技能指导 Agent 使用 CLI 操控 Apple Simulator,适合 iOS、iPad 和 Apple Watch 应用测试。内容涵盖交互、画面串流、摄像头输入及辅助功能检查等操作。

主要功能

  1. 01点击、滑动及多步手势
  2. 02浏览器预览模拟器画面
  3. 03注入合成摄像头画面
  4. 04管理应用隐私权限
  5. 05读取辅助功能树
  6. 06旋转设备及发送硬件按钮

适用场景

  1. 01自动化测试模拟器中的应用流程
  2. 02通过浏览器远程查看模拟器
  3. 03测试应用摄像头输入与权限
  4. 04按辅助功能元素定位界面控件

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/evanbacon/serve-sim --skill serve-sim

安装后在 Claude Code 中输入/serve-sim确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

README.md
evals/
evals.json
references/
buttons-rotation.md
ca-debug.md
camera.md
endpoints.md
gestures.md
permissions.md
workflows.md
scripts/
check-prereqs.sh
ensure-running.sh

详细介绍

serve-sim

使用 serve-sim CLI,让 Agent 操控 Apple 模拟器(iOS、iPad、Apple Watch)。serve-sim 会启动一个 Swift 辅助程序,通过 simctl io 捕获模拟器帧缓冲区,将其作为 MJPEG 流和二进制 WebSocket 输入通道公开,并在其上提供 React 预览界面。本技能将向 Agent 介绍完整的 CLI 命令、手势 JSON 格式、注意事项和推荐工作流。

适用场景

  • 用户希望 Agent 对正在运行的 Apple 模拟器轻点、滑动、拖动、捏合或发送硬件按钮操作。
  • 用户希望将模拟器画面流式传输到浏览器(本地、局域网或通过隧道),以便查看或远程控制。
  • 用户希望向模拟器上的特定应用注入合成摄像头画面(文件、网络摄像头或动画占位画面)。
  • 用户希望切换 CoreAnimation 调试叠加层(屏幕外渲染、混合图层、慢速动画)以进行性能调优。
  • 用户希望以编程方式模拟内存警告或旋转设备。
  • 用户希望读取模拟器的辅助功能树,以便查找 UI 元素,无需依赖像素位置。
  • 用户希望授予、撤销或重置应用的隐私权限——摄像头、照片、位置、联系人或推送通知。

不适用场景

  • Android 模拟器 → 使用 adb shell 工具。
  • 构建或安装 iOS 应用 → 使用 xcodebuild 或 xcrun simctl install。
  • React Native 应用内运行时调试(Redux 状态、网络检查、组件树)→ 使用 rn-debugger 工具。
  • 真实 iOS 硬件设备 → 使用 xcrun devicectl 或 Xcode。

前置条件

执行任何其他操作之前,请确认主机满足以下条件。如果缺少任何一项,请明确告知用户需要安装什么——不要继续操作。

要求检查命令原因
macOS 主机uname -s 返回 Darwinserve-sim 仅能在 macOS 上运行
Xcode CLI 工具xcrun --version 退出码为 0simctl 是底层模拟器驱动程序
Node.js ≥18node --version ≥18serve-sim 是通过 npx 运行的 npm 包
macOS 14+(可选)sw_vers -productVersion ≥14仅 camera 子命令需要

提供了一个打包好的辅助脚本:scripts/check-prereqs.sh。运行该脚本;如果退出码非零,请将提示信息告知用户。

大多数子命令都要求模拟器已启动。使用 xcrun simctl list devices booted 检查。如果没有已启动的模拟器,请告知用户打开 Xcode → Simulator,或运行 xcrun simctl boot <UDID>。

工作原理

┌──────────────┐  simctl io  ┌─────────────────┐  MJPEG / WS  ┌─────────┐
│ iOS Simulator│ ──────────► │ serve-sim-bin   │ ───────────► │ Browser │
└──────────────┘   (Swift)   │ (per-device)    │              └─────────┘
                             └─────────────────┘
                                     ▲
                              state file in
                            $TMPDIR/serve-sim/
                                     ▲
                            ┌──────────────────┐
                            │ serve-sim CLI    │
                            └──────────────────┘

Agent 必须遵守的关键规则:

  • 所有坐标均为 0..1 归一化坐标,显示屏左上角为 (0, 0),右下角为 (1, 1)。切勿传入像素坐标。
  • 每台设备对应一个辅助程序。支持多个已启动的模拟器:可传入多个设备名称,或连接到所有设备。
  • 状态保存在 $TMPDIR/serve-sim/server-{udid}.json 中。使用 serve-sim --list 查询;除非清楚自己在做什么,否则不要直接读取 JSON 文件。
  • 辅助程序会记住通过 rotate 设置的方向,并在客户端旋转之后的手势。旋转后发送原始坐标的 Agent 无需手动校正。

常见操作

目标命令说明
启动预览服务器npx serve-sim [device]默认预览地址为 http://localhost:3200,流地址为 :3100。以前台进程运行。
无头模式/以守护进程启动npx serve-sim --detach [device]返回包含 pid、port、url 的 JSON。可用于 Agent 循环。
在宿主的预览中显示流npx serve-sim --detach -q → 将 url 交给宿主的预览工具参见“在 Agent 的预览中显示流”一节。
列出正在运行的流npx serve-sim --list添加 -q 可仅输出 JSON。
停止所有辅助进程npx serve-sim --kill传入 [device] 可停止指定设备。
单次轻点npx serve-sim tap <x> <y><x> <y> 的取值范围为 0..1。普通轻点请使用此命令,而不是 gesture。 参见下文的“关键注意事项”。
多步手势npx serve-sim gesture '<json>'参见 references/gestures.md。
硬件按钮npx serve-sim button <name>可用名称:home、swipe_home、app_switcher、lock、siri、side_button。参见 references/buttons-rotation.md。
旋转设备npx serve-sim rotate <orientation>portrait、portrait_upside_down、landscape_left、landscape_right。
模拟内存警告npx serve-sim memory-warning等同于“调试”→“模拟内存警告”。
CoreAnimation 调试npx serve-sim ca-debug <option> <on|off>选项:blended、copies、misaligned、offscreen、slow-animations。参见 references/ca-debug.md。
注入摄像头画面npx serve-sim camera <bundle-id> [--file <path>|--webcam [name]](重新)启动应用并附加摄像头 dylib。仅适用于 macOS 14 及更高版本。参见 references/camera.md。
热切换摄像头源npx serve-sim camera switch <placeholder|webcam|file> [arg]无需重新启动应用。
管理应用权限npx serve-sim permissions <grant|revoke|reset|list> <permission> <bundle-id>摄像头、照片、位置、推送通知、联系人等。参见 references/permissions.md。
读取无障碍树curl http://localhost:3100/ax返回 axe 风格的 JSON。所有端点见 references/endpoints.md。

当有多个设备处于启动状态时,大多数子命令都接受 -d <udid|name>,用于指定目标设备。

关键注意事项:轻点优先使用 tap,而不是 gesture

每次调用 serve-sim gesture 都会建立独立的 WebSocket。如果连续调用两次 gesture——一次使用 {"type":"begin",...},另一次使用 {"type":"end",...}——由于两次调用之间存在一定延迟,模拟器会将触摸识别为长按,而不是轻点。这是协议的一项刻意限制,并非需要设法绕过的错误。

规则:对于任何单次轻点,请使用 serve-sim tap <x> <y>。只有在拖动、滑动或多步交互(必须让 begin → move × N → end 共用同一套 socket)时,才使用 gesture。

指定目标设备

启动多个模拟器时,每个子命令都接受 -d <udid|name>。名称匹配不区分大小写,并与 xcrun simctl list devices booted 返回的设备名称进行比对。示例:

npx serve-sim tap 0.5 0.5 -d "iPhone 16 Pro"
npx serve-sim button home -d ABC12345-...
npx serve-sim --list                                # show all running streams

如果用户只启动了一个模拟器,可以完全省略 -d。此技能应优先自动检测,而不是硬编码设备名称。

输出模式

默认情况下,serve-sim 会向 stdout 输出人类可读的状态信息。对于 Agent 循环,建议使用 JSON 输出:

npx serve-sim --list -q          # JSON array of running streams
npx serve-sim --detach -q        # JSON with pid/port/url after spawn
npx serve-sim camera status -q   # JSON with {alive, source, mirror, ...}

以编程方式解析 -q 输出。切勿解析不带 -q 的人类可读输出,因为它可能随版本变化。

在 Agent 的预览中显示串流

当用户要求“在这里查看模拟器”“在预览中查看”“在此工具中打开”或类似操作时,目标是将模拟器串流到用户正在聊天的同一界面中。serve-sim 会返回一个常规 HTTP URL,Agent 需要显示该 URL;如果宿主提供预览工具,则将 URL 交给该工具。

步骤:

  1. 启动 serve-sim 并获取 URL:

    npx serve-sim --detach -q
    

    这会返回类似 {"pid":..., "port":3200, "url":"http://localhost:3200", "streamUrl":"http://localhost:3100", ...} 的 JSON。url 字段是面向用户的预览 UI;streamUrl 是原始 MJPEG 端点。

  2. 始终在回复中直接显示 URL,以便用户可以在任何浏览器中手动打开。

  3. 检查宿主的预览工具,如果存在,则将 URL 交给该工具。工具集中可能出现的名称包括:

    • preview_start(Claude Code)——使用 { url: "<url>" } 调用。
    • mcp__Claude_Preview__preview_start(某些 MCP 配置)。
    • browser_open、open_url 或类似的 URL 打开工具——传入 URL。
    • Cursor / Codex CLI / 其他工具可能不会向 Agent 提供预览工具。这种情况下,只需打印 URL 并告知用户如何打开它(使用浏览器、IDE 内置浏览器窗格等)。
  4. 不要假设一定存在某种特定预览工具。 检查当前会话中可用的工具。如果有符合上述描述的工具,请使用它。如果没有,则回退到步骤 2(醒目地打印 URL)。

串流会一直运行,直到执行 npx serve-sim --kill。多个客户端(宿主的预览、用户的浏览器和隧道)可以同时读取同一个 URL。

完整操作流程请参阅 references/workflows.md 中的工作流“在宿主的预览中显示模拟器串流”。

工作流

如需完整的端到端操作流程(UI 自动化、摄像头测试、基于无障碍功能的点击、深层链接流程、预览交接),请参阅 references/workflows.md。该参考文档涵盖了 serve-sim 自带 AGENTS.md 中记录的模式。

清理

完成后始终停止辅助进程,除非用户明确要求继续运行:

npx serve-sim --kill            # stop all
npx serve-sim --kill "iPhone 16 Pro"  # stop one

残留的辅助进程会占用端口 3200/3100,妨碍重新启动。

反模式

  • 不要传入像素坐标。 所有坐标都已归一化到 0..1。如果用户提供像素值,请用 GET /config 报告的屏幕尺寸进行换算。
  • 不要将 gesture 用于普通点击。 请使用 tap。参阅上文的“关键注意事项”。
  • 不要假设 npx serve-sim 已在运行。 使用 --list 或检查 $TMPDIR/serve-sim/server-{udid}.json 进行确认。如果文件不存在,请显式启动。
  • 首次在会话中调用时,不要跳过先决条件检查。 macOS 版本不匹配、缺少 Xcode CLI 工具或 Node 版本低于 18,都会导致后续出现难以理解的错误。
  • 不要臆造按钮名称。 只有以下六个有效:home、swipe_home、app_switcher、lock、siri、side_button。权威列表请参阅 references/buttons-rotation.md。
  • 不要解析非静默的人类可读输出。 使用 -q 获取 JSON。
  • 不要让摄像头辅助进程在无关任务期间继续运行。 完成后使用 npx serve-sim camera --stop-webcam 将其停止。
  • 如果无障碍查询没有匹配结果,不要猜测坐标。 如果你获取了 AX 树(例如通过 GET /ax)来查找目标元素,但查询没有返回结果,请明确报告失败——点击猜测的位置通常远不如向用户报告“未找到目标”。请参阅 references/workflows.md 中工作流 1 的防护模式。

参考索引

评论

支持 Markdown