simdeck

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

SimDeck Agent Guide

SimDeck Agent 使用指南

SimDeck automates iOS Simulators and Android emulators. Use the CLI for automation and the browser UI for live human visibility. iOS works with NativeScript, UIKit, SwiftUI, React Native, Expo, and Flutter apps; Android works through ADB, emulator lifecycle, screenshots, logs, and UIAutomator hierarchy dumps.
SimDeck uses one long-running local service. Run
simdeck
first; it starts or reuses the background service and prints the browser URL plus pairing code. Pass
--open
only when you want SimDeck to open the default browser itself. Pass
-p <port>
or
--port <port>
when the service should use a non-default port. Pass
-a
or
--autostart
when the service should also be registered as a macOS LaunchAgent.
Example response from
simdeck
:
json
{
  "ok": true,
  "pairingCode": "401974",
  "pid": 91285,
  "projectRoot": "-",
  "started": true,
  "url": "http://127.0.0.1:4310"
}
bash
simdeck
simdeck --open
simdeck -p 4311
simdeck -a
simdeck pair # prints LAN/Tailscale pairing URLs, code, and iOS QR
simdeck service stop
simdeck service kill # stops all SimDeck services from any binary
simdeck service restart
Usually
http://127.0.0.1:4310
. Pass a simulator name or UDID to
simdeck
when the browser URL should open with
?device=<UDID>
. Use
simdeck -p 4311
when the default port is not the right fit. Use
simdeck pair
when a native iOS client needs to pair. It starts or refreshes the LaunchAgent-backed service, detects LAN and Tailscale IPv4 addresses, and prints a QR with a
simdeck://pair
URL. Normal service restarts preserve the token and pairing code; use
simdeck service reset
only when you need to rotate them. Use
simdeck service kill
or
simdeck service killall
when you need a clean slate across installed and source-checkout binaries.
Always first run
simdeck
and open the reported URL in the in-app browser using the Browser tool if available.
If Browser Use is not available, only then use
simdeck --open
; it opens the default browser and may take focus away from the app.
SimDeck 可自动化 iOS Simulators 和 Android emulators 操作。使用 CLI 实现自动化,通过浏览器 UI 实现实时可视化。iOS 端支持 NativeScript、UIKit、SwiftUI、React Native、Expo 和 Flutter 应用;Android 端通过 ADB、模拟器生命周期管理、截图、日志以及 UIAutomator 层级导出实现功能。
SimDeck 依赖一个长期运行的本地服务。首先运行
simdeck
命令;它会启动或复用后台服务,并打印浏览器 URL 及配对码。仅当需要 SimDeck 自动打开默认浏览器时,添加
--open
参数。当服务需要使用非默认端口时,添加
-p <port>
--port <port>
参数。若要将服务注册为 macOS LaunchAgent,添加
-a
--autostart
参数。
simdeck
命令的示例响应:
json
{
  "ok": true,
  "pairingCode": "401974",
  "pid": 91285,
  "projectRoot": "-",
  "started": true,
  "url": "http://127.0.0.1:4310"
}
bash
simdeck
simdeck --open
simdeck -p 4311
simdeck -a
simdeck pair # 打印 LAN/Tailscale 配对 URL、代码及 iOS 二维码
simdeck service stop
simdeck service kill # 终止所有来自任意二进制文件的 SimDeck 服务
simdeck service restart
默认地址通常为
http://127.0.0.1:4310
。若希望浏览器 URL 以
?device=<UDID>
形式打开,可在
simdeck
命令后传入模拟器名称或 UDID。当默认端口不合适时,使用
simdeck -p 4311
。 当原生 iOS 客户端需要配对时,使用
simdeck pair
命令。它会启动或刷新基于 LaunchAgent 的服务,检测 LAN 和 Tailscale IPv4 地址,并打印包含
simdeck://pair
URL 的二维码。常规服务重启会保留令牌和配对码;仅当需要轮换它们时,使用
simdeck service reset
。 当需要彻底清理已安装和源码检出的二进制文件相关服务时,使用
simdeck service kill
simdeck service killall
请始终先运行
simdeck
命令,若应用内浏览器可用,则使用浏览器工具打开返回的 URL。
若无法使用应用内浏览器,再使用
simdeck --open
;它会打开默认浏览器,可能会抢占应用的焦点。

