harmonyos-device-automation について
スクリーンショットと自然言語コマンドで HarmonyOS NEXT デバイスを操作する Midscene スキルです。HDC 経由でデバイスにアクセスし、AI エージェントが UI 操作を検証します。
主な機能
- 01自然言語による UI 操作
- 02画面の撮影と分析
- 03画面状態のアサーション
- 04一時的な UI の記録
- 05HDC コマンドとレポート
活用シーン
- 01HarmonyOS アプリで複数手順を実行
- 02QA で表示状態を確認
- 03一時的な通知や画面遷移を記録
- 04HDC コマンドでデバイス情報を確認
MCP 対応
HarmonyOS コマンドラインの各コマンドは MCP ツールに対応し、AI エージェントがスクリーンショットを基にデバイスを操作します。
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ web-infra-dev/ midscene-skills --skill harmonyos-device-automationインストール後、Claude Code で/harmonyos-device-automationを入力して読み込まれたか確認します。
詳細
HarmonyOS デバイスの自動化
重要なルール — 違反するとワークフローが破損します:
- midscene コマンドをバックグラウンドで実行しないでください。 各コマンドは同期的に実行し、出力(特にスクリーンショット)を確認してから次の操作を決めてください。バックグラウンド実行は、スクリーンショットを確認・分析して操作するループを妨げます。
- 一度に実行する midscene コマンドは1つだけにしてください。 前のコマンドが完了するのを待ち、スクリーンショットを確認してから次の操作を決めてください。複数のコマンドを連結して実行しないでください。
- 各コマンドの完了に十分な時間を確保してください。 Midscene のコマンドでは AI 推論と画面操作が行われるため、一般的なシェルコマンドより時間がかかることがあります。通常、コマンドには約1分かかります。複雑な
actコマンドでは、さらに時間がかかる場合があります。
npx -y @midscene/harmony@1 を使って HarmonyOS NEXT デバイスを自動化します。各 CLI コマンドは MCP ツールに直接対応します。AI エージェントであるあなたが、スクリーンショットに基づいて実行する操作を判断します。
act でできること
HarmonyOS 上で1回の act 呼び出しを行うと、Midscene は現在表示されている画面をもとに、タップ、ダブルタップ、長押し、テキスト入力、テキストの消去、スクロール、項目のドラッグ、キーの押下、戻る、ホーム、最近使ったアプリなどのシステムナビゲーションを実行できます。HarmonyOS の基盤となる自動化レイヤーがマルチタッチ入力を公開していないため、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。
モデルが設定されていない場合は、ユーザーに設定を依頼してください。対応プロバイダーについては、モデルの設定 を参照してください。
HDC のセットアップ
HDC(HarmonyOS Device Connector)をインストールし、アクセスできる状態にする必要があります。一般的なセットアップ方法:
- DevEco Studio からインストールします
- または、
HDC_HOME環境変数に HDC ディレクトリを指定します
HDC が動作することを確認します:
hdc version
hdc list targets
コマンド
デバイスに接続する
npx -y @midscene/harmony@1 connect
npx -y @midscene/harmony@1 connect --deviceId 0123456789ABCDEF
アプリまたは URL を起動する
タスクの残りの操作に進む前に開始状態を確実に整えたい場合は、専用の起動ステップを使用します:
npx -y @midscene/harmony@1 launch --uri com.huawei.hmos.settings
npx -y @midscene/harmony@1 launch --uri com.huawei.hmos.camera
npx -y @midscene/harmony@1 launch --uri https://www.example.com
HarmonyOS のシェルコマンドを直接実行する
画面上の UI 操作では適切に表現できない、より低レベルのデバイス制御が必要な場合に使用します:
npx -y @midscene/harmony@1 runhdcshell --command "hidumper -s RenderService -a screen"
これは、接続済みデバイス上の hdc shell に転送されます。実際には、基盤となるコマンドは hdc -t <deviceId> shell hidumper -s RenderService -a screen です。
スクリーンショットを撮る
npx -y @midscene/harmony@1 take_screenshot
スクリーンショットを撮った後、保存された画像ファイルを読み込み、次の操作を決める前に現在の画面の状態を確認してください。
操作を実行する
デバイスを操作して結果を取得するには act を使用します。タップ、入力、スクロール、スワイプ、待機、ナビゲーションなど、すべての UI 操作を内部で自律的に処理します。そのため、細かい手順に分割するのではなく、複雑で高レベルなタスクをまとめて指示してください。自然な言葉で、何をしたいのか、どのような結果を望むのかを説明します:
# specific instructions
npx -y @midscene/harmony@1 act --prompt "type hello world in the search field and press Enter"
npx -y @midscene/harmony@1 act --prompt "long press the message bubble and tap Delete in the popup menu"
# or target-driven instructions
npx -y @midscene/harmony@1 act --prompt "open Settings and navigate to Wi-Fi settings, tell me the connected network name"
現在の画面状態をアサートする
assert を使用して、現在の画面が自然言語で指定した条件を満たしているか確認します。UI 操作は行わず、表示中の画面状態をチェックし、アサーションが真の場合にのみ成功します。検証、QA チェック、act 実行後の最終状態確認に使用します。
npx -y @midscene/harmony@1 assert --prompt "there is a login button visible"
npx -y @midscene/harmony@1 assert --prompt "the settings screen shows Wi-Fi and Bluetooth options"
npx -y @midscene/harmony@1 assert --deviceId 0123456789ABCDEF --prompt "the app shows a successful login message"
デフォルトでは、アサーションが失敗すると AI が生成した理由をスローします。代わりにカスタムエラーメッセージをスローするには --message を渡します。QA や CI のログに意図した結果を表示する場合に便利です。
npx -y @midscene/harmony@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/harmony@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/harmony@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/harmony@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/harmony@1 record start \
--device-id 0123456789ABCDEF \
--output ./submission-observation.json
# Terminal 2, while Terminal 1 records
npx -y @midscene/harmony@1 act --device-id 0123456789ABCDEF \
--prompt "tap the Submit button"
# Send Ctrl+C to Terminal 1 and wait for the saved-path message, then assert
npx -y @midscene/harmony@1 assert --device-id 0123456789ABCDEF \
--record ./submission-observation.json \
--prompt "a success toast appeared during submission"
record start に対象指定フラグ、キャプチャフラグ、--output を渡してから、Recording. Press Ctrl+C to stop and save. が表示されるまで待ちます。レコーダーは専用ターミナルでフォアグラウンドプロセスとして実行し、シェルの & は追加しないでください。手動または別のターミナルから操作を行い、レコーダーに Ctrl+C を送信してから、保存先のパスが表示されるまで待ってアサートします。HarmonyOS の記録では、スクリーンショットを定期的に撮影します。任意のキャプチャフラグは --interval-ms、--max-frames、--watchdog-ms です。--max-frames はサンプリングするフレーム数を制限し、マニフェストには代表的な最終フレームがさらに 1 枚含まれる場合があります。デフォルトではウォッチドッグが 5 分後に記録を確定して保存します。--watchdog-ms 0 を指定すると、この安全制限が無効になります。出力は JSON マニフェストと、その隣にある <name>.frames 画像ディレクトリであり、エンコードされた動画やアーカイブではありません。マニフェストには相対パスの JPEG/PNG ファイルが含まれ、base64 の画像データは含まれません。JSON ファイルと画像ディレクトリは一緒に保管するか、まとめて移動し、JSON のパスを assert --record に渡します。現在の画面だけが対象の場合は、--record を指定せず通常の assert を使用します。
正確なターゲット指定に参照画像を使用する
ユーザーがスクリーンショット、アイコン、ロゴ、参照画像を提供し、見た目を正確に一致させたい場合は、汎用的な act --prompt よりも tap --locate を優先します。--locate には JSON を渡します。prompt はターゲットを説明し、images は名前付きの参照画像を指定します。画像 URL にモデルが直接アクセスできない場合は、convertHttpImage2Base64: true が便利です。
npx -y @midscene/harmony@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/harmony@1 disconnect
レポートファイルを利用する
人が最初に読む場合は、生成された HTML レポートを推奨します。各操作の手順ごとの実行詳細と再生動画が含まれているため、何が起きたのかを把握し、問題をトラブルシューティングしやすくなります。
別のスキルやツールでレポートを利用する場合は、まず同じプラットフォームの CLI パッケージに含まれる report-tool で変換してください。LLM ベースのワークフローには Markdown を推奨します。プログラムでレポートを処理する必要がある場合は JSON を使用します。
npx -y @midscene/harmony@1 report-tool --action to-markdown --htmlPath ./midscene_run/report/.../index.html --outputDir ./output-markdown
npx -y @midscene/harmony@1 report-tool --action split --htmlPath ./midscene_run/report/.../index.html --outputDir ./output-data
ワークフローのパターン
CLI コマンドは呼び出し間で状態を保持しないため、次のパターンに従います。
- 接続してセッションを確立します
- 対象のアプリを起動してスクリーンショットを撮影し、現在の状態を確認します。アプリが起動しており、画面上に表示されていることを確認してください。
actを使用して目的の操作またはターゲット指定の手順を実行し、操作を実行します。操作後の画面状態にはassertを使用します。一時的な状態を扱うワークフローでは、専用ターミナルでrecord start --output ...を実行したままにし、Ctrl+C で停止してからassert --recordを使用します。- 完了したら切断します
ベストプラクティス
- 操作する前に、対象アプリをフォアグラウンドに表示します:接続後、専用のランチャー(例:
npx -y @midscene/harmony@1 launch --uri <bundleName>)を使用し、スクリーンショットを撮ってアプリが実際にフォアグラウンドに表示されていることを確認します。HarmonyOS アプリでは異なるエントリーアビリティが宣言されている場合があるため、推測したアビリティ名を使ってaa startを実行しないでください。画面で確認してから、このスキルを使って UI の自動化を進めてください。 - UI 要素を具体的に指定します:曖昧な説明ではなく、明確で具体的な詳細を伝えてください。「トグル」ではなく「右側にある Wi-Fi の切り替えスイッチ」と指定します。
- 可能な限り位置を説明します:位置を説明して、対象となる要素を特定しやすくします(例:「右上の検索アイコン」「リストの3番目の項目」)。
- バックグラウンドでは実行しないでください:すべての midscene コマンドは同期実行する必要があります。バックグラウンド実行すると、スクリーンショットの取得・分析・操作のループが機能しなくなります。
- 関連する操作は1つの
actコマンドにまとめます:同じアプリ内で連続して操作するときは、別々のコマンドに分けず、1つのactプロンプトにまとめてください。たとえば、「設定を開き、Wi-Fi をタップしてオンにする」は3つではなく、1回のact呼び出しにします。これにより、やり取りの回数と不要なスクリーンショットの取得・分析を減らし、大幅に高速化できます。 - 適切な検証方法を選びます:現在の画面には
assert --prompt "..."を使用します。トースト、バナー、アニメーション、画面遷移の場合は、専用のターミナルでrecord start --output ...を実行し、操作を行ってから Ctrl+C で録画を停止します。保存先のメッセージが表示されるまで待ち、その後、生成されたファイルをassert --recordに渡します。 - 完了後にレポートファイルをまとめます:自動化タスクを終えたら、すべてのレポートファイル(スクリーンショット、ログ、出力ファイルなど)を収集して、ユーザー向けに要約します。実行した内容、生成されたファイル、その保存場所を明確にまとめ、ユーザーが結果を簡単に確認できるようにします。
- 参照画像がある場合は
tap --locateを優先します:ユーザーがスクリーンショット、アイコン、ロゴを共有し、その画像と完全に一致する対象を指定している場合は、act --promptだけに頼らず、{ "prompt": "...", "images": [...] }のようなマルチモーダルなlocateJSON オブジェクトを指定してtap --locateを使用します。
例 — アプリの起動と操作:
npx -y @midscene/harmony@1 connect
npx -y @midscene/harmony@1 launch --uri com.huawei.hmos.settings
npx -y @midscene/harmony@1 take_screenshot
npx -y @midscene/harmony@1 act --prompt "scroll down the settings list and tap About device"
npx -y @midscene/harmony@1 take_screenshot
npx -y @midscene/harmony@1 disconnect
例 — フォームの操作:
npx -y @midscene/harmony@1 act --prompt "fill in the username field with 'testuser' and the password field with 'pass123', then tap the Login button"
npx -y @midscene/harmony@1 take_screenshot
HarmonyOS の一般的なバンドル名
| アプリ | バンドル名 |
|---|---|
| 設定 | com.huawei.hmos.settings |
| カメラ | com.huawei.hmos.camera |
| ギャラリー | com.huawei.hmos.photos |
| カレンダー | com.huawei.hmos.calendar |
| 時計 | com.huawei.hmos.clock |
| 電卓 | com.huawei.hmos.calculator |
| ブラウザー | com.huawei.hmos.browser |
| 天気 | com.huawei.hmos.weather |
精度の向上(Deep Locate / Deep Think)
Midscene がタスクの実行に苦戦する場合に役立つ、2つの任意のグローバルフラグがあります。コマンド内のどこにでも(サブコマンドの前後どちらでも)指定できます。一度設定すると、該当する操作でデフォルトで使用されるため、呼び出しごとにパラメーターを渡す必要はありません。
--deep-locate— 対象の要素を特定するために、視覚的な推論をもう1回行います。操作する位置がずれる場合に使用してください。tap --locateやact内での要素の特定など、要素の位置を特定するすべての操作に適用されます。--deep-think— より深い推論(豊富なコンテキストとサブゴールへの分解)を使ってactの計画を立てます。複雑な複数ステップのact指示に使用してください。影響するのは計画のみです。
どちらも実行速度をわずかに犠牲にして結果を改善します。併用することもできます。
# more accurate element location (helps act's internal locating too)
npx -y @midscene/harmony@1 act --deep-locate --prompt "tap the small back arrow in the top-left corner"
# deeper planning for a complex, multi-step act
npx -y @midscene/harmony@1 act --deep-think --prompt "scroll the settings list, open About device, and find the system version"
# combine both
npx -y @midscene/harmony@1 act --deep-locate --deep-think --prompt "open Settings, go to Wi-Fi, and toggle it on"
トラブルシューティング
| 問題 | 解決策 |
|---|---|
| HDC が見つからない | DevEco Studio 経由でインストールするか、HDC_HOME 環境変数を設定してください。 |
| デバイスが一覧に表示されない | USB 接続を確認し、「開発者向けオプション」で USB デバッグが有効になっていることを確認してから、hdc list targets を実行してください。 |
| コマンドがタイムアウトする | デバイスの画面がオフになっているか、ロックされている可能性があります。デバイスを起動してロックを解除してください。 |
| API キーのエラー | .env ファイルに MIDSCENE_MODEL_API_KEY=<your-key> が含まれていることを確認してください。モデルの設定を参照してください。 |
@midscene/* の依存関係のバージョンが古い | npm ls @midscene/harmony @midscene/core @midscene/shared(または pnpm why @midscene/harmony)でローカルのバージョンを確認してください。npm view @midscene/harmony version、npm view @midscene/core version、npm view @midscene/shared version で最新バージョンと比較してください。必要に応じて、npm i @midscene/harmony@latest @midscene/core@latest @midscene/shared@latest でアップグレードしてください。 |
| 対象のデバイスが違う | 複数のデバイスが接続されている場合は、connect コマンドで --deviceId <id> フラグを使用してください。 |