serve-sim について
serve-sim は、Agent から CLI で Apple Simulator を操作する方法を案内するスキルです。iOS、iPad、Apple Watch アプリのテスト向けに、操作や画面配信、カメラ入力、アクセシビリティ確認を扱います。
主な機能
- 01タップ、スワイプ、複数段階のジェスチャー
- 02ブラウザーでシミュレーター画面をプレビュー
- 03合成カメラ映像の注入
- 04アプリのプライバシー権限管理
- 05アクセシビリティツリーの取得
- 06デバイスの回転とハードウェアボタン操作
活用シーン
- 01シミュレーター上のアプリフローを自動テスト
- 02ブラウザーからシミュレーター画面を確認
- 03アプリのカメラ入力と権限をテスト
- 04アクセシビリティ情報から UI 要素を特定
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ evanbacon/ serve-sim --skill serve-simインストール後、Claude Code で/serve-simを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
README.mdevals/evals.jsonreferences/buttons-rotation.mdca-debug.mdcamera.mdendpoints.mdgestures.mdpermissions.mdworkflows.mdscripts/check-prereqs.shensure-running.sh詳細
serve-sim
serve-sim CLI を使って、エージェントから Apple Simulator(iOS、iPad、Apple Watch)を操作します。serve-sim は、simctl io 経由でシミュレーターのフレームバッファーをキャプチャする Swift ヘルパーを起動し、MJPEG ストリームとバイナリ WebSocket 入力チャネルとして公開するとともに、その上に React プレビュー UI を提供します。このスキルでは、エージェント向けに正確な CLI の仕様、ジェスチャー JSON の形式、注意点、推奨ワークフローについて説明します。
使用する場面
- ユーザーが、実行中の Apple Simulator に対してエージェントからタップ、スワイプ、ドラッグ、ピンチ、またはハードウェアボタンの入力を行いたい場合。
- ユーザーが、レビューやリモート操作のためにシミュレーターをブラウザーにストリーミングしたい場合(ローカル、LAN、またはトンネル経由)。
- ユーザーが、シミュレーター上の特定のアプリに合成カメラフィード(ファイル、Web カメラ、またはアニメーション付きプレースホルダー)を入力したい場合。
- ユーザーが、パフォーマンス作業のためにCoreAnimation デバッグオーバーレイ(オフスクリーンレンダリング、ブレンドレイヤー、低速アニメーション)を切り替えたい場合。
- ユーザーが、プログラムからメモリー警告をシミュレートしたり、デバイスを回転させたりしたい場合。
- ユーザーが、ピクセルを探し回ることなく UI 要素を見つけるために、シミュレーターのアクセシビリティツリーを読み取りたい場合。
- ユーザーが、アプリのプライバシー権限(カメラ、写真、位置情報、連絡先、プッシュ通知)を許可、取り消し、またはリセットしたい場合。
使用しない場面
- Android エミュレーター →
adb shellツールを使用します。 - iOS アプリのビルドまたはインストール →
xcodebuildまたはxcrun simctl installを使用します。 - React Native アプリ内ランタイムのデバッグ(Redux の状態、ネットワークの検査、コンポーネントツリー) → rn-debugger ツールを使用します。
- 実機の iOS デバイス →
xcrun devicectlまたは Xcode を使用します。
前提条件
ほかの操作を行う前に、ホストが以下の条件を満たしていることを確認します。不足しているものがあれば、ユーザーにインストールするものを正確に伝え、先へ進まないでください。
| 要件 | 確認コマンド | 理由 |
|---|---|---|
| macOS ホスト | uname -s の戻り値が Darwin | serve-sim は macOS でのみ動作します |
| Xcode CLI ツール | xcrun --version が終了コード 0 で終了 | simctl は基盤となるシミュレータードライバーです |
| Node.js ≥18 | node --version が ≥18 | serve-sim は npx 経由で実行する npm パッケージです |
| macOS 14+(任意) | sw_vers -productVersion が ≥14 | camera サブコマンドでのみ必須です |
バンドル済みのヘルパースクリプト scripts/check-prereqs.sh を利用できます。実行し、終了コードが 0 以外の場合はメッセージをユーザーに伝えてください。
ほとんどのサブコマンドでは、起動済みのシミュレーターが必要です。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 │
└──────────────────┘
エージェントが守るべき重要な不変条件:
- すべての座標は 0..1 に正規化され、画面の左上が
(0, 0)、右下が(1, 1)です。ピクセル座標は決して渡さないでください。 - デバイスごとにヘルパーは 1 つです。複数の起動済みシミュレーターは、デバイス名を複数渡すか、すべてに接続することでサポートされます。
- 状態は
$TMPDIR/serve-sim/server-{udid}.jsonに保存されます。状態の確認にはserve-sim --listを使用し、仕組みを理解していない限り JSON を直接読み取らないでください。 rotateで設定した向きはヘルパーに記憶され、後続のジェスチャーはクライアント側で回転されます。回転後に生の座標を送信するエージェントは、手動で補正する必要はありません。
一般的な操作
| 目的 | コマンド | 備考 |
|---|---|---|
| プレビューサーバーを起動する | npx serve-sim [device] | デフォルトのプレビューは http://localhost:3200、ストリームは :3100 です。フォアグラウンドで動作します。 |
| ヘッドレス/デーモンとして起動する | npx serve-sim --detach [device] | pid、port、url を含む JSON を返します。エージェントのループで使用します。 |
| ホストのプレビューにストリームを表示する | npx serve-sim --detach -q → url をホストのプレビューツールに渡す | 「エージェントのプレビューにストリームを表示する」セクションを参照してください。 |
| 実行中のストリームを一覧表示する | npx serve-sim --list | JSON のみを出力するには -q を追加します。 |
| すべてのヘルパーを停止する | 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 | Debug → Simulate 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> を指定して対象のデバイスを選択できます。
重要な注意点:タップには gesture ではなく tap を使用する
serve-sim gesture を呼び出すたびに、独自の WebSocket が開きます。{"type":"begin",...} と {"type":"end",...} を指定した gesture の呼び出しを連続して行うと、呼び出し間の遅延が十分に大きいため、シミュレーターはタッチをタップではなく長押しとして解釈します。これはプロトコル上の意図的な制約であり、回避すべき不具合ではありません。
ルール:単発のタップには、必ず serve-sim tap <x> <y> を使用してください。gesture は、begin → move × N → end の間、同じソケットを使い続ける必要があるドラッグ、スワイプ、または複数ステップの操作にのみ使用してください。
特定のデバイスを指定する
複数のシミュレーターが起動している場合、すべてのサブコマンドで -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
起動中のシミュレーターが 1 台だけの場合は、-d を省略してください。このスキルでは、デバイス名を固定で指定するよりも、自動検出を優先してください。
出力モード
デフォルトでは、serve-sim は人が読めるステータスを stdout に出力します。エージェントのループでは、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 を付けない、人間向けの出力はバージョン間で変わる可能性があるため、解析しないでください。
エージェントのプレビューにストリームを表示する
ユーザーが「ここでシミュレーターを見せて」「プレビューで表示して」「このツールで開いて」などと依頼した場合、目的はシミュレーターを、ユーザーがチャットしているのと同じ画面にストリーミングすることです。serve-sim は通常の HTTP URL を返します。エージェントはその URL をユーザーに提示し、ホストにプレビューツールがあれば、そのツールに渡します。
手順:
-
serve-sim を起動して URL を取得します:
npx serve-sim --detach -q次のような JSON が返されます:
{"pid":..., "port":3200, "url":"http://localhost:3200", "streamUrl":"http://localhost:3100", ...}。urlフィールドは人間向けのプレビュー UI で、streamUrlは生の MJPEG エンドポイントです。 -
ユーザーが任意のブラウザーで手動で開けるよう、必ず URL をそのまま明示して返信に含めます。
-
ホストのプレビューツールを確認し、利用できるものがあれば URL を渡します。ツールセットに次のようなツールがある場合があります:
preview_start(Claude Code)—{ url: "<url>" }を指定して呼び出します。mcp__Claude_Preview__preview_start(一部の MCP セットアップ)。browser_open、open_urlなど、URL を開くツール — URL を渡します。- Cursor、Codex CLI などでは、エージェントにプレビューツールが公開されていない場合があります。その場合は URL を表示し、ユーザーに開き方(ブラウザー、IDE の組み込みブラウザーペインなど)を案内します。
-
**特定のプレビューツールがあると決めつけないでください。**現在のセッションで利用できるツールを確認します。上記の説明に当てはまるものがあれば使用し、なければ手順 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 未満の場合、後続で分かりにくいエラーが発生します。
- ボタン名を作り出さないでください。 有効なのは次の 6 つだけです:
home、swipe_home、app_switcher、lock、siri、side_button。正確な一覧は references/buttons-rotation.md を参照してください。 - 人間向けの非 quiet 出力を解析しないでください。 JSON を取得するには
-qを使います。 - カメラヘルパーを無関係なタスクの間も実行したままにしないでください。 終了したら
npx serve-sim camera --stop-webcamで停止します。 - アクセシビリティ検索で一致するものが見つからなかった場合、座標を推測しないでください。 対象要素を見つけるために AX ツリー(例:
GET /ax)を取得し、検索で結果が返されなかった場合は、明確に失敗を報告してください。推測した位置をタップするのは、ほとんどの場合、ユーザーに「対象が見つかりませんでした」と伝えるより悪い結果になります。ガードパターンについては、references/workflows.md のワークフロー 1 を参照してください。
リファレンス一覧
- references/gestures.md — 正確なジェスチャー JSON の形式、境界値、マルチタッチ、ドラッグ/スワイプの手順。
- references/buttons-rotation.md — 有効な 6 つのボタンと 4 つの向き、および動作に関する注意事項。
- references/camera.md — 合成カメラ入力:プレースホルダー、ファイル、ウェブカメラ、ミラーモード、ホットスワップ。
- references/permissions.md — プッシュ通知を含む、アプリのプライバシー権限の付与/取り消し。
- references/ca-debug.md — 5 つの CoreAnimation デバッグフラグと、それぞれが役立つ場面。
- references/endpoints.md — CLI を介さないエージェント向けの HTTP および WebSocket エンドポイント。
- references/workflows.md — UI オートメーション、カメラテスト、ディープリンクのワークフローに関する一連の手順。