Device and app

设备与应用

Start by choosing a project default device.
simdeck use <UDID>
stores the selection for the current workspace/CWD so later commands can omit the UDID. Explicit UDIDs,
--device
,
SIMDECK_DEVICE
, and
SIMDECK_UDID
still work for one-off overrides. Prefer short forms in agent loops, such as
simdeck tap "Continue"
and
simdeck snapshot --format agent --max-depth 2 -i
.
bash
simdeck list
simdeck list --format json
simdeck use <UDID>
simdeck boot <UDID>
simdeck shutdown
simdeck erase
simdeck core-simulator restart
simdeck install /path/to/App.app
simdeck install /path/to/App.ipa
simdeck install android:<AVD_NAME> /path/to/app.apk
simdeck launch com.example.App
simdeck uninstall com.example.App
simdeck open-url myapp://route
simdeck open-url https://example.com
simdeck toggle-appearance
simdeck list
defaults to compact JSON for token-efficient agent selection. Use
simdeck list --format json
only when you need full paths and display metadata.
Build apps with project tooling.
Android devices use IDs like
android:Pixel_8_API_36
.
simdeck list
discovers AVDs from the Android SDK.
首先选择项目默认设备。
simdeck use <UDID>
命令会将选择保存到当前工作区/CWD,后续命令可省略 UDID。显式传入 UDID、
--device
参数、
SIMDECK_DEVICE
SIMDECK_UDID
环境变量仍可用于单次覆盖设置。在 Agent 循环中优先使用简短形式,例如
simdeck tap "Continue"
simdeck snapshot --format agent --max-depth 2 -i
bash
simdeck list
simdeck list --format json
simdeck use <UDID>
simdeck boot <UDID>
simdeck shutdown
simdeck erase
simdeck core-simulator restart
simdeck install /path/to/App.app
simdeck install /path/to/App.ipa
simdeck install android:<AVD_NAME> /path/to/app.apk
simdeck launch com.example.App
simdeck uninstall com.example.App
simdeck open-url myapp://route
simdeck open-url https://example.com
simdeck toggle-appearance
simdeck list
默认输出紧凑 JSON 格式,便于 Agent 高效选择设备。仅当需要完整路径和显示元数据时,使用
simdeck list --format json
使用项目工具构建应用。
Android 设备使用类似
android:Pixel_8_API_36
的 ID。
simdeck list
会从 Android SDK 中发现 AVD。

Fast agent inspection

快速 Agent 检查

Use targeted checks for test loops.
describe
is a diagnostic snapshot of the whole hierarchy. For verification, prefer the service APIs exposed by
simdeck/test
:
action
,
query
,
waitFor
,
assert
, selector
tap
, and
batch
.
bash
simdeck describe
simdeck describe --format agent --max-depth 4
simdeck describe --format agent --max-depth 4 --interactive
simdeck snapshot --format agent --max-depth 4 -i
simdeck describe --format compact-json
simdeck describe --point 120,240
simdeck describe --source auto
simdeck describe --source nativescript|react-native|flutter|swiftui|uikit
simdeck describe --source native-ax
simdeck describe --source android-uiautomator
simdeck describe --direct
simdeck wait-for --label "Welcome" --timeout-ms 5000
simdeck wait --label "Welcome" --timeout-ms 5000
simdeck assert --id login.button --source auto --max-depth 8
The default source is
native-ax
, which is the fastest and most universal path for agents. Use
--source auto
when you want richer NativeScript, React Native, Flutter, SwiftUI, or UIKit inspector data before native accessibility fallback. Use
--direct
or
--source native-ax
for the private CoreSimulator accessibility bridge. Use
--source android-uiautomator
for Android emulator UIAutomator hierarchies. For Android IDs,
describe
uses
uiautomator dump
; use
--format agent
or
--format compact-json
the same way as iOS. Use
--interactive
or
-i
when an agent only needs controls and actionable framework nodes; SimDeck keeps ancestor context so the output is still navigable. Agent output labels nodes with refs such as
@e3
; reuse them with
simdeck press @e3
.
snapshot
,
press
, and
wait
are aliases for
describe
,
tap
, and
wait-for
.
Prefer selectors, coordinates only when needed. Selector taps go through the service and wait for the element server-side. Use
--expect-id
,
--expect-label
, or another
--expect-*
selector when the tap should also wait for the next screen before returning.
bash
simdeck tap --id LoginButton --wait-timeout-ms 5000
simdeck tap --id com.apple.settings.screenTime --expect-id BackButton
simdeck tap --label "Continue" --element-type Button
simdeck tap 120 240
simdeck tap "Continue"
simdeck press @e3
For persistent app integration tests, use
simdeck/test
instead of shelling out repeatedly:
ts
import { connect } from "simdeck/test";

