ios-device-automation について
スクリーンショットと自然言語コマンドで iOS デバイスを操作する Midscene スキルです。iOS コマンドラインを使い、AI エージェントが UI 操作を順に実行して検証します。
主な機能
- 01自然言語による UI 操作
- 02画面の撮影と分析
- 03画面状態のアサーション
- 04一時的な UI の記録
- 05WebDriverAgent リクエストとレポート
活用シーン
- 01iOS アプリで複数手順を実行
- 02QA で表示状態を確認
- 03一時的な通知や画面遷移を記録
- 04WebDriverAgent 経由でデバイスを確認
MCP 対応
iOS コマンドラインの各コマンドは MCP ツールに対応し、AI エージェントがスクリーンショットを基にデバイスを操作します。
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ web-infra-dev/ midscene-skills --skill ios-device-automationインストール後、Claude Code で/ios-device-automationを入力して読み込まれたか確認します。
詳細
iOS デバイスの自動化
重要なルール — 違反するとワークフローが壊れます:
- midscene コマンドをバックグラウンドで実行しないでください。 各コマンドは同期的に実行し、次のアクションを決める前に出力(特にスクリーンショット)を確認してください。バックグラウンドで実行すると、スクリーンショットを分析して操作するループが壊れます。
- midscene コマンドは一度に1つだけ実行してください。 前のコマンドが完了するのを待ち、スクリーンショットを確認してから、次のアクションを決めてください。複数のコマンドを連結して実行しないでください。
- 各コマンドの完了に十分な時間を確保してください。 Midscene のコマンドでは AI 推論と画面操作が行われるため、一般的なシェルコマンドより時間がかかることがあります。通常、コマンドの実行には約1分かかります。複雑な
actコマンドでは、さらに長くかかることがあります。- 終了する前に、必ずタスクの結果を報告してください。 自動化タスクの完了後、見つかった重要なデータ、完了した操作、撮影したスクリーンショット、関連する調査結果などを含め、ユーザーに結果を積極的に要約して伝える必要があります。最後の自動化手順の後に何も言わずに終了しないでください。ユーザーは1回のやり取りで完結した回答を期待しています。
npx -y @midscene/ios@1 を使用して iOS デバイスを自動化します。各 CLI コマンドは MCP ツールに直接対応します。AI エージェントであるあなたが、スクリーンショットに基づいて実行する操作を決定します。
act でできること
iOS で1回の act 呼び出しを行うと、Midscene は現在表示されている画面をもとに、タップ、ダブルタップ、長押し、テキスト入力、テキストの消去、スクロール、項目のドラッグ、2本指でのズーム、キーの押下、ホーム画面やアプリスイッチャーなどのシステムナビゲーションを実行できます。
前提条件
Midscene には、視覚的なグラウンディング能力に優れたモデルが必要です。以下の環境変数を、システム環境変数または現在の作業ディレクトリにある .env ファイルに設定する必要があります(Midscene は .env を自動的に読み込みます)。
MIDSCENE_MODEL_API_KEY="your-api-key"
MIDSCENE_MODEL_NAME="model-name"
MIDSCENE_MODEL_BASE_URL="https://..."
MIDSCENE_MODEL_FAMILY="family-identifier"
例:Gemini(Gemini-3-Flash)
MIDSCENE_MODEL_API_KEY="your-google-api-key"
MIDSCENE_MODEL_NAME="gemini-3-flash"
MIDSCENE_MODEL_BASE_URL="https://generativelanguage.googleapis.com/v1beta/openai/"
MIDSCENE_MODEL_FAMILY="gemini"
例:Qwen 3.5
MIDSCENE_MODEL_API_KEY="your-aliyun-api-key"
MIDSCENE_MODEL_NAME="qwen3.5-plus"
MIDSCENE_MODEL_BASE_URL="https://dashscope.aliyuncs.com/compatible-mode/v1"
MIDSCENE_MODEL_FAMILY="qwen3.5"
MIDSCENE_MODEL_REASONING_ENABLED="false"
# If using OpenRouter, set:
# MIDSCENE_MODEL_API_KEY="your-openrouter-api-key"
# MIDSCENE_MODEL_NAME="qwen/qwen3.5-plus"
# MIDSCENE_MODEL_BASE_URL="https://openrouter.ai/api/v1"
例:Doubao Seed 2.0 Lite
MIDSCENE_MODEL_API_KEY="your-doubao-api-key"
MIDSCENE_MODEL_NAME="doubao-seed-2-0-lite"
MIDSCENE_MODEL_BASE_URL="https://ark.cn-beijing.volces.com/api/v3"
MIDSCENE_MODEL_FAMILY="doubao-seed"
よく使用されるモデル:Doubao Seed 2.0 Lite、Qwen 3.5、Zhipu GLM-4.6V、Gemini-3-Pro、Gemini-3-Flash。
モデルが設定されていない場合は、ユーザーに設定を依頼してください。対応プロバイダーについては、モデルの設定を参照してください。
コマンド
デバイスへの接続
npx -y @midscene/ios@1 connect
WebDriverAgent がすでに起動していて、セッションが Midscene の外部で作成されている場合は、WDA エンドポイントと外部セッション ID を一緒に渡します。
npx -y @midscene/ios@1 connect --wda-host 127.0.0.1 --wda-port 8100 --session-id <sessionId>
既存の WDA セッションを使用して後続のコマンドを実行する場合は、同じ --wda-host、--wda-port、--session-id オプションを指定してください。
アプリ、URL、またはディープリンクを起動する
タスクの残りを始める前に、既知のアプリやルートから開始する場合は、組み込みの起動機能を使用します。バンドル ID、Web URL、ディープリンク、電話番号またはメールアドレスへのリンクなど、入手できる中で最も具体的なターゲットを指定してください。一般的なターゲットには、com.apple.Preferences、https://www.apple.com、myapp://profile/user/123、tel:+1234567890 などがあります。
デバイスへ直接リクエストを送信する
通常の画面上の操作ではなく、より低レベルのデバイス制御が必要なタスクでは、これを使用します。
npx -y @midscene/ios@1 runwdarequest --method GET --endpoint /wda/screen
これは ADB コマンドを実行しません。iOS では、基盤となる操作は WebDriverAgent への HTTP リクエストで、通常は GET http://<wdaHost>:<wdaPort>/session/<sessionId>/wda/screen です。
スクリーンショットを撮る
npx -y @midscene/ios@1 take_screenshot
スクリーンショットを撮った後、保存された画像ファイルを読み込み、次のアクションを決める前に現在の画面の状態を確認してください。
操作を実行する
act を使用してデバイスを操作し、結果を取得します。タップ、テキスト入力、スクロール、スワイプ、待機、画面遷移など、すべての UI 操作を内部で自律的に処理します。そのため、作業を細かい手順に分けるのではなく、複雑で高レベルなタスク全体をまとめて指示してください。自然言語で、何をしたいのか、どのような結果を得たいのかを説明します。
# specific instructions
npx -y @midscene/ios@1 act --prompt "type hello world in the search field and press Enter"
npx -y @midscene/ios@1 act --prompt "tap Delete, then confirm in the alert dialog"
# or target-driven instructions
npx -y @midscene/ios@1 act --prompt "open Settings and navigate to Wi-Fi, tell me the connected network name"
現在の画面状態を検証する
assert を使用して、現在の画面が自然言語の条件を満たしているかを検証します。UI 操作は実行せず、表示されている画面の状態をチェックし、アサーションが真の場合にのみ成功します。検証、QA チェック、および act の後の最終状態の確認に使用してください。
npx -y @midscene/ios@1 assert --prompt "there is a login button visible"
npx -y @midscene/ios@1 assert --prompt "the settings screen shows Wi-Fi and Bluetooth options"
デフォルトでは、アサーションに失敗すると AI が生成した理由を含むエラーがスローされます。代わりにカスタムエラーメッセージをスローするには --message を渡します。これは、QA や CI のログに意図した結果を表示するのに便利です。
npx -y @midscene/ios@1 assert \
--prompt "the order confirmation screen is visible" \
--message "the order should be confirmed after tapping Pay"
参照画像(アイコン、ロゴ、スクリーンショット)と比較する必要がある場合は、URL/パスに --image を、表示名に --image-name を渡します。各 --image には、http(s) リンク、data: URI、またはローカルファイルパスを指定できます。複数の画像を添付する場合は、両方のフラグを対応する順序で繰り返します。モデルが URL に直接アクセスできない場合は、--convertHttpImage2Base64 true を追加してください。@midscene/[email protected]+ が必要です。
npx -y @midscene/ios@1 assert \
--prompt "the visible app icon matches the supplied reference image" \
--image "https://github.githubassets.com/assets/GitHub-Mark-ea2971cee799.png" \
--image-name "icon" \
--convertHttpImage2Base64 true
# or with a local file
npx -y @midscene/ios@1 assert \
--prompt "the header on screen matches the local screenshot" \
--image "./fixtures/header.png" \
--image-name "header"
# multiple reference images — pair --image and --image-name by order
npx -y @midscene/ios@1 assert \
--prompt "the screen shows both the app icon and the header" \
--image "./fixtures/icon.png" --image-name "icon" \
--image "./fixtures/header.png" --image-name "header"
一時的な UI を記録して検証する
トースト、読み込みバナー、アニメーション、トランジションなど、現在の画面を検証する前に状態が消える可能性がある場合は、記録を使用します。
# Terminal 1: keep this foreground command running
npx -y @midscene/ios@1 record start --device-id <udid> \
--output ./submission-observation.json
# Terminal 2, while Terminal 1 records
npx -y @midscene/ios@1 act --device-id <udid> \
--prompt "tap the Submit button"
# Send Ctrl+C to Terminal 1 and wait for the saved-path message, then assert
npx -y @midscene/ios@1 assert --device-id <udid> \
--record ./submission-observation.json \
--prompt "a success toast appeared during submission"
record start に対象フラグ、キャプチャフラグ、--output を渡し、Recording. Press Ctrl+C to stop and save. が表示されるまで待ちます。レコーダーは専用ターミナルでフォアグラウンドプロセスとして実行してください。シェルの & は追加しないでください。操作は手動または 2 つ目のターミナルから実行し、レコーダーに Ctrl+C を送信した後、保存先のパスが表示されるまで待ってから検証します。記録では、有効な場合は WDA MJPEG フレームソースを使用し、それ以外の場合は定期的なスクリーンショットにフォールバックします。省略可能なキャプチャフラグは --interval-ms、--max-frames、--watchdog-ms です。--max-frames はサンプリングするフレーム数を制限しますが、マニフェストには代表的な最終フレームが 1 枚追加される場合があります。デフォルトでは、ウォッチドッグが 5 分後に記録を確定して保存します。--watchdog-ms 0 を指定すると、この安全制限は無効になります。出力は JSON マニフェストと、その隣にある <name>.frames 画像ディレクトリです。エンコードされた動画やアーカイブではありません。マニフェストには相対 JPEG/PNG パスが含まれ、base64 画像データは含まれません。JSON ファイルと画像ディレクトリは一緒に保管または移動し、assert --record に JSON のパスを渡してください。現在の画面だけを確認する場合は、--record を付けずに通常の assert を使用します。
正確なターゲット指定に参照画像を使う
ユーザーがスクリーンショット、アイコン、ロゴ、または参照画像を提供し、視覚的に完全一致させたい場合は、汎用的な act --prompt ではなく、tap --locate を優先してください。--locate には JSON を渡します。prompt で対象を説明し、images で名前付き参照画像を指定します。画像 URL にモデルが直接アクセスできない可能性がある場合は、convertHttpImage2Base64: true が便利です。
npx -y @midscene/ios@1 tap --locate '{
"prompt": "tap the area contains the image",
"images": [
{
"name": "target image",
"url": "https://github.githubassets.com/assets/GitHub-Mark-ea2971cee799.png"
}
],
"convertHttpImage2Base64": true
}'
同じ locate JSON 形式は、locate パラメーターを受け付ける他のコマンドでも使用できます。
切断する
npx -y @midscene/ios@1 disconnect
レポートファイルを利用する
生成された HTML レポートは、まず人が読む用途におすすめです。各操作の手順ごとの実行詳細とリプレイ動画が含まれているため、何が起きたかを理解し、問題をトラブルシューティングしやすくなります。
別のスキルやツールでレポートを利用する場合は、まず同じプラットフォームの CLI パッケージに含まれる report-tool で変換してください。LLM ベースのワークフローでは Markdown を優先します。レポートをプログラムで処理する必要がある場合は、JSON を使用してください。
npx -y @midscene/ios@1 report-tool --action to-markdown --htmlPath ./midscene_run/report/.../index.html --outputDir ./output-markdown
npx -y @midscene/ios@1 report-tool --action split --htmlPath ./midscene_run/report/.../index.html --outputDir ./output-data
ワークフローパターン
CLI コマンドは呼び出し間で状態を保持しないため、次のパターンに従ってください。
- 接続してセッションを確立します
- 対象のアプリを起動してスクリーンショットを撮影し、現在の状態を確認します。アプリが起動しており、画面上に表示されていることを確認してください。
actを使って操作を実行し、目的の操作や対象に基づく指示を行います。操作後の画面状態にはassertを使います。または、一時的な状態を扱うワークフローでは、専用のターミナルでrecord start --output ...を実行したままにし、Ctrl+C で停止してからassert --recordを使います。- 完了したら切断します
- 結果を報告します — 実行した内容をまとめ、重要な調査結果やタスク中に抽出したデータを提示し、生成されたファイル(スクリーンショット、ログなど)をパスとともに列挙します
ベストプラクティス
- UI 要素を具体的に指定する:曖昧な説明ではなく、明確で具体的な詳細を示してください。「アイコン」ではなく、「右上の Settings アイコン」のように指定します。
- 可能な場合は位置を説明する:要素の位置(例:「右上の検索アイコン」「リストの3番目の項目」)を説明して、対象を見つけやすくしてください。
- バックグラウンドで実行しない:Midscene の各コマンドは同期的に実行する必要があります。バックグラウンドで実行すると、スクリーンショットを確認して操作するループが崩れます。
- 関連する操作は1つの
actコマンドにまとめる:同じアプリ内で連続して操作する場合は、別々のコマンドに分けず、1つのactプロンプトにまとめてください。たとえば、「Settings を開き、Wi-Fi をタップして、接続中のネットワークを確認する」操作は、3回ではなく1回のact呼び出しで行います。これにより、やり取りの回数と不要なスクリーンショット確認のサイクルが減り、大幅に高速化できます。 - 適切な検証タイミングを選ぶ:現在の画面には
assert --prompt "..."を使います。トースト、バナー、アニメーション、画面遷移を確認する場合は、専用のターミナルでrecord start --output ...を実行し、操作を行ってから Ctrl+C で録画を停止します。保存先のメッセージが表示されるまで待ち、その後、保存されたファイルをassert --recordに渡します。 - 完了後は必ず結果を報告する:自動化タスクを終えたら、ユーザーから尋ねられるのを待たずに、必ず結果を提示してください。これには、(1)ユーザーの元の質問への回答、または依頼されたタスクの結果、(2)実行中に抽出または確認した重要なデータ、(3)スクリーンショットやその他の生成ファイルとそのパス、(4)実施した手順の簡単なまとめが含まれます。最後の自動化コマンドの後に、結果を報告せずに終了しないでください。ユーザーは1回のやり取りで完結した結果を期待しています。
- 参照画像がある場合は
tap --locateを優先する:ユーザーがスクリーンショット、アイコン、ロゴを共有し、その見た目と完全に一致する対象を指定した場合は、act --promptだけに頼るのではなく、{ "prompt": "...", "images": [...] }のようなマルチモーダルなlocateJSON オブジェクトを使ってtap --locateを実行してください。
例 — アラートダイアログの操作:
npx -y @midscene/ios@1 act --prompt "tap the Delete button and confirm in the alert dialog"
npx -y @midscene/ios@1 take_screenshot
例 — フォームの操作:
npx -y @midscene/ios@1 act --prompt "fill in the username field with 'testuser' and the password field with 'pass123', then tap the Login button"
npx -y @midscene/ios@1 take_screenshot
精度の向上(Deep Locate / Deep Think)
Midscene でタスクの実行が難しい場合に役立つ、任意のグローバルフラグが2つあります。コマンドのどこにでも(サブコマンドの前後に)指定できます。一度設定すると、該当する操作でデフォルトとして使われるため、呼び出しごとにパラメーターを渡す必要はありません。
--deep-locate— 対象要素を特定するために、視覚的な推論を追加で行います。操作する位置がずれている場合(位置のずれやオフセットがある場合)に使います。tap --locateを含め、要素を特定するすべての操作と、act内で行われる要素の特定に適用されます。--deep-think— より深い推論(より豊かなコンテキストとサブゴールへの分解)を用いてactの計画を立てます。複雑な複数ステップのact指示に使います。計画にのみ影響します。
どちらも速度を少し犠牲にする代わりに、結果の精度を高めます。組み合わせて使うこともできます。
# more accurate element location (helps act's internal locating too)
npx -y @midscene/ios@1 act --deep-locate --prompt "tap the small back chevron in the top-left corner"
# deeper planning for a complex, multi-step act
npx -y @midscene/ios@1 act --deep-think --prompt "complete the multi-step signup form and submit"
# combine both
npx -y @midscene/ios@1 act --deep-locate --deep-think --prompt "open Settings, go to Display & Brightness, and turn on Dark Mode"
トラブルシューティング
WebDriverAgent が実行されていない
症状: 接続拒否またはタイムアウトエラーが発生します。 解決方法:
- WebDriverAgent がデバイスにインストールされ、実行中であることを確認してください。
- 別のツールで WDA セッションを作成した場合は、
--session-idと、それに一致する--wda-hostおよび--wda-portを指定して、そのセッションを明示的に渡してください。 - セットアップ手順については、https://midscenejs.com/usage-ios.html を参照してください。
デバイスが見つからない
症状: デバイスが検出されない、または接続エラーが発生します。 解決方法:
- デバイスが USB で接続され、信頼されていることを確認してください。
API キーの問題
症状: 認証エラーまたはモデルエラーが発生します。 解決方法:
.envファイルにMIDSCENE_MODEL_API_KEY=<your-key>が含まれていることを確認してください。- 詳細については、https://midscenejs.com/zh/model-common-config.html を参照してください。
@midscene/* の依存関係のバージョンが古い
症状: 予期しない動作、機能の不足、またはバージョン不一致エラーが発生します。 解決方法:
- ローカルのバージョンを確認してください:
npm ls @midscene/ios @midscene/core @midscene/shared(またはpnpm why @midscene/ios)。 - 最新バージョンを確認してください:
npm view @midscene/ios version、npm view @midscene/core version、npm view @midscene/shared version。 - 依存関係をアップグレードしてください:
npm i @midscene/ios@latest @midscene/core@latest @midscene/shared@latest。