Agent skill

mobile-automation

MCP (dart-mcp + Marionette) を使ったFlutterアプリのE2E自動化・UI検証ガイド。シミュレーターでのUI動作確認、モックプレビュー検証、Bridge経由のE2Eテスト、スクリーンショット撮影など、アプリの動作検証が必要なときに使う。「動作確認して」「UIを検証して」「E2Eテスト」「シミュレーターで確認」「モックで確認」と言われたときや、UI変更後の検証フェーズで使用すること。

Stars 572
Forks 39

Install this agent skill to your Project

npx add-skill https://github.com/K9i-0/ccpocket/tree/main/.claude/skills/mobile-automation

SKILL.md

Mobile Automation

dart-mcp と Marionette MCP を使ったFlutterアプリのUI検証・E2E自動化ガイド。

デフォルト設定

特別な指示がない限り、以下をデフォルトとして使う:

  • デバイス: iOSシミュレーター(flutter devices で確認し、iPhone Simulator を選択)
  • Bridge ポート: 8766(テスト用。本番の8765と分離してテストできる)
  • プロジェクトルート: リポジトリルート(git rev-parse --show-toplevel で取得)
  • アプリルート: <プロジェクトルート>/apps/mobile

ユーザーが実機やポート8765を指定した場合はそちらに従う。

サブエージェント活用

E2E検証は e2e-verifier サブエージェント に委譲すると効率的。独立したコンテキストで検証するため、実装バイアスなく客観的に動作を確認できる。

Agent tool で e2e-verifier サブエージェントを起動:

subagent_type: e2e-verifier

プロンプト:
---
アプリが起動済みです。以下の検証を実施してください。

## 検証内容
[検証したい項目を記述]

## 接続情報
- VM Service URI: [wsUri]
- PID: [pid]

日本語で回答してください。
---

使い分け:

  • 単純なUI確認(要素の存在チェック、1-2画面の確認)→ 直接MCP操作
  • 包括的なE2E検証(複数画面のフロー、回帰テスト)→ e2e-verifier サブエージェントに委譲

アプリ起動ワークフロー

Step 1: デバイス確認

bash
flutter devices

出力からシミュレーターのデバイスIDを確認する(例: 1A2B3C4D-5E6F-...)。

Step 2: アプリ起動

mcp__dart-mcp__launch_app
  root: <アプリルートの絶対パス>
  target: lib/main.dart
  device: <シミュレーターのデバイスID>

返り値の pid を控える(以降の全ステップで必要)。

Step 3: 待機

5秒待機する。 Xcodeビルド + シミュレーターへのデプロイが完了するまで待つ必要がある。初回ビルド時は10秒程度かかることもある。

Step 4: VM Service URI 取得

mcp__dart-mcp__get_app_logs
  pid: <Step 2のpid>

ログ出力から app.debugPort イベントを探し、wsUri を抽出する:

json
"params": { "wsUri": "ws://127.0.0.1:XXXXX/YYYY=/ws" }

wsUri が見つからない場合はビルドがまだ完了していない。5秒待って再度 get_app_logs を呼ぶ。

Step 5: Marionette 接続

mcp__marionette__connect
  uri: <wsUri>

Marionette MCP は自動接続しないため、この手動 connect が必須。省略するとその後のUI操作が全て失敗する。

Step 6: 接続確認

mcp__marionette__get_interactive_elements

UI要素の一覧が返れば接続成功。

CLI vs MCP の使い分け

原則: DTD/VM Service接続が必要な操作はMCP、それ以外はCLI

MCP が必要な操作はアプリのランタイムに接続して情報を取得・操作するもの(起動、停止、ホットリロード、UI操作、ログ取得など)。一方、ビルドツールや静的解析のようにアプリのランタイムに依存しない操作はCLIの方が速くて確実。

MCP 操作一覧