const udid = "your-device-udid";
const simdeck = await connect({ udid });

try {
  await simdeck.launch("com.example.App");
  await simdeck.waitFor({ id: "login.button" }, { maxDepth: 8 });
  await simdeck.tap(0.5, 0.5);
  await simdeck.assert({ label: "Welcome" }, { maxDepth: 8 });
  const matches = await simdeck.query({ id: "account.name" });
  console.log(matches);
} finally {
  simdeck.close();
}
simdeck/test
state-query helpers default to
source: "native-ax"
for fast agent control. Pass
source: "auto"
only when you intentionally want richer framework inspector trees before native accessibility fallback.
Use
tree()
/
describe
only when a test needs to print the whole UI for debugging. In a normal agent loop, do not fetch the full tree after every action; verify the specific element or text that proves the step succeeded.
在测试循环中使用针对性检查。
describe
命令会生成整个层级的诊断快照。如需验证,优先使用
simdeck/test
暴露的服务 API:
action
query
waitFor
assert
、选择器
tap
batch
bash
simdeck describe
simdeck describe --format agent --max-depth 4
simdeck describe --format agent --max-depth 4 --interactive
simdeck snapshot --format agent --max-depth 4 -i
simdeck describe --format compact-json
simdeck describe --point 120,240
simdeck describe --source auto
simdeck describe --source nativescript|react-native|flutter|swiftui|uikit
simdeck describe --source native-ax
simdeck describe --source android-uiautomator
simdeck describe --direct
simdeck wait-for --label "Welcome" --timeout-ms 5000
simdeck wait --label "Welcome" --timeout-ms 5000
simdeck assert --id login.button --source auto --max-depth 8
默认数据源为
native-ax
,这是 Agent 最快且最通用的路径。当需要在原生无障碍回退前获取更丰富的 NativeScript、React Native、Flutter、SwiftUI 或 UIKit 检查器数据时,使用
--source auto
。如需使用私有 CoreSimulator 无障碍桥接,使用
--direct
--source native-ax
。对于 Android 模拟器 UIAutomator 层级,使用
--source android-uiautomator
。 针对 Android ID,
describe
命令使用
uiautomator dump
;与 iOS 一样,可使用
--format agent
--format compact-json
格式。 当 Agent 仅需要控件和可操作框架节点时,使用
--interactive
-i
参数;SimDeck 会保留祖先上下文,因此输出仍可导航。Agent 输出会用
@e3
这类引用标记节点;可通过
simdeck press @e3
复用这些引用。
snapshot
press
wait
分别是
describe
tap
wait-for
的别名。
优先使用选择器,仅在必要时使用坐标。选择器点击会通过服务执行,并在服务器端等待元素。当点击后需要等待下一个屏幕再返回时,使用
--expect-id
--expect-label
或其他
--expect-*
选择器。
bash
simdeck tap --id LoginButton --wait-timeout-ms 5000
simdeck tap --id com.apple.settings.screenTime --expect-id BackButton
simdeck tap --label "Continue" --element-type Button
simdeck tap 120 240
simdeck tap "Continue"
simdeck press @e3
对于持久化应用集成测试,使用
simdeck/test
而非反复调用 shell 命令:
ts
import { connect } from "simdeck/test";

const udid = "your-device-udid";
const simdeck = await connect({ udid });

