Back to skills

Simulator Workflows

iOS Simulator device and app management with simctl. Use when managing simulator devices (boot, create, delete), installing/launching apps, or troubleshooting simulator issues. Covers device lifecycle, app lifecycle, and diagnostics.

21 stars
0 votes
0 copies
0 views
Added 12/19/2025
data-aibashtestinggitapidatabaseperformance

Works with

terminalapimcp

Install via CLI

$openskills install conorluddy/xclaude-plugin
Download Zip
Files
SKILL.md
---
name: simulator-workflows
description: iOS Simulator device and app management with simctl. Use when managing simulator devices (boot, create, delete), installing/launching apps, or troubleshooting simulator issues. Covers device lifecycle, app lifecycle, and diagnostics.
---

# Simulator Workflows

**Use the `execute_simulator_command` MCP tool for all simulator management**

The xclaude-plugin provides the `execute_simulator_command` MCP tool which consolidates all simctl operations into a single, token-efficient dispatcher.

## ⚠️ CRITICAL: Always Use MCP Tools First

**This is the most important rule:** When working with iOS simulators, you MUST use the `execute_simulator_command` MCP tool.

- ✅ **DO**: Invoke `execute_simulator_command` for all device/app lifecycle operations
- ✅ **DO**: If the MCP tool fails, adjust parameters and retry
- ✅ **DO**: Read error messages and debug the parameters
- ❌ **NEVER**: Fall back to bash `xcrun simctl` commands
- ❌ **NEVER**: Use `simctl` directly in bash
- ❌ **NEVER**: Run `xcrun simctl` commands in a terminal

**Why?** The MCP tool provides:
- Structured error handling
- Token efficiency (consolidated into 1 tool vs. verbose bash output)
- Proper integration with the xclaude-plugin architecture
- Consistent response formatting

If `execute_simulator_command` fails, the issue is with parameters or device state - not that you should use bash.

## When to Use Bash (And When NOT to)

### ❌ NEVER Use Bash For These (Use MCP Tools Instead)

| Task | ❌ WRONG (Bash) | ✅ RIGHT (MCP Tool) |
|------|---------------|-------------------|
| List devices | `xcrun simctl list` | `execute_simulator_command` op: "list" |
| Boot simulator | `xcrun simctl boot <UDID>` | `execute_simulator_command` op: "device-lifecycle" sub: "boot" |
| Install app | `xcrun simctl install <UDID> <app.app>` | `execute_simulator_command` op: "app-lifecycle" sub: "install" |
| Launch app | `xcrun simctl launch <UDID> <bundle-id>` | `execute_simulator_command` op: "app-lifecycle" sub: "launch" |
| Screenshot | `xcrun simctl io <UDID> screenshot` | `execute_simulator_command` op: "io" sub: "screenshot" |

### ✅ Bash is Acceptable For (Non-Simulator Tasks)

- File operations: `mkdir`, `cp`, `rm`, `ls`, etc.
- Text inspection: `grep`, `find`, `cat`, etc.
- Git operations: `git status`, `git log`, etc.
- Environment checks: `which`, `simctl --version`, etc.
- Project exploration: `find . -name "*.app"`, etc.

### The Rule: If it's about simulator management → Use MCP tool, not bash

## Quick Reference

| Task | MCP Tool | Operation | Sub-Operation |
|------|----------|-----------|---------------|
| List devices | `execute_simulator_command` | `list` | - |
| Boot device | `execute_simulator_command` | `device-lifecycle` | `boot` |
| Shutdown device | `execute_simulator_command` | `device-lifecycle` | `shutdown` |
| Create device | `execute_simulator_command` | `device-lifecycle` | `create` |
| Delete device | `execute_simulator_command` | `device-lifecycle` | `delete` |
| Install app | `execute_simulator_command` | `app-lifecycle` | `install` |
| Launch app | `execute_simulator_command` | `app-lifecycle` | `launch` |
| Screenshot | `execute_simulator_command` | `io` | `screenshot` |
| Health check | `execute_simulator_command` | `health-check` | - |

## Device Management

### 1. Listing Devices - Use `execute_simulator_command` with operation: "list"

Invoke the `execute_simulator_command` MCP tool:

```json
{
  "operation": "list"
}
```

**Returns (Progressive Disclosure):**
```json
{
  "summary": {
    "total_devices": 47,
    "available_devices": 31,
    "booted_devices": 1
  },
  "booted": [
    {
      "name": "iPhone 15",
      "udid": "ABC123...",
      "state": "Booted",
      "runtime": "iOS 17.0"
    }
  ],
  "cache_id": "sim-list-xyz789",
  "next_steps": [
    "Use device name or UDID for operations",
    "Query cache_id for full device list if needed"
  ]
}
```

**Note:** Large device lists use progressive disclosure to save tokens.

### 2. Booting a Simulator - Use `execute_simulator_command` with device-lifecycle

Invoke the `execute_simulator_command` MCP tool:

**By Name:**
```json
{
  "operation": "device-lifecycle",
  "sub_operation": "boot",
  "device_id": "iPhone 15"
}
```

**By UDID:**
```json
{
  "operation": "device-lifecycle",
  "sub_operation": "boot",
  "device_id": "ABC123-DEF456-...",
  "parameters": {
    "wait_for_boot": true
  }
}
```

**wait_for_boot:** Blocks until device fully booted (recommended)

### 3. Shutting Down

```json
{
  "operation": "device-lifecycle",
  "sub_operation": "shutdown",
  "device_id": "iPhone 15"
}
```

### 4. Creating a New Simulator

```json
{
  "operation": "device-lifecycle",
  "sub_operation": "create",
  "device_id": "My iPhone 15 Test",
  "parameters": {
    "device_type": "iPhone 15",
    "runtime": "iOS 17.0"
  }
}
```

**Returns:** New device UDID

**Available Device Types:**
- iPhone SE (3rd generation)
- iPhone 14, 14 Plus, 14 Pro, 14 Pro Max
- iPhone 15, 15 Plus, 15 Pro, 15 Pro Max
- iPad (10th generation), iPad Air, iPad Pro

**Check available runtimes:** Use `list` to see installed iOS versions

### 5. Deleting a Simulator

```json
{
  "operation": "device-lifecycle",
  "sub_operation": "delete",
  "device_id": "My iPhone 15 Test"
}
```

**Warning:** This is permanent and cannot be undone.

### 6. Erasing a Simulator

**Remove all data but keep device:**

```json
{
  "operation": "device-lifecycle",
  "sub_operation": "erase",
  "device_id": "iPhone 15"
}
```

**When to erase:**
- Reset app state completely
- Clear test data
- Reproduce fresh install behavior

### 7. Cloning a Simulator

**Duplicate a device with all its data:**

```json
{
  "operation": "device-lifecycle",
  "sub_operation": "clone",
  "device_id": "iPhone 15",
  "parameters": {
    "new_name": "iPhone 15 Clone"
  }
}
```

**Use case:** Preserve a specific test state

## App Management

### 1. Installing an App

```json
{
  "operation": "app-lifecycle",
  "sub_operation": "install",
  "device_id": "iPhone 15",
  "app_identifier": "/path/to/MyApp.app"
}
```

**Note:** `app_identifier` is the path to `.app` bundle for install operation.

**Build + Install Pattern:**

```
1. execute_xcode_command (operation: build) → Get .app path
2. execute_simulator_command (operation: app-lifecycle, sub_operation: install)
```

### 2. Launching an App

```json
{
  "operation": "app-lifecycle",
  "sub_operation": "launch",
  "device_id": "iPhone 15",
  "app_identifier": "com.example.MyApp"
}
```

**With Arguments:**
```json
{
  "operation": "app-lifecycle",
  "sub_operation": "launch",
  "device_id": "iPhone 15",
  "app_identifier": "com.example.MyApp",
  "parameters": {
    "arguments": ["--test-mode", "--mock-data"],
    "environment": {
      "API_URL": "https://staging.example.com"
    }
  }
}
```

### 3. Terminating an App

```json
{
  "operation": "app-lifecycle",
  "sub_operation": "terminate",
  "device_id": "iPhone 15",
  "app_identifier": "com.example.MyApp"
}
```

### 4. Uninstalling an App

```json
{
  "operation": "app-lifecycle",
  "sub_operation": "uninstall",
  "device_id": "iPhone 15",
  "app_identifier": "com.example.MyApp"
}
```

### 5. Getting App Container Paths

**For accessing app data:**

```json
{
  "operation": "get-app-container",
  "device_id": "iPhone 15",
  "app_identifier": "com.example.MyApp",
  "parameters": {
    "container_type": "data"
  }
}
```

**Container Types:**
- **data**: App's Documents, Library, tmp directories
- **bundle**: App's .app bundle
- **group**: Shared group containers

**Returns:** File system path to container

**Use case:** Inspect database files, logs, or user defaults

## Capture & Media

### 1. Taking Screenshots

```json
{
  "operation": "io",
  "sub_operation": "screenshot",
  "device_id": "iPhone 15",
  "parameters": {
    "output_path": "/path/to/screenshot.png"
  }
}
```

**Auto-generated path:** If `output_path` omitted, creates temp file

### 2. Recording Video

```json
{
  "operation": "io",
  "sub_operation": "video",
  "device_id": "iPhone 15",
  "parameters": {
    "output_path": "/path/to/video.mp4",
    "duration": 30
  }
}
```

**Note:** Duration in seconds. Press Ctrl+C to stop recording manually.

## Advanced Operations

### 1. Opening URLs

```json
{
  "operation": "openurl",
  "device_id": "iPhone 15",
  "parameters": {
    "url": "myapp://deep-link/path"
  }
}
```