操作 ツール MCP名
アプリ起動 Dart MCP launch_app
アプリ停止 Dart MCP stop_app
アプリログ取得 Dart MCP get_app_logs
DTD接続 Dart MCP connect_dart_tooling_daemon
ホットリロード Dart MCP hot_reload
ホットリスタート Dart MCP hot_restart
ウィジェットツリー Dart MCP get_widget_tree
ランタイムエラー Dart MCP get_runtime_errors
VM Service接続 Marionette connect
UI要素一覧 Marionette get_interactive_elements
タップ Marionette tap
ダブルタップ Marionette double_tap
長押し Marionette long_press
テキスト入力 Marionette enter_text
スワイプ/ドラッグ Marionette swipe
ピンチズーム Marionette pinch_zoom
戻る操作 Marionette press_back_button
スクロール Marionette scroll_to
アプリログ Marionette get_logs
スクリーンショット Marionette take_screenshots
カスタム拡張一覧 Marionette list_custom_extensions
カスタム拡張呼び出し Marionette call_custom_extension

CLI 操作一覧

操作 コマンド
デバイス一覧 flutter devices
テスト実行 cd apps/mobile && flutter test
静的解析 dart analyze apps/mobile
フォーマット dart format apps/mobile
依存関係 cd apps/mobile && flutter pub get

ツール優先順位

UI検証時は以下の順序で使う。スクリーンショットはトークンを大量に消費するため、テキストベースの検証を優先する:

  1. get_interactive_elements — 最優先。画面上のタップ可能なボタン・入力欄の一覧を取得。画面遷移後は必ずこれを呼んで現在の状態を確認する
  2. get_logs — エラー確認。"ERROR", "Exception" でフィルタして問題がないか確認
  3. tap / enter_text / scroll_to — 基本UI操作。key指定を優先し、textやcoordinatesは代替手段
  4. double_tap / long_press / swipe / pinch_zoom / press_back_button — ジェスチャー系。通常操作で足りないときに使う
  5. list_custom_extensions / call_custom_extension — アプリ固有の拡張操作。画面遷移ショートカットや内部トグル向け
  6. take_screenshots — 最後の手段。レイアウトやビジュアルの確認が本当に必要な場合のみ。1セッションで3-5枚を目安に

Widget Keys 一覧

各画面のインタラクティブ要素に付与されたValueKey。tapenter_text では key 指定が最も確実。

Session List Screen (ホーム画面)

  • session_list — セッション一覧ListView
  • search_field — セッション検索入力
  • search_button — 検索トグルボタン
  • mock_preview_button — モックシナリオギャラリーを開く (AppBar)
  • gallery_button — ギャラリー画面へ遷移
  • refresh_button — セッション一覧リフレッシュ
  • disconnect_button — サーバー切断
  • new_session_fab — 新規セッション作成FAB
  • load_more_button — セッション追加読み込み

接続フォーム (Connect Form)

  • server_url_field — サーバーURL入力
  • api_key_field — APIキー入力
  • connect_button — 接続ボタン
  • scan_qr_button — QRスキャンボタン

Chat Input Bar

  • message_input — メッセージテキスト入力
  • send_button — メッセージ送信
  • voice_button — 音声入力
  • stop_button — ストリーミング停止
  • slash_command_button — スラッシュコマンドメニュー

Approval Bar (承認バー)

  • approve_button — ツール実行承認
  • reject_button — ツール実行拒否
  • approve_always_button — Always承認モード
  • view_plan_header_button — プランヘッダー表示
  • plan_feedback_input — プランフィードバック入力
  • clear_context_chip — コンテキストクリアチップ

Message Action Bar

  • copy_button — メッセージコピー
  • plain_text_toggle — プレーンテキスト表示切替
  • share_button — メッセージ共有

Plan Card & Detail Sheet

  • plan_edited_badge — プラン編集済みバッジ
  • view_full_plan_button — プラン詳細シート表示
  • plan_edit_toggle — プラン編集モード切替
  • plan_edit_field — プラン編集テキスト入力
  • plan_edit_cancel — プラン編集キャンセル
  • plan_edit_apply — プラン編集適用