try {
  await simdeck.launch("com.example.App");
  await simdeck.waitFor({ id: "login.button" }, { maxDepth: 8 });
  await simdeck.tap(0.5, 0.5);
  await simdeck.assert({ label: "Welcome" }, { maxDepth: 8 });
  const matches = await simdeck.query({ id: "account.name" });
  console.log(matches);
} finally {
  simdeck.close();
}
simdeck/test
的状态查询助手默认使用
source: "native-ax"
以实现快速 Agent 控制。仅当有意在原生无障碍回退前获取更丰富的框架检查器树时,传入
source: "auto"
仅当测试需要打印整个 UI 用于调试时,使用
tree()
/
describe
。在常规 Agent 循环中,不要在每次操作后获取完整树结构;只需验证能证明步骤成功的特定元素或文本即可。

Interact

交互操作

bash
simdeck tap 120 240
simdeck touch 0.5 0.5 --phase began --normalized
simdeck touch 0.5 0.5 --phase ended --normalized
simdeck touch 120 240 --down --up --delay-ms 800
simdeck swipe 200 700 200 200
simdeck swipe 200 700 200 200 --duration-ms 500 --pre-delay-ms 100 --post-delay-ms 250
simdeck gesture scroll-up
simdeck gesture scroll-down
simdeck gesture swipe-from-left-edge
simdeck gesture swipe-from-right-edge
simdeck pinch --start-distance 160 --end-distance 80
simdeck pinch --start-distance 0.20 --end-distance 0.35 --normalized --duration-ms 250 --steps 8
simdeck rotate-gesture --radius 100 --degrees 90
simdeck rotate-gesture --radius 0.12 --degrees 45 --normalized --duration-ms 250 --steps 8
simdeck type 'hello'
simdeck type --stdin
simdeck type --file message.txt
simdeck key enter
simdeck key 42 --duration-ms 500
simdeck key-sequence --keycodes h,e,l,l,o --delay-ms 75
simdeck key-combo --modifiers cmd,shift --key z
simdeck dismiss-keyboard
simdeck button software-keyboard
simdeck button home
simdeck back
simdeck button lock --duration-ms 1000
simdeck button side-button
simdeck button volume-up
simdeck button volume-down
simdeck button action --duration-ms 1000
simdeck button mute
simdeck button digital-crown
simdeck crown --delta 50
simdeck button left-side-button
simdeck button siri
simdeck button apple-pay
simdeck home
simdeck app-switcher
simdeck rotate-left
simdeck rotate-right
simdeck pasteboard set 'text'
simdeck pasteboard get
Use
--stdin
or
--file
for text with quotes, newlines, shell variables, or shell-sensitive characters.
bash
simdeck tap 120 240
simdeck touch 0.5 0.5 --phase began --normalized
simdeck touch 0.5 0.5 --phase ended --normalized
simdeck touch 120 240 --down --up --delay-ms 800
simdeck swipe 200 700 200 200
simdeck swipe 200 700 200 200 --duration-ms 500 --pre-delay-ms 100 --post-delay-ms 250
simdeck gesture scroll-up
simdeck gesture scroll-down
simdeck gesture swipe-from-left-edge
simdeck gesture swipe-from-right-edge
simdeck pinch --start-distance 160 --end-distance 80
simdeck pinch --start-distance 0.20 --end-distance 0.35 --normalized --duration-ms 250 --steps 8
simdeck rotate-gesture --radius 100 --degrees 90
simdeck rotate-gesture --radius 0.12 --degrees 45 --normalized --duration-ms 250 --steps 8
simdeck type 'hello'
simdeck type --stdin
simdeck type --file message.txt
simdeck key enter
simdeck key 42 --duration-ms 500
simdeck key-sequence --keycodes h,e,l,l,o --delay-ms 75
simdeck key-combo --modifiers cmd,shift --key z
simdeck dismiss-keyboard
simdeck button software-keyboard
simdeck button home
simdeck back
simdeck button lock --duration-ms 1000
simdeck button side-button
simdeck button volume-up
simdeck button volume-down
simdeck button action --duration-ms 1000
simdeck button mute
simdeck button digital-crown
simdeck crown --delta 50
simdeck button left-side-button
simdeck button siri
simdeck button apple-pay
simdeck home
simdeck app-switcher
simdeck rotate-left
simdeck rotate-right
simdeck pasteboard set 'text'
simdeck pasteboard get
当文本包含引号、换行符、shell 变量或 shell 敏感字符时,使用
--stdin
--file
参数。

Timing and batch

时序与批量操作

