device-interaction について
デバイス上でアプリの動作や UI、タッチ操作を検証するサブエージェントスキルです。アプリの起動、確認、操作、結果報告を行うセッション手順を定めています。
主な機能
- 01デバイス上でのアプリ検証
- 02ワークスペースとデバイスのセッション手順
- 03スクリーンショットと UI 階層の確認
- 04タッチ、キーボード、リモコン操作
- 05機能面と表示面の問題報告
活用シーン
- 01実装後の UI 機能確認
- 02想定外のタッチ動作の調査
- 03アプリの画面遷移と表示項目の検証
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ tartinerlabs/ skills --skill device-interactionインストール後、Claude Code で/device-interactionを入力して読み込まれたか確認します。
詳細
デバイス操作
トリガー条件: ユーザーがアプリの実機動作を検証/テスト/確認したいと依頼したとき、デバイスでの検証が必要な UI に影響する機能を実装した後、ユーザーが「動作しますか」「これをテストして」「デバイスで確認して」と発言したとき、ユーザーが UI が期待どおりに動作しないと報告したとき、タッチ/操作の問題をデバッグする必要があるとき。 トリガーしない条件: ユーザーが単体テストのみについて質問しているとき、デバイステストを伴わないビルドのみのリクエスト、デバイステストを伴わないコードレビュー、シミュレーター設定の質問、UI に影響しない変更(例: コメント、リファクタリング、UI 以外のロジック)。
メインエージェント向け
これはサブエージェントスキルです。 デバイス検証が必要なときに Agent ツール経由で呼び出してください。その作業用のセッションがすでに開いている場合は、そのセッション識別子をサブエージェントに渡し、そのサブエージェント専用に使用させてください。
Agent tool:
- subagent_type: "general-purpose"
- description: "Verify login feature works"
- prompt: "Using the device-interaction skill, verify that the login feature works correctly on session <session-identifier>. Launch the app, capture screenshot and UI hierarchy, check that the login button is visible and tappable, and report if the implementation is working correctly."
UI に影響する機能を実装した後は、このスキルを呼び出して、その実装がデバイス上で動作することを検証してください。
セッションのライフサイクル
DeviceInteractionStartWorkspaceSession (workspace-backed; do this early, runs in the background)
→ DeviceInteractionInstallAndRun (after each code change; includes building)
→ DeviceEventSynthesize (interact + observe, repeatable)
→ DeviceInteractionEndSession (when done — keeping sessions open is resource-heavy)
セッションを開始する方法は 2 つあります:
- DeviceInteractionStartWorkspaceSession — ワークスペースにバインドされます。DeviceInteractionInstallAndRun に必須です。ビルド中のアプリを検証するときに使用します。
- DeviceInteractionStartSession — どのワークスペースにもバインドされません。すでにインストールされているアプリを操作する場合にのみ使用します。
DeviceInteraction(Workspace)StartSession ツール
デバイスの検出
新しいデバイス操作セッションを開くときは、デバイス識別子を渡してデバイスを選択するか、省略して現在の宛先を使用します。空文字列を渡すと、利用可能なターゲットの一覧を取得できます。
DeviceInteractionInstallAndRun ツール
任意パラメータ
commandLineArguments— 起動時にアプリへ渡される引数。$(inherited)をトークンとして使用すると、スキームの既存の引数を保持できます(例:["$(inherited)", "--reset-state"]で末尾に引数を追加)。environmentVariables— 起動時にアプリの環境に設定されるキーと値のペア。"$(inherited)"をキーとして使用すると、スキームの既存の環境変数を保持できます(例:{"$(inherited)": "", "DEBUG_MODE": "1"})。
どちらのパラメータも省略すると、スキームの引数と環境は変更されません。
スキームを直接編集するよりも、これらのパラメータを優先してください。 これらはその 1 回の実行にのみ適用され、ユーザーの設定に永続的な影響を与えません。
サブエージェント向け
コードが原因である可能性のある UI の問題は必ず報告してください: テキストの重なりや判読不能、予期しない画像/テキストの切れ、誤った色など。
DeviceEventSynthesize ツール
このツールを使用すると、操作を実行し、デバイスの状態を観察できます。
ヒエラルキーファイルの読み取り
ヒエラルキーファイルには、各要素について計算された hitPoint 位置が含まれています:
UIView {{100, 200}, {60, 30}}, hitPoint: {130.0, 215.0}
UIButton "Login" {{110, 205}, {30, 20}}, hitPoint: {125.0, 215.0}
UIButton "Login2" {{140, 205}, {20, 20}}, hitPoint: {150.0, 215.0}, activationBundleId: com.your.app
{100, 200}- 原点位置{50, 30}- 幅と高さhitPoint: {125.0, 215.0}- 計算された hitPoint の座標(タップに最適)
タッチイベントには常に hitPoint 座標を優先してください。 hitPoint をタップし、(再キャプチャによって)効果がなかったことを確認した後にのみ、スクリーンショットから推定した生の位置にフォールバックしてもかまいません。
警告: isRemoteLeafPlaceholder とマークされた要素は子要素を報告しません — それらを操作するには、スクリーンショットから推定した座標にフォールバックする必要があります。
複数のアプリケーション(activationBundleId 注釈)
複数のアプリケーションのウィンドウが画面上で重なっている場合、各要素の行に activationBundleId: <bundle-identifier> という接尾辞が注釈として付きます。
要素の行に activationBundleId が付いている場合、それを操作するにはまずそのアプリケーションをアクティブにする必要があります。DeviceEventSynthesize ツールに activationBundleId パラメータを渡してください。
ヒント: interactionCommand なしで activationBundleId を渡すことができます。
アプリケーションのアクティブ化はコストが高いため、必要な場合にのみ使用してください。
例:
Device orientation: Landscape Right
------------------------
Application bundle identifier: com.some.app
Application UI orientation: Landscape Left
Application, pid: 123, label: ' '
Window, {{0.0, 0.0}, {1133.0, 744.0}}, hitPoint: {566.5, 372.0}
Other, {{0.0, 0.0}, {744.0, 1133.0}}, hitPoint: {372.0, 372.0}
...
------------------------
Application bundle identifier: com.some.other.app
Application UI orientation: Landscape Left
Application, pid: 333, label: ' '
Window, {{0.0, 0.0}, {1133.0, 744.0}}, hitPoint: {566.5, 372.0}
...
インタラクションコマンド構文
interactionCommand パラメータはコマンド構文を受け付けます:
| コマンド | 説明 |
|---|---|
t <x> <y> [duration] | 指定した座標をタップします。任意で長押し時間を指定できます |
d <x> <y> | ダブルタップします |
t <x1> <y1> f <x2> <y2> [duration] | (x1,y1) から (x2,y2) へスワイプします |
drag <x1> <y1> <x2> <y2> [holdDuration] [moveDuration] | ドラッグアンドドロップ: (x1,y1) を長押ししてから (x2,y2) へゆっくり移動します。リストの並べ替えやドラッグアンドドロップの対象に使用します |
mt [x1 y1, ...] dur [x1 y1, ...] dur ... | マルチタッチのシーケンス。各 [...] キーフレームはタッチ位置(x y)を列挙します。各ブロックの後の duration は次のキーフレームへの移動時間です。最後のブロックでは、指を離すまでの保持時間になります。指は、そのスロットが空のカンマ項目(例: [, x y])になったとき または フレームの項目数がその指のインデックスより少なくなったときに終了します。どちらも同じ意味です。離した後に後のキーフレームで再び現れる指は、新しいタップを開始します。 |
b h/p/u/d [duration] | ハードウェアボタン: h=ホーム、p=電源、u=音量アップ、d=音量ダウン |
b c/s/a [duration] | watchOS のみ。 c=Digital Crown の押下、s=サイドボタン、a=Action ボタン(一部のデバイスのみ) |
sender keyboard kbd <text> | テキストを入力します。チェーン内の最後のコマンドでなければなりません — kbd より後のすべての内容はそのまま(複数のスペースも保持して)取得されます。特殊文字には \u{XXXX} Unicode エスケープを使用します: \u{000A}(リターン/改行)、\u{0009}(タブ) |
w duration | 何もせずに指定した時間だけ待機します |
orientation faceDown/faceUp/landscapeLeft/landscapeRight/portrait/portraitUpsideDown | デバイスの向きを設定します(iOS のみ) |
c <rotations> | watchOS のみ。 Digital Crown を回転させます。符号で方向を指定し、1.0 = 1 回転全体 |
r up/down/left/right/select/menu/playpause/home | tvOS のみ。 Siri Remote のボタンを押してフォーカスを移動したり、選択したり、ホーム画面に移動したりします |
例:
"t 100 200"- (100, 200) をタップ"d 200 300"- (200, 300) をダブルタップ"t 200 600 f 200 200 0.3"- 上へスワイプ(下のコンテンツまでスクロール)"t 200 200 f 200 600 0.3"- 下へスワイプ(上のコンテンツまでスクロール)"drag 100 300 100 100"- デフォルトの時間で (100,300) から (100,100) へドラッグアンドドロップ"drag 100 300 100 100 0.5 1.5"- 0.5 秒の保持、1.5 秒の移動でドラッグアンドドロップ"mt [100 200] 0.5 [100 200] 1.0 [300 400] 0.2"- ドラッグ: (100,200) で 0.5 秒保持し、(300,400) へ 1.0 秒かけて移動し、0.2 秒保持してから離します"mt [100 300, 300 300] 0.5 [175 300, 225 300] 0.5"- 2 本指のピンチ: 両方の指が 200px 離れた位置から始まり、互いに近づきます"b h"- ホームボタンを押す"b h b h"- ホームボタンを 2 回押してアプリスイッチャーへ移動"b h w 0 b h"- デバイスをスリープ解除してロック解除(パスコードなしのデバイスのみ)"b c"- watchOS: Digital Crown を押す"b s"- watchOS: サイドボタンを押す"b a"- watchOS: Action ボタンを押す(一部のデバイスのみ)"sender keyboard kbd hello world"- スペースを含むテキストを入力"sender keyboard kbd hello world"- 複数のスペースを保持してテキストを入力"sender keyboard kbd submit\u{000A}"- テキストを入力してから Return/送信を押す"w 0.3"- 0.3 秒待機"orientation landscapeLeft"- デバイスを横向きに回転"c 1.0"- watchOS: Digital Crown を 1 回転全体回す(例: リストをスクロール)"c -0.5"- watchOS: クラウンを逆方向に半回転回す"r down"- tvOS: フォーカスを下へ移動"r select"- tvOS: フォーカスされている要素で Select を押す"r home"- tvOS: ホーム画面へ移動
標準サブエージェントワークフロー
いかなる操作の前にも、必ず階層(およびスクリーンショット)をキャプチャして読み取ってください。いかなる操作の後にも、再度キャプチャして結果を検証してください。複雑なコンポーネント(トグルやスイッチなど)については、ネストされた要素(Switch や Slider など)を確認してください。近くの要素が実際のコントロールに対応している場合があります。完了したら、調査結果をメインエージェントに報告してください。
- 操作せずにキャプチャするには、空の interactionCommand を指定して DeviceEventSynthesize を使用します。
- スクリーンショットだけから位置を推測しないでください。階層の hitPoint 座標を使用してください。スクリーンショットからの推定は、hitPoint を試して失敗した後のフォールバックにすぎません。
- 確信が持てない場合やサムネイルの解像度が不十分な場合は、フルサイズのスクリーンショットを分析してください。
tvOS(Apple TV)
tvOS はフォーカスベースです。タッチスクリーンが存在しないため、座標によるタップやスワイプは適用できません。一度にちょうど 1 つの要素がフォーカスされ、現在フォーカスされているものだけをアクティブ化できます。代わりに Siri Remote で操作してください。
- 階層を読み取り、フォーカス可能なすべての要素と、どれが
Focusedとマークされているかを確認します。 r up/r down/r left/r rightでフォーカスをターゲット方向へ移動し、r selectでアクティブ化します。戻るにはr menuを使用します。- 複数回の押下を 1 つのコマンドに連結し、キャプチャは 1 回だけ行ってください。毎回の押下後にキャプチャするのではなく、そうしてください。階層には要素の順序がリストされているので、ターゲットまでのステップ数を計算してまとめて送信します。たとえば
r right r right r rightのようにしてから、キャプチャしてフォーカスが目的の場所に移動したことを確認します。
タイミングとリトライ
- アプリの起動: セッションを開始した後、アプリの読み込みに数秒かかる場合があります。階層をキャプチャし、操作する前に意味のある UI 要素があることを確認してください。階層がほぼ空であるか起動画面が表示されている場合は、続行する前にもう一度キャプチャしてください。
- 操作後: タップやスワイプで期待どおりの変化が得られない場合は、階層を再キャプチャし、操作を 1 回リトライしてください(アニメーション中に要素が移動した可能性があります)。1 回リトライしても失敗する場合は、無限にリトライせず、失敗を報告してください。
- 読み込み状態: 階層にスピナーや読み込みインジケーターが表示されている場合は、少し待ってからもう一度キャプチャしてください。まだ読み込み中の要素とは操作しないでください。
- パフォーマンス: 処理を遅くする可能性のある待機遅延を追加しないでください。ツールはアニメーションが完了すると完了するように設計されています。
成功と失敗の判断
検証する際は、次のカテゴリを区別してください。
- 機能バグ(常に報告): 要素がタップに反応しない、ナビゲーションが誤った画面へ進む、クラッシュ、データが表示されない、期待される UI 要素が欠落している。
- 視覚/レイアウトバグ(常に報告): テキストの重なり、ラベルの切り詰め、画面外にレンダリングされた要素、誤った色、崩れた配置。
- 一時的な状態(バグとして報告しない): 読み込みスピナー、短いアニメーション、キーボードの表示/非表示。遷移が完了した後にもう一度キャプチャしてください。
- 予期しない終了(常に報告): クラッシュ、アプリケーションの終了。特定するには、プロセス ID を追跡し、プロセスの標準出力をキャプチャしてください。
- 期待される動作(バグとして報告しない): プレースホルダーテキスト付きの空の状態、フォームが不完全なときの無効化されたボタン、権限ダイアログ。
エラー処理
- アプリケーションが表示されない場合は、デバイスが遅いことが原因の可能性があるため、1 回リトライしてください。
- タップ対象が不明確な場合は、正しい hitPoint 座標について階層データを再読み取りしてください。
- 実行時ログを調査してトラブルシューティングできます。タイミングのバグが疑われる場合は、関連するコードに一時的に
printステートメントを追加すると問題の診断に役立つ可能性があることをメインエージェントに提案してください。 - 問題は詳細と提案を添えてメインエージェントに報告してください。