**Use cases:**
- Test universal links
- Test deep linking
- Open Safari to specific URL

### 2. Push Notifications

```json
{
  "operation": "push",
  "device_id": "iPhone 15",
  "app_identifier": "com.example.MyApp",
  "parameters": {
    "payload": {
      "aps": {
        "alert": "Test notification",
        "badge": 1,
        "sound": "default"
      }
    }
  }
}
```

**Payload:** Standard APNs JSON payload

## Environment Validation

### Health Check

**Verify iOS development environment:**

```json
{
  "operation": "health-check"
}
```

**Checks:**
- Xcode installation
- Command line tools
- simctl availability
- CoreSimulator framework

**Returns:**
```json
{
  "xcode_installed": true,
  "xcode_version": "15.0",
  "simctl_available": true,
  "issues": []
}
```

## Device Selection Strategies

### By Name (Easiest)

```json
{
  "device_id": "iPhone 15"
}
```

**Pro:** Readable, easy to remember
**Con:** May match multiple devices

### By UDID (Most Reliable)

```json
{
  "device_id": "ABC123-DEF456-GHI789..."
}
```

**Pro:** Unique, guaranteed single match
**Con:** Long, hard to remember

### Using "booted" (Convenience)

Some tools (like IDB) accept `"booted"` to target the currently booted simulator:

```json
{
  "target": "booted"
}
```

**Note:** Only works with IDB operations, not simctl

## Common Workflows

### Workflow: Fresh Install Test

```
1. boot → Start simulator
2. uninstall → Remove existing app
3. install → Install fresh build
4. launch → Start app
5. (UI automation) → Test flow
6. terminate → Stop app
7. shutdown → Stop simulator
```

### Workflow: Rapid Iteration

```
1. build → Compile latest code
2. install → Update app on simulator (already booted)
3. terminate → Stop running app
4. launch → Start updated app
```

**Note:** No need to boot/shutdown between iterations

### Workflow: Multi-Device Testing

```
1. list → Get available devices
2. For each device:
   - boot → Start device
   - install → Install app
   - launch → Start app
   - (run tests) → Execute test suite
   - terminate → Stop app
   - shutdown → Stop device
```

## Troubleshooting

### Device Not Found

**Problem:** "Unable to find device: iPhone 15"

**Solutions:**
1. Run `list` to see exact device names
2. Use UDID instead of name
3. Check device hasn't been deleted

### Unable to Boot

**Problem:** Boot fails or times out

**Solutions:**
1. Check disk space (simulators need space)
2. Shutdown other running simulators
3. Restart CoreSimulator: `killall -9 com.apple.CoreSimulator.CoreSimulatorService`
4. Run `health-check` to validate environment

### App Install Fails

**Problem:** Install operation fails

**Solutions:**
1. Verify .app path is correct
2. Check device is booted
3. Ensure .app is built for simulator (not device)
4. Try erasing simulator first

### App Won't Launch

**Problem:** Launch succeeds but app crashes immediately

**Solutions:**
1. Check app logs in Console.app
2. Verify app is signed correctly
3. Check for missing frameworks/resources
4. Try clean build + reinstall

## Performance Tips

### 1. Keep Simulators Booted

Booting is slow (~5-10 seconds). Keep simulator running during development.

### 2. Use Progressive Disclosure

Device lists can be large. Summary provides what you need 95% of the time.

### 3. Reuse Simulators

Creating/deleting is slower than erasing. Reuse devices when possible.

### 4. Parallel Operations

Boot multiple simulators in parallel for multi-device testing:

```
Launch 3 boot operations concurrently
Wait for all to complete
Proceed with testing
```

## Integration with Other Tools

### With Xcodebuild

```
1. execute_xcode_command (build) → Get .app bundle
2. execute_simulator_command (install) → Install to simulator
3. execute_simulator_command (launch) → Start app
```

### With IDB

```
1. execute_simulator_command (boot) → Start device
2. execute_idb_command (describe) → Query UI
3. execute_idb_command (tap) → Interact
```

### With Testing

```
1. execute_simulator_command (boot) → Start device
2. execute_xcode_command (test) → Run tests on device
3. execute_simulator_command (shutdown) → Stop device
```

## Integration with MCP Tools

This Skill works with `execute_simulator_command` tool:

- All operations use the `execute_simulator_command` tool
- Tool handles simctl execution
- Tool provides progressive disclosure for large outputs
- This Skill teaches WHEN and HOW to use operations

## Related Skills

- **xcode-workflows**: Building apps for simulators
- **ui-automation-workflows**: Automating simulator interactions
- **ios-testing-patterns**: Test execution strategies

## Related Resources

- `xc://operations/simulator`: Complete simctl operations reference
- `xc://reference/device-specs`: Available device types and runtimes
- `xc://reference/error-codes`: Common simulator errors

---

**Tip: Use `list` to discover, boot by name for convenience, use UDID for reliability.**

Comments (0)

No comments yet. Be the first to comment!