bash
simdeck tap --label "Continue" --wait-timeout-ms 5000
simdeck tap --label "Continue" --expect-label "Done"
simdeck back
simdeck swipe 200 700 200 200 --pre-delay-ms 100 --post-delay-ms 250
simdeck button lock --duration-ms 1000
Prefer to use
wait-for
or
assert
in a batch to wait for UI state instead of fixed delays.
sleep 500
in a batch waits 500 ms. Use
sleep 0.5s
or
sleep --seconds 0.5
when you want to write seconds explicitly.
Use
batch
when steps are known; use discrete commands when a later step depends on parsing previous output.
bash
simdeck batch \
  --step "tap --label Continue --wait-timeout-ms 5000 --expect-label Done" \
  --step "type 'hello world'" \
  --step "back" \
  --step "pinch --start-distance 0.20 --end-distance 0.35 --normalized"
Batch rules: one source (
--step
,
--file
, or
--stdin
); set the default with
simdeck use <UDID>
or keep
<UDID>
at batch level; ordered steps; fail-fast by default;
--continue-on-error
for best effort. Step commands:
tap
,
back
,
wait-for
,
assert
,
swipe
,
gesture
,
pinch
,
rotate-gesture
,
touch
,
type
,
button
,
key
,
key-sequence
,
key-combo
,
sleep
.
For JS tests, batch can combine action and verification without extra CLI process startup:
ts
await simdeck.batch([
  { action: "tap", selector: { label: "Continue" }, waitTimeoutMs: 5000 },
  {
    action: "waitFor",
    selector: { label: "Continue Tapped" },
    timeoutMs: 5000,
  },
  { action: "assert", selector: { id: "fixture.status" } },
]);
For app-style flows, SimDeck can run a practical subset of Maestro YAML:
bash
simdeck maestro test flow.yaml --artifacts-dir artifacts/maestro
bash
simdeck tap --label "Continue" --wait-timeout-ms 5000
simdeck tap --label "Continue" --expect-label "Done"
simdeck back
simdeck swipe 200 700 200 200 --pre-delay-ms 100 --post-delay-ms 250
simdeck button lock --duration-ms 1000
优先在批量操作中使用
wait-for
assert
等待 UI 状态,而非固定延迟。批量操作中的
sleep 500
会等待 500 毫秒。若要显式以秒为单位,可使用
sleep 0.5s
sleep --seconds 0.5
当步骤已知时使用
batch
;当后续步骤依赖于解析前一步输出时,使用离散命令。
bash
simdeck batch \
  --step "tap --label Continue --wait-timeout-ms 5000 --expect-label Done" \
  --step "type 'hello world'" \
  --step "back" \
  --step "pinch --start-distance 0.20 --end-distance 0.35 --normalized"
批量操作规则:仅可使用一种数据源(
--step
--file
--stdin
);通过
simdeck use <UDID>
设置默认设备,或在批量操作级别指定
<UDID>
;步骤按顺序执行;默认快速失败;使用
--continue-on-error
参数可实现尽力执行。支持的步骤命令包括:
tap
back
wait-for
assert
swipe
gesture
pinch
rotate-gesture
touch
type
button
key
key-sequence
key-combo
sleep
对于 JS 测试,批量操作可将动作与验证结合,无需额外启动 CLI 进程:
ts
await simdeck.batch([
  { action: "tap", selector: { label: "Continue" }, waitTimeoutMs: 5000 },
  {
    action: "waitFor",
    selector: { label: "Continue Tapped" },
    timeoutMs: 5000,
  },
  { action: "assert", selector: { id: "fixture.status" } },
]);
对于应用式流程,SimDeck 可运行 Maestro YAML 的实用子集:
bash
simdeck maestro test flow.yaml --artifacts-dir artifacts/maestro

Evidence

证据收集

