Skip to content
Back to skills

ios-simulator-automation

ASecurity

Xcode 27 の iOS シミュレータをコマンドと MCP で操作・検証するときの道具の選び方と落とし穴。Device Hub を開かずに済む経路と、開くしかない操作の区別。タップ・スワイプ・撮影・回転・要素ツリーの取得、状態の作り込み、xcodebuildmcp / axe / simctl / devicectl / Device Hub / Xcode MCP の使い分けを扱う。シミュレータで画面を確認したい、タップが効かない、要素の座標が取れない、回転させたい、スクリーンショットを撮りたい、UI 自動操作が不安定、Device Hub を開かずに済ませたい、といったときに使う。

  • 2 stars
  • 0 votes
  • 0 copies
  • 1 view
  • Added September 30, 2026
ai-agentsrustbashnodeci/cd

Works with

  • cli
  • mcp

Security analysis

A100/100

Scanned September 30, 2026

npx -y skills add capsrock/ios-simulator-automation-skill --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of ios-simulator-automation?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for ios-simulator-automation
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/capsrock-ios-simulator-automation/badge)](https://www.skillsdirectory.com/skills/capsrock-ios-simulator-automation)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: ios-simulator-automation
description: Xcode 27 の iOS シミュレータをコマンドと MCP で操作・検証するときの道具の選び方と落とし穴。Device Hub を開かずに済む経路と、開くしかない操作の区別。タップ・スワイプ・撮影・回転・要素ツリーの取得、状態の作り込み、xcodebuildmcp / axe / simctl / devicectl / Device Hub / Xcode MCP の使い分けを扱う。シミュレータで画面を確認したい、タップが効かない、要素の座標が取れない、回転させたい、スクリーンショットを撮りたい、UI 自動操作が不安定、Device Hub を開かずに済ませたい、といったときに使う。
---

# iOS シミュレータの自動操作

シミュレータを操作する道具は複数あり、**同じことができる道具でも、動くものと動かないものが混ざっている**。
何を使うかだけでなく、**なぜそれを選んだのか**を区別して持っておく。壊れているから避けているのか、
それが本来の道なのかが分からないと、下の層が直ったときに見直せない。

## 対象バージョン

**Xcode 27.0 および 27.1 beta / iOS 27.0 / 27.1 のシミュレータ / macOS 26**。実測は 2026-09-20。

**Xcode 26 以前には当てはまらない。** 下の背景のとおり、土台ごと入れ替わっている。

複数の Xcode を入れている場合、`xcrun` も MCP も **`xcode-select` が指すほう**を使う。
別バージョンのランタイム(折りたたみ端末など)を触るときは、そのコマンドにだけ
`DEVELOPER_DIR=...` を付ける。

## 背景 — なぜ Xcode 27 で変わったのか

**Xcode 27 で `Simulator.app` が廃止され、`Device Hub` に置き換わった。**
ファイルの位置も `<Xcode>.app/Contents/Developer/Applications/Simulator.app` から
`<Xcode>.app/Contents/Applications/DeviceHub.app` へ移った(bundle id は `com.apple.dt.Devices`)。
27.0 / 27.1 beta とも旧パスに `Simulator.app` は存在しない。

置き換えの中身は**統合**である。Simulator は端末ごとに別ウインドウを開く作りだったが、
Device Hub は左に端末の一覧、右にその詳細という1ウインドウにまとめ、
**シミュレータと実機を同じ画面で扱う。** 回転・撮影・ダークモード・文字サイズ・リサイズ・
実機へのアプリ起動が、すべて同じ場所から行える。

このスキルの内容は、ほぼすべてこの移行から導かれる。

- **`devicectl` がシミュレータも扱うようになった。** `devicectl` はもともと実機用の CLI だったが、
  統合に合わせて拡張された。**`simctl` に無い回転が `devicectl` にあるのはこのため。**
  新しく何かをしたいときは、`simctl` だけでなく `devicectl` も見る
- **既存のツールが軒並み壊れた。** `Simulator.app` のパスや前提に依存していたものが動かなくなり、
  CI やテスト基盤が対応途中にある。このスキルに出てくる「成功と返すのに効かない」たぐいの失敗も、
  **この移行期にあたっているためと考えられる**(Apple の説明があるわけではなく、こちらの推測)。
  だからこそ、回避策には「いつ見直すか」を必ず書く

参考: [Michael Tsai — Xcode 27's Device Hub](https://mjtsai.com/blog/2026/06/25/xcode-27s-device-hub/) /
[Bitrise — WWDC 2026: Device Hub and what it means for CI/CD](https://bitrise.io/blog/post/wwdc-2026-device-hub-and-what-it-means-for-ci-cd)

## Device Hub 経由かどうか

これが最初の分かれ目になる。**Device Hub は画面を占有してユーザーの作業を止めるので、
直接叩ける経路で済むならそちらを使う。**

ただし前提が1つある。**ここに書いた検証はすべて Device Hub が起動している状態で行った。**
Device Hub を終了するとシミュレータも一緒に落ちるため、閉じた状態での可否は確かめていない。
実務上 Device Hub は常に起動しているので、区別が意味を持つのは「GUI を前面に出して人が操作するか」の
一点だと考えてよい。

## 道具の選び方

「経路」は、Device Hub を前面に出して人が操作する必要があるかどうか。

| やりたいこと | 使うもの | 経路 | なぜ | 種別 | 見直す条件 |
|---|---|---|---|---|---|
| タップ(縦向き) | Claude のシミュレータパネル `mcp__Claude_Code_iOS_Simulator__control` の `tap` | 直接 | 確実に効く。手数が少ない | 正道 | — |
| タップ(横向き・確実さ優先) | `axe touch -x -y --down --up` | 直接 | パネルのタップが横向きで届かない。`axe tap` は効かない | **回避策** | axe が上がったら `tap` と横向きのパネルを再試験 |
| 要素の座標・ラベル | `axe describe-ui` | 直接 | 座標を取る唯一の手段。画像から目測するより正確 | 正道 | — |
| 撮影 | `xcrun simctl io <UDID> screenshot` | 直接 | パネルの `screenshot` が `captureFailed` を返す | **回避策** | パネル側が直ったら |
| 回転 | `xcrun devicectl device orientation set` | 直接 | `simctl` に回転が無い。Xcode 27 の正規の手段 | 正道 | — |
| 回転+タップ+階層をまとめて | Xcode MCP の `DeviceInteractionSynthesize` | 直接 | 1回でスクリーンショットと hitPoint 付き階層が返る | 正道 | — |
| 外観・文字サイズ・コントラスト | `xcrun simctl ui` | 直接 | 正規の手段 | 正道 | — |
| 画面の状態づくり | アプリの UserDefaults を直接書く | 直接 | UI 自動操作は取りこぼす。シートが開かない・別の項目に当たる | **回避策** | 入力系が安定したら |
| キー入力 | 人に押してもらう | **Device Hub** | どの経路も届かない(下記) | **回避策** | axe 更新時、iOS / Xcode 更新時 |
| 折りたたみ端末の開閉 | 人に開いてもらう | **Device Hub** | コマンドに対応が無い | **回避策** | `devicectl` にサブコマンドが増えたら |
| 折りたたみ端末の内側へのタップ | 人に押してもらう | **Device Hub** | どの経路も届かない | **回避策** | axe 更新時 |
| 可変ウインドウの幅 | 人に操作してもらう | **Device Hub** | `devicectl device appResize` が非対応で弾かれる | **回避策** | Resizable のデバイスタイプが入ったら再試験 |

## 使ってはいけないもの

### xcodebuildmcp の `tap` / `swipe` / `key_press`

**「成功」と返しても効かない。** 返り値を信用しない。中身は同梱の `axe` を呼んでいるだけで、
その axe が動いていないため。`snapshot_ui` / `describe-ui` が失敗するのも同じ根。

### 同梱の `bundled/axe`

`/usr/local/lib/node_modules/xcodebuildmcp/bundled/axe` は `describe-ui` が失敗する。
**Homebrew 版を使う。**

```bash
brew trust --formula cameroncooke/axe/axe && brew install axe
# → /opt/homebrew/bin/axe
```

版はどちらも 1.8.0 で同じ。brew 版だけ動くのは、`FBSimulatorControl` などのフレームワークを同梱し、
インストール時にローカルで codesign されるため。**版を上げれば直るという話ではない。**

`XCODEBUILDMCP_AXE_PATH` に brew 版を指すと xcodebuildmcp 側も差し替えられるが、
`axe tap` 自体が効かないので `tap` ツールは直らない。

### `axe tap`

効かない。`✓ Tap at (x, y) completed successfully` と返すが画面は変わらない。
**`axe touch -x <x> -y <y> --down --up` を使う。** こちらは縦向き・横向きとも届く。

## キー入力は届かない

`keyboardShortcut` や `onKeyPress` の動作確認は、**この環境では自動化できない。**

| 試したもの | 結果 |
|---|---|
| `axe key <keycode>` | 届かない |
| `axe type "<text>"` | 届かない |
| xcodebuildmcp `key_press` | 届かない(修飾キーも送れない) |
| Xcode MCP `sender keyboard kbd <text>` | 届かない |

入力欄にフォーカスを置いて1文字送っても入らないので、**アプリ側の実装の問題ではない。**
シミュレータの「Simulate Hardware Keyboard」が入っていても変わらない。

検証はユーザーに Device Hub 上で押してもらうか、実機にキーボードを繋いで行う。
**未確認のままコミットするなら、その旨をコミットメッセージに書く。**

## 座標の落とし穴

- **`describe-ui` は画面上の全アプリの階層を返す。** 裏のアプリの座標を拾って誤タップしやすい。
  目的のアプリに絞ってから読む
- **横向きではパネルのタップが届かない。** `axe touch` を使う
- **折りたたみ端末の内側ディスプレイには、どの経路のタップも届かない。** Device Hub 越しのクリックだけ。
  `describe-ui` は内側の座標空間で正しい値を返すのに、注入したタッチは届かない
- **再起動すると向きは縦に戻る。** ユーザーが回したあとに勝手に `shutdown` / `boot` をしない

## Device Hub を開くしかない操作

コマンドに対応が無いのは次の4つだけ。ほかは全部、直接叩ける経路がある。

- **キーボードの接続**(`Device > Keyboard`)**とキー入力**
- **折りたたみ端末の開閉**
- **可変ウインドウ**(`Enter Resize Mode`)。`devicectl device appResize` は
  `Resizable App Management` 非対応で弾かれ、名前に `Resizable` を含むディスプレイが要る。
  そのデバイスタイプが入っていない環境では使えない
- **折りたたみ端末の内側へのクリック**

いずれも人にやってもらうことになる。**画面まで自分で進めてから、押す操作だけを頼む。**
何度も往復させない。

**Device Hub を終了するとシミュレータも一緒に落ちる。** 作業中は終了させない。

## 確認の作法

- **返り値ではなく、撮って確かめる。** 成功と返して効いていない道具が複数ある
- **読み出した値を報告に書く。** 「確認しました」だけでは、その確認をした証拠にならない
- 座標は目測せず `describe-ui` の `frame` から取る。撮った画像から読むのは最後の手段
- 数値が説明できないときは、**一時的な計測コードを入れて実測する。** 推測で定数を置かない。
  `onGeometryChange` で `proxy.size` と `proxy.safeAreaInsets` をオーバーレイに出し、
  確認後に必ず外す

## よく使う組み立て

```bash
UDID=<simulator-udid>
AXE=/opt/homebrew/bin/axe

# 要素の座標を取る
$AXE describe-ui --udid $UDID

# 押す
$AXE touch -x 344 -y 255 --down --up --udid $UDID

# 撮る
xcrun simctl io $UDID screenshot out.png

# 回す
xcrun devicectl device orientation set --device $UDID landscapeLeft
xcrun devicectl device orientation get --device $UDID

# 状態を作る(UI を触らない)
xcrun simctl status_bar $UDID override --time 9:41 --cellularBars 4 --batteryState charging
xcrun simctl ui $UDID appearance dark
```

複数ディスプレイを持つ端末は `--display` で選ぶ。`xcrun simctl io <UDID> enumerate` で一覧が出る。

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.