simdeck について
simdeckは、コマンドラインとブラウザー画面からiOSシミュレーターやAndroidエミュレーターを操作するツールです。Agentによる画面確認やアプリテストに向け、端末操作、UI操作、テストAPIをローカルサービスにまとめています。
主な機能
- 01iOSシミュレーターとAndroidエミュレーターの操作
- 02UI階層の確認とセレクター操作
- 03バッチコマンドとsimdeck/test API
- 04スクリーンショット、録画、ログ、統計情報
- 05iOSアプリ向けカメラ映像のシミュレーション
活用シーン
- 01モバイルアプリのUIテストフローの自動化
- 02画面の確認とUI状態の検証
- 03シミュレーターの証跡や診断情報の取得
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ nativescript/ simdeck --skill simdeckインストール後、Claude Code で/simdeckを入力して読み込まれたか確認します。
詳細
SimDeck エージェントガイド
SimDeck は iOS シミュレーターと Android エミュレーターを自動化します。自動化には CLI を、リアルタイムで人が確認するにはブラウザー UI を使用します。iOS は NativeScript、UIKit、SwiftUI、React Native、Expo、Flutter アプリに対応しています。Android のライブ表示では、エミュレーターの -share-vid 共有ディスプレイサーフェスと SimDeck のネイティブホスト H.264 エンコーダーを使用し、ライフサイクル、スクリーンショット、ログ、UIAutomator の階層ダンプも ADB 経由で処理します。
SimDeck は、長時間稼働する単一のローカルサービスを使用します。最初に simdeck を実行すると、バックグラウンドサービスを起動または再利用し、ブラウザー URL とペアリングコードを表示します。SimDeck に既定のブラウザーを開かせる場合に限り、--open を指定してください。サービスに既定以外のポートを使用させる場合は、-p <port> または --port <port> を指定してください。サービスを macOS LaunchAgent として登録する場合は、-a または --autostart を指定してください。
simdeck の応答例:
{
"ok": true,
"pairingCode": "401974",
"pid": 91285,
"projectRoot": "-",
"started": true,
"url": "http://127.0.0.1:4310"
}
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
通常は http://127.0.0.1:4310 です。ブラウザー URL を ?device=<UDID> 付きで開く場合は、シミュレーター名または UDID を simdeck に渡してください。既定のポートが適さない場合は、simdeck -p 4311 を使用してください。
ネイティブ iOS クライアントをペアリングするには、simdeck pair を使用してください。LaunchAgent 経由のサービスを起動または更新し、LAN と Tailscale の IPv4 アドレスを検出して、simdeck://pair URL を含む QR コードを表示します。通常のサービス再起動ではトークンとペアリングコードが保持されます。これらを更新する必要がある場合に限り、simdeck service reset を使用してください。
インストール済みのバイナリとソースチェックアウトのバイナリをまとめてクリーンな状態にする必要がある場合は、simdeck service kill または simdeck service killall を使用してください。
ユーザーが現在のシミュレーターをスマートフォンから操作したい可能性がある場合は、任意で simdeck link [sim] を実行し、解決されたシミュレーターを対象にした、iOS の SimDeck Studio(またはブラウザーのランチパッド)を開く https://app.simdeck.sh/open のユニバーサルリンクを表示します。
必ず最初に simdeck を実行し、Browser ツールが利用可能な場合は、アプリ内ブラウザーで表示された URL を開いてください。
Browser Use が利用できない場合に限り、simdeck --open を使用してください。これは既定のブラウザーを開き、アプリからフォーカスを移す可能性があります。
デバイスとアプリ
最初に、プロジェクトの既定デバイスを選択してください。simdeck use <UDID> は、現在のワークスペース/CWD に選択内容を保存するため、以降のコマンドでは UDID を省略できます。明示的な UDID、--device、SIMDECK_DEVICE、SIMDECK_UDID は、引き続き単発の上書きに使用できます。エージェントのループでは、simdeck tap "Continue" や simdeck snapshot --format agent --max-depth 2 -i のような短い形式を優先してください。
simdeck list
simdeck list --format json
simdeck use <UDID>
simdeck boot <UDID>
simdeck boot android:<AVD_NAME> --android-emulator-arg=-no-snapshot
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 camera sources
simdeck camera start com.example.App --file /absolute/path/to/camera.mov
simdeck camera start com.example.App --webcam
simdeck camera switch --placeholder
simdeck camera status
simdeck camera stop
simdeck list は、エージェントによるトークン効率の高い選択のため、既定でコンパクトな JSON を出力します。フルパスと表示メタデータが必要な場合に限り、simdeck list --format json を使用してください。
アプリはプロジェクトのツールでビルドしてください。
Android デバイスの ID は android:Pixel_8_API_36 のような形式です。simdeck list は Android SDK から AVD を検出します。
SimDeck が管理する Android の起動では、ライブ動画にエミュレーターの gRPC スクリーンショットストリーミングを使用し、フォールバックとしてエミュレーターの共有動画サーフェスを維持します。また、既定で --android-gpu host を使用します。Android のブラウザーストリームは、エミュレーターの gRPC フレーム生成をスムーズに保つため、既定でソフトウェア H.264、60 fps、長辺 960px の上限を使用します。macOS では、管理対象の起動時に -qt-hide-window を使用し、ネイティブのエミュレーターウィンドウを表示せずに Qt のレンダリングループを動作させます。
ホスト GPU のレンダリングが不安定な場合に限り、simdeck service restart --android-gpu auto または --android-gpu swiftshader_indirect を使用してください。
ユーザー向けの任意の既定値は ~/.simdeck/config.json に保存されます。サポートされるキーには、service.port、android.emulatorArgs、android.disableAudio があります。単発の実行では、明示的に指定した CLI/API の起動引数が引き続き優先されます。
高速なエージェント検査
テストループには、対象を絞ったチェックを使用します。describe は階層全体の診断用スナップショットです。検証には、simdeck/test が公開するサービス API の action、query、waitFor、assert、セレクターの tap、batch を優先してください。
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 です。エージェントにとって最速かつ最も汎用的な方法です。ネイティブのアクセシビリティへのフォールバック前に、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 を使用してください。
エージェントに必要なのがコントロールと操作可能なフレームワークノードだけの場合は、--interactive または -i を使用してください。SimDeck は祖先のコンテキストを維持するため、出力を引き続きたどることができます。エージェント向け出力では、ノードに @e3 のような参照が付けられます。これを simdeck press @e3 で再利用してください。snapshot、press、wait はそれぞれ describe、tap、wait-for のエイリアスです。
必要な場合に限り、座標ではなくセレクターを優先してください。セレクターによるタップはサービスを経由し、サーバー側で要素が表示されるまで待機します。タップ後、次の画面が表示されるまで待ってから戻るようにするには、--expect-id、--expect-label、または別の --expect-* セレクターを使用してください。
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 を使用してください。
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" を使用します。ネイティブのアクセシビリティへのフォールバック前に、フレームワークインスペクターのツリーを意図的に詳しく取得する場合に限り、source: "auto" を渡してください。
デバッグのために UI 全体を出力する必要があるテストに限り、tree()/describe を使用してください。通常のエージェントループでは、アクションのたびにツリー全体を取得しないでください。その手順が成功したことを証明する特定の要素またはテキストを検証してください。
操作
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
引用符、改行、シェル変数、またはシェルで特別な扱いを受ける文字を含むテキストには、--stdin または --file を使用してください。
タイミングとバッチ
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
固定時間の待機ではなく、UI の状態を待つために、バッチ内で wait-for または assert を優先して使用してください。バッチ内の sleep 500 は 500 ms 待機します。秒数を明示したい場合は、sleep 0.5s または sleep --seconds 0.5 を使用してください。
手順が決まっている場合は batch を使用し、後続の手順が前の出力の解析に依存する場合は個別のコマンドを使用してください。
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"
バッチのルール:ソースは 1 つだけ(--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 プロセスの起動を余分に行わずに済みます。
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 の実用的なサブセットを実行できます。
simdeck maestro test flow.yaml --artifacts-dir artifacts/maestro
証拠
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 を指定してください。短い MP4 画面録画には record を使用します。シミュレーターアプリの CPU、メモリ、ディスク書き込み、ネットワークの受信/送信レート、接続、ハング、クラッシュ/終了のシグナルには stats を使用してください。短い CPU スタックのキャプチャに追加の一時停止をかける価値がある場合に限り、sample を使用してください。十分なコンテキストが得られる場合は、トークンを節約できる状態ダンプとして describe を優先してください。
カメラシミュレーション
起動済みの iOS シミュレーターアプリに決定性のあるカメラフィードが必要な場合は、camera start を使用します。CLI は SimDeck デーモンと通信します。デーモンはカメラソースと共有メモリーライターを管理し、simctl launch でカメラシムをアプリに注入して、バンドルを再起動します。デーモンのフィードが動作している間は、camera switch を使用して、再起動せずにプレースホルダー、メディア、ウェブカメラのソースを切り替えられます。
simdeck camera sources
simdeck camera start com.example.App --file /absolute/path/to/feed.mov --mirror off
simdeck camera switch --placeholder
simdeck camera start com.example.App --webcam "FaceTime HD Camera"
simdeck camera stop
メディアのパスは絶対パスである必要があります。URL は動画ストリームとして扱われます。ウェブカメラのサポートは、macOS でカメラが利用可能であり、SimDeck にアクセス許可が与えられていることを条件とします。
デフォルトのループ
- UI を起動し、一覧表示して、
simdeck use <UDID>を実行し、デバイスを起動または選択して、アプリ内ブラウザーが利用可能であればビューアーを開きます - プロジェクトのツールでビルドし、SimDeck でインストールして起動します。
- 不慣れな画面を把握するには、
describe --format agent --max-depth 4を一度使用します。 - まずセレクターで操作し、必要な場合にのみ座標を使用します。
describeの全出力を繰り返し取得するのではなく、waitFor/assert/queryで検証します。- 既知のフローはまとめて実行し、
describeは失敗時やデバッグ時の記録として使用します。
オプションのインスペクタープラグイン
より詳細な階層が必要で、ユーザーがオプトインを希望する場合
NativeScript Inspector
NativeScript アプリは、JS から実行中のサーバーに直接接続し、ビュー階層と UIKit の生のバッキングビューを公開できます。
import { startSimDeckInspector } from "@nativescript/simdeck-inspector";
if (__DEV__) {
startSimDeckInspector({ port: 4310 });
}
ランタイムは WebSocket として GET /api/inspector/connect に接続します。
React Native Inspector
React Native アプリは、インスペクターパッケージを使用してコンポーネントツリーと Metro の開発モードのソース位置を公開できます。
import "react-native-simdeck/auto";
import "expo-router/entry";
expo-router/entry または AppRegistry.registerComponent(...) より前にインポートしてください。自動エントリーポイントは開発モード以外では何もせず、EXPO_PUBLIC_SIMDECK_PORT が設定されている場合はその値を読み取り、設定されていない場合は一般的な SimDeck サービスポートをスキャンします。ホスト/パス/セキュリティのオプションをカスタマイズする場合は、手動の startSimDeckReactNativeInspector(...) API を使用してください。