bash
simdeck screenshot --output screen.png
simdeck screenshot --with-bezel --output screen-bezel.png
simdeck screenshot --stdout > screen.png
simdeck record --seconds 5 --output screen-recording.mp4
simdeck record --seconds 5 --stdout > screen-recording.mp4
simdeck logs --seconds 30 --limit 200
simdeck chrome-profile
simdeck processes
simdeck stats
simdeck stats --watch
simdeck sample --seconds 3
Use screenshots for still evidence,
--with-bezel
when the device frame matters, and
record
for short MP4 screen recordings. Use
stats
for simulator app CPU, memory, disk write, network receive/send rates, connections, hang, and crash/termination signals. Use
sample
only when a short CPU stack capture is worth the extra pause. Prefer describe for token-efficient state dumps, if they have enough context.
bash
simdeck screenshot --output screen.png
simdeck screenshot --with-bezel --output screen-bezel.png
simdeck screenshot --stdout > screen.png
simdeck record --seconds 5 --output screen-recording.mp4
simdeck record --seconds 5 --stdout > screen-recording.mp4
simdeck logs --seconds 30 --limit 200
simdeck chrome-profile
simdeck processes
simdeck stats
simdeck stats --watch
simdeck sample --seconds 3
使用截图获取静态证据,当设备边框重要时使用
--with-bezel
参数,使用
record
命令获取短时长 MP4 屏幕录制。使用
stats
命令查看模拟器应用的 CPU、内存、磁盘写入、网络接收/发送速率、连接情况、卡顿以及崩溃/终止信号。仅当短时间 CPU 堆栈捕获值得额外暂停时,使用
sample
命令。如果上下文足够,优先使用 describe 命令获取高效的状态快照。

Default loop

默认流程

  1. Start UI, list,
    simdeck use <UDID>
    , boot/select the device, open viewer if in-app browser available
  2. Build with project tools; install and launch with SimDeck.
  3. Use one
    describe --format agent --max-depth 4
    to understand an unfamiliar screen.
  4. Interact with selectors first; use coordinates only when needed.
  5. Verify with
    waitFor
    /
    assert
    /
    query
    , not repeated full
    describe
    dumps.
  6. Batch known flows; keep
    describe
    as a failure/debug artifact.
  1. 启动 UI,列出设备,执行
    simdeck use <UDID>
    ,启动/选择设备;若应用内浏览器可用,打开查看器
  2. 使用项目工具构建应用;通过 SimDeck 安装并启动应用
  3. 执行一次
    describe --format agent --max-depth 4
    命令,了解陌生界面
  4. 优先使用选择器进行交互;仅在必要时使用坐标
  5. 使用
    waitFor
    /
    assert
    /
    query
    进行验证,而非反复获取完整的
    describe
    输出
  6. 对已知流程使用批量操作;将
    describe
    作为失败/调试产物

Optional inspector plugins

可选检查器插件

For a richer hierarchy, if user wants to opt-in
若用户希望获得更丰富的层级结构,可选择启用以下插件

NativeScript Inspector

NativeScript 检查器

NativeScript apps can connect directly to the running server from JS and expose their view hierarchy plus raw UIKit backing views
ts
import { startSimDeckInspector } from "@nativescript/simdeck-inspector";

if (__DEV__) {
  startSimDeckInspector({ port: 4310 });
}
The runtime connects to
GET /api/inspector/connect
as a WebSocket
NativeScript 应用可从 JS 直接连接到运行中的服务器,暴露其视图层级及原始 UIKit 底层视图
ts
import { startSimDeckInspector } from "@nativescript/simdeck-inspector";

if (__DEV__) {
  startSimDeckInspector({ port: 4310 });
}
运行时会通过 WebSocket 连接到
GET /api/inspector/connect

React Native Inspector

React Native 检查器

React Native apps can expose their component tree and Metro dev-mode source locations with the inspector package:
ts
import "react-native-simdeck/auto";
import "expo-router/entry";
Import it before
expo-router/entry
or
AppRegistry.registerComponent(...)
. The auto entrypoint no-ops outside development, reads
EXPO_PUBLIC_SIMDECK_PORT
when present, and otherwise scans common SimDeck service ports. Use the manual
startSimDeckReactNativeInspector(...)
API when you need custom host/path/security options.
React Native 应用可通过检查器包暴露其组件树及 Metro 开发模式源码位置:
ts
import "react-native-simdeck/auto";
import "expo-router/entry";
需在
expo-router/entry
AppRegistry.registerComponent(...)
之前导入该包。自动入口在开发环境外会无操作,若存在
EXPO_PUBLIC_SIMDECK_PORT
则读取该端口,否则扫描常用的 SimDeck 服务端口。当需要自定义主机/路径/安全选项时,使用手动
startSimDeckReactNativeInspector(...)
API。