New Session Sheet

  • dialog_project_path — プロジェクトパス選択
  • dialog_permission_mode — パーミッションモード選択
  • dialog_worktree — Worktreeトグル
  • dialog_worktree_branch — Worktreeブランチ入力
  • dialog_start_button — セッション開始ボタン

Chat Screen

  • status_indicator — ステータスインジケーター
  • session_switcher — セッション切替

Mock UI テスト (Bridge不要)

Bridge Server なしでUIの見た目と挙動を確認できる。AppBarの「Mock Preview」ボタンから10種のモックシナリオにアクセスできる。

ワークフロー

1. アプリ起動 (上記ワークフロー)
2. get_interactive_elements → ホーム画面の要素確認
3. tap key: "mock_preview_button" → モックギャラリーを開く
4. tap text: "<シナリオ名>" → 目的のシナリオを選択
5. get_interactive_elements → チャットUIの要素確認
6. get_logs → エラーがないか確認

モックシナリオ一覧

# 名前 検証ポイント
1 Approval Flow approve/reject/always_approve ボタン表示
2 AskUserQuestion 質問テキスト + 選択肢オプション表示
3 Multi-Question 複数質問の同時表示 + multiSelect
4 Image Result 画像参照のツール結果表示
5 Streaming 文字単位のストリーミング表示
6 Thinking Block 折りたたみ可能な思考コンテンツ
7 Plan Mode EnterPlanMode → ExitPlanMode フロー
8 Subagent Summary Taskツール + 圧縮結果表示
9 Error エラーメッセージ表示
10 Full Conversation System → Assistant → Tool → Result 全体

クイックテスト推奨: Approval Flow, Streaming, Plan Mode(主要UIパターンをカバー)

E2E テスト (Bridge必要)

Bridge Server を経由して実際のClaude Code / Codexセッションでの動作を検証する。

ワークフロー

bash
# Step 1: テスト用 Bridge 起動(ポート8766、本番8765に影響なし)
cd <プロジェクトルート> && BRIDGE_PORT=8766 npm run bridge &

# Step 2: アプリ起動(上記「アプリ起動ワークフロー」に従う)

# Step 3: サーバー接続
#   get_interactive_elements で接続フォームを確認
#   enter_text key: "server_url_field" text: "ws://localhost:8766"
#   tap key: "connect_button"

# Step 4: セッション作成
#   tap key: "new_session_fab"
#   dialog_project_path でパスを選択
#   tap key: "dialog_start_button"

# Step 5: メッセージ送信 & 検証
#   enter_text key: "message_input" text: "<テスト用プロンプト>"
#   tap key: "send_button"
#   get_interactive_elements で応答UIを確認
#   承認バーが表示されたら approve/reject の動作を検証

# Step 6: クリーンアップ
#   mcp__dart-mcp__stop_app (pid指定)
#   lsof -ti :8766 | xargs kill

Bridge接続時の注意

  • テスト用Bridge(8766)を使うことで本番Bridge(8765)に接続しているiPhoneアプリに影響を与えない
  • Bridgeが起動していない状態で接続しようとすると「Connection refused」になる。Bridgeの起動を先に確認すること

トラブルシューティング

"Connection refused" (Marionette接続失敗)

  • 原因: アプリが完全に起動していない、またはwsUriが不正
  • 対策: launch_app 後に5秒以上待ってから get_app_logs でwsUriを再取得。wsUriが取得できない場合はビルド中なのでさらに待つ

"Widget not found" (タップ失敗)

  • 原因: ウィジェットが未描画、キー名の誤り、または画面外にある
  • 対策:
    1. get_interactive_elements で現在表示中の要素を確認
    2. 上記Widget Keys一覧でキー文字列のスペルを確認
    3. scroll_to で画面外のウィジェットを表示させる

アプリクラッシュ

  • 対策:
    1. get_logs でスタックトレースを確認
    2. stop_applaunch_app で再起動
    3. 再起動後は Step 3 (wsUri取得) からやり直す

Marionette Tips

  • tap: key > text > coordinates の優先順位で指定する。keyが最も安定
  • enter_text: key パラメータでテキストフィールドを指定する
  • get_logs: Marionette接続後のログのみ取得。起動時のログは get_app_logs (dart-mcp) で取得
  • hot_reload: UIの微調整に便利。ただしconst定義の変更やdependency更新には hot_restart が必要
  • long_press: InkWell.onLongPressGestureDetector.onLongPress に繋がる。CC Pocket の recent/running session card では長押しでアクションシートを開ける
  • long_press の検証対象は実画面を優先する。ストアスクリーンショット用のモック Session ListonLongPressRecentSession / onLongPressRunningSession が no-op のため、長押し挙動の確認には使えない
  • swipe: SlidableDismissible の両方で有効。CC Pocket では recent session card のアーカイブ action pane 表示や、Git画面の stage / unstage / revert に使える
  • swipe 実行後は必ず get_interactive_elements を再取得して、action pane が開いたか、対象セルが横移動したかを確認する
  • クリップボード系アクションは Marionette から直接読み出せない。copy_resume_command のような機能は、長押しでシートが出ること、対象項目をタップできること、シートが閉じることをもってUIフロー確認とする
  • recent session card は Slidable の key が要素一覧に出るので、swipe(key: "recent_session_<id>", direction: "left") のように key 指定で狙うのが安定
  • 長押し対象に key が無い場合は、まず get_interactive_elements で bounds を確認し、long_press(coordinates: {x, y}) を使うと成功率が高い

Dart MCP Tips

  • launch_app: root は絶対パスで指定。返り値のPIDは必ず保存する
  • list_devices: 起動中のデバイスのみ表示される
  • stop_app: launch_app で取得したPIDを渡す

クリーンアップ

検証完了後は必ずリソースを解放する:

1. mcp__dart-mcp__stop_app (pid指定) → アプリ停止
2. Bridge実行中なら: lsof -ti :8766 | xargs kill → テスト用Bridge停止

Expand your agent's capabilities with these related and highly-rated skills.

K9i-0/ccpocket

triage

GitHub Issue・PRのトリアージ。番号を渡すと、要望の要約・実現難易度・既存機能との重複チェック・対応判断を調査してレポートする。Issue/PRの番号が出てきたとき、トリアージ、優先度判断、対応判断と言われたときに使用する。

572 39
Explore
K9i-0/ccpocket

self-review

タスク完了前のセルフレビュー。Claude subagentで別コンテキストから客観的にコード変更を検証。

572 39
Explore
K9i-0/ccpocket

release-bridge

Bridge Server のリリース(バージョンbump + CHANGELOG + タグ → GH Actions で npm publish)

572 39
Explore
K9i-0/ccpocket

flutter-upgrade

Flutter SDKバージョンアップグレード対応。新バージョンのリリースノート・Breaking Changes調査、コードベース影響分析、mise/CI/Shorebird含むプロジェクト全体の対応タスクリスト作成と実行。「Flutterアップグレード」「Flutter X.Y.Zがリリースされた」「Flutter最新化」「Flutter更新」と言われたとき、またはFlutterの新バージョンについて言及されたときに使用する。

572 39
Explore
K9i-0/ccpocket

flutter-ui-design

Flutter UI実装のアーキテクチャ規約・コンポーネント分割・状態管理ガイド(Bloc/Cubit版)

572 39
Explore
K9i-0/ccpocket

test-bridge

Bridge Server (TypeScript) のテスト実行・型チェック・テスト記述ガイド

572 39
Explore

Didn't find tool you were looking for?

Be as detailed as possible for better results