# Command Line

Drive your iPhone, iPad, Android device or simulator from Terminal, shell scripts and CI with device-mcp-cli, Device MCP's command line. Every command can answer in JSON.

`device-mcp-cli` is Device MCP's command line. What you do in the app, or ask your AI agent to do, you can run from Terminal, a shell script, a Makefile or CI: list your devices, take screenshots, read the screen, tap and type, launch and install apps, set the location, and manage your license.

Every command can answer in JSON, so your scripts read the result with `jq` instead of parsing text.

## 1. Install

* **Homebrew**: `brew install --cask device-mcp` puts `device-mcp-cli` on your `PATH`.
* **Downloaded from the website**: run this once in Terminal, to put it on your `PATH`:

```bash
sudo ln -sf "/Applications/Device MCP.app/Contents/MacOS/device-mcp-cli" /usr/local/bin/device-mcp-cli
```

The link keeps working when Device MCP updates itself. Check it with:

```bash
device-mcp-cli --version
device-mcp-cli --help                  # every command
device-mcp-cli help apps launch        # one command, with its options
```

## 2. How it works

* **Device MCP runs your commands.** Device commands go to the Device MCP app on your Mac. If it isn't running, the command asks before opening it: `--launch` opens it without asking (use it in scripts), `--no-launch` never opens it. `status`, `mcp`, `tools` and `logs` never open it.
* **Which device**: add `--device` (or `-d`) with a device's name or UDID. Without it, commands use the device you picked with `devices select`, else the one selected in Device MCP.
* **JSON**: add `--json` to any command. Errors come in JSON too.
* **You stay in charge**: installing and removing apps, opening links, reading or changing the clipboard and Build & Run ask you in Device MCP first, as they do for an AI agent. See [Approvals](ai-agents/approvals.md). Unpairing a device and deactivating your license always ask.
* **Free and Pro**: every command works on Device MCP Free, except Build & Run, installing apps and the 3D view inspector, which need [Device MCP Pro](license.md). Free mirrors one device at a time.

## 3. Commands

`<device>` is a device's name or UDID. Every command takes `--json`; device commands take `--device`.

### Devices

| Command | What it does |
| --- | --- |
| `devices` | Lists your devices: name, kind, OS, connection, state and UDID. `--all` adds every simulator and emulator, and the models a new simulator can be. |
| `devices info` | A device's model, OS, screen size, mirror and lock state. `--settings` adds its appearance and accessibility settings. |
| `devices select <device>` | Picks the device the next commands use, and shows it in Device MCP. |
| `devices start-mirroring`, `devices stop-mirroring` | Starts or stops a device's mirror. |
| `devices reconnect` | Reconnects a device whose mirror froze. |
| `devices unpair <device>` | Unpairs an iPhone or iPad from your Mac. |
| `devices remove <device>` | Takes a device off Device MCP's list. |
| `simulators` | Lists your iOS and watchOS Simulators and Android emulators. |
| `simulators start <name>` | Starts a simulator or emulator and waits until it runs. `--model "iPhone 17 Pro"` creates a new simulator. |
| `simulators stop <name>` | Shuts a simulator or emulator down. |

### The screen

| Command | What it does |
| --- | --- |
| `screenshot` | Saves a full-resolution screenshot. `-o` picks the file (`.png` or `.jpg`) or folder; the default is `~/Pictures/Device MCP`. |
| `record start`, `record stop` | Records the screen to a movie in `~/Movies/Device MCP`. |
| `elements` | Lists what's on the screen: each element's type, label, value, frame and ref (`e12`), for `tap --ref`. |

### Touch and keys

| Command | What it does |
| --- | --- |
| `tap` | Taps an element by its text (`--text "Sign In"`), by its ref (`--ref e12`), or at a point (`-x 120 -y 640`). `--double` double-taps, `--long` long-presses. |
| `type <text>` | Types into the focused field. `--field "Email"` fills a field: taps it, empties it, types. `--submit` presses Return. `-` reads the text from a pipe or a file. |
| `scroll up\|down\|left\|right` | Scrolls. `--distance 300` moves the content exactly that many points. |
| `swipe --from x,y --to x,y` | Swipes from one point to another. |
| `press <button>` | Presses `home`, `lock`, `volume_up`, `volume_down`, `mute`, `siri` or `back`. |
| `key <key>` | Presses a keyboard key, with `--modifier command` and others. |
| `gesture <gesture>` | `go_home`, `app_switcher`, `control_center`, `notification_center` or `spotlight`. |
| `rotate <orientation>` | `portrait`, `landscape_left`, `landscape_right` or `portrait_upside_down`. |
| `hide-keyboard` | Hides the on-screen keyboard. |
| `wait-for <text>` | Waits until the text is on the screen (`--gone`: until it isn't), up to `--timeout` seconds. |
| `alert accept\|dismiss` | Answers a system alert, such as a permission request. `--button` taps a button by its text. |

### Apps

| Command | What it does |
| --- | --- |
| `apps` | Lists the installed apps: name, bundle ID and version. `--user` lists only the apps you installed. |
| `apps foreground` | The app in front, with its bundle ID. |
| `apps launch <app>` | Launches an app by bundle ID or name. `--language`, `--locale`, `--arg` and `--env` for a test launch. |
| `apps terminate <bundle-id>` | Quits a running app. |
| `apps install <path>` | Installs an `.ipa`, `.app` or `.apk`. Device MCP Pro. |
| `apps uninstall <bundle-id>` | Removes an app and its data. |
| `apps container <bundle-id>` | Downloads a development app's data as an `.xcappdata` package, like Xcode. |
| `open-url <url>` | Opens a web page or a deep link (`myapp://…`). |
| `build-and-run <project>` | Builds your Xcode project, installs it and launches it. Device MCP Pro. See [Build & Run](ai-agents/build-and-run.md). |
| `crashes` | Lists crash reports, newest first. `--app` filters by app. |
| `crashes show <path>` | Shows a crash report: what crashed and where. `--app` shows an app's newest crash. |

### Device settings

| Command | What it does |
| --- | --- |
| `location set <latitude> <longitude>` | Simulates a location. `location clear` goes back to the real one. |
| `appearance light\|dark` | Switches the device to light or dark mode. |
| `clipboard get`, `clipboard set <text>` | Reads or replaces the text on the device's clipboard. |

### Device MCP

| Command | What it does |
| --- | --- |
| `status` | Whether Device MCP is running, its version, its MCP server and your license. |
| `app open`, `app quit` | Opens Device MCP in the background, or quits it. |
| `mcp` | Whether the MCP server is on, and its address. `mcp on` and `mcp off` turn it on and off. |
| `mcp setup claude\|codex` | Adds Device MCP to Claude Code or Codex. `--print` shows the command instead. |
| `mcp config` | The JSON other MCP clients, such as Cursor, take. |
| `license` | Your license: Free, or its plan, key, seats and the versions it covers. |
| `license activate <key>` | Activates a license key on this Mac. |
| `license revoke` | Deactivates the license on this Mac and frees its seat. |
| `logs` | Device MCP's log, for a bug report. `-f` keeps printing new lines. |

### Anything else

| Command | What it does |
| --- | --- |
| `call <tool> [name=value…]` | Runs any of Device MCP's MCP tools, the way your AI agent does. |
| `tools` | Lists those tools and their arguments. |

## 4. Examples

### Sign in and check the result

A smoke test for your app, in a shell script or a CI step:

```bash
set -e
device-mcp-cli apps launch com.example.myapp --launch
device-mcp-cli wait-for "Sign In"
device-mcp-cli type "test@example.com" --field "Email"
device-mcp-cli type - --field "Password" < password.txt
device-mcp-cli tap --text "Sign In"
device-mcp-cli wait-for "Welcome" --timeout 20 || {
  device-mcp-cli screenshot -o failure.png
  exit 1
}
```

### Take a screenshot of every device

```bash
device-mcp-cli devices --json |
  jq -r '.devices[] | select(.state == "ready" or .state == "running") | .udid' |
  while read -r udid; do device-mcp-cli screenshot --device "$udid" -o ~/Desktop/; done
```

### Tap an element on the screen

`elements` lists the screen with refs. Find one with `jq`, then tap it:

```bash
REF=$(device-mcp-cli elements --json | jq -r '.elements[] | select(.label == "General") | .ref')
device-mcp-cli tap --ref "$REF"
```

### Test your app in another language and place

```bash
device-mcp-cli apps launch com.example.myapp --language fr --locale fr_FR
device-mcp-cli location set 48.8584 2.2945
device-mcp-cli open-url "myapp://map"
device-mcp-cli appearance dark
```

### Build and run on a new simulator

```bash
device-mcp-cli simulators start --model "iPhone 17 Pro" --launch
device-mcp-cli build-and-run ~/Projects/MyApp/MyApp.xcodeproj --scheme MyApp
device-mcp-cli screenshot -o ~/Desktop/myapp.png
```

### Record a bug

```bash
device-mcp-cli record start
# reproduce the bug on the device
device-mcp-cli record stop
```

### Set up a Mac

On a CI Mac or a new teammate's Mac:

```bash
device-mcp-cli license activate --launch < license-key.txt
device-mcp-cli mcp on
device-mcp-cli mcp setup claude
device-mcp-cli status
```

## 5. JSON and exit codes

With `--json`, a command prints one JSON object. For example, `device-mcp-cli devices --json`:

```json
{
  "devices" : [
    {
      "connection" : "USB",
      "current" : true,
      "kind" : "iphone",
      "mirroringStopped" : false,
      "model" : "iPhone 17 Pro",
      "name" : "My iPhone",
      "osVersion" : "27.0.1",
      "platform" : "iOS",
      "state" : "ready",
      "udid" : "00008150-000A1B2C3D4E5F60"
    }
  ]
}
```

A device's `kind` is `iphone`, `ipad`, `watch`, `android`, `simulator` or `emulator`. Its `state` is `ready`, `locked`, `blocked` (with `issue` and `fix` saying why and what to do), `connecting`, `running`, `shut_down`, `booting`, `shutting_down`, `creating` or `starting`.

An error prints `{"error": {"code": "…", "message": "…"}}`:

| Code | Exit code | Meaning |
| --- | --- | --- |
| `not_running` | 69 | Device MCP isn't running and wasn't opened, or it quit before it answered. |
| `no_answer` | 69 | Device MCP is running but didn't answer: update it, or quit it and open it again. |
| `not_installed` | 69 | Device MCP isn't installed. |
| `invalid_arguments` | 64 | A wrong argument or a malformed license key. |
| `pro_required` | 1 | The command needs Device MCP Pro. |
| `not_approved` | 1 | You declined it in Device MCP, or nobody answered. |
| `timed_out` | 1 | Device MCP didn't finish in time. |
| `cancelled` | 1 | You answered no. |
| `failed` | 1 | Anything else: the message says why. |

A command that works exits with 0.

## 6. With your AI agent

Your agent can use the command line too, for example to write a test script or a CI step for your app:

* *"Write a script that signs in on my iPhone and fails if the home screen doesn't load."*
* *"Add a CI step that takes a screenshot of every screen of the onboarding."*

Commands your agent runs show in the **Agent** tab as **device-mcp-cli**. See [Agent Activity](ai-agents/agent-activity.md).
