---
name: axe-simulator-control
description: Automate iOS Simulator interactions using AXe for taps, gestures, text input, hardware buttons, and video recording
---

# AXe Simulator Control

Use this skill when you need to automate iOS Simulator interactions, including taps, gestures, text input, hardware buttons, or video recording.

## Related Skills

- See [`xcodebuild-testing`](../xcodebuild-testing/SKILL.md) for running tests that might require simulator interactions
- See [`screenshot`](../screenshot/SKILL.md) for capturing screenshots from the simulator

## Skill Flow

- Example queries:
  - "tap at coordinates (100, 200) in the simulator"
  - "type 'hello world' into the simulator"
  - "press the home button in the simulator"
  - "record a video of the simulator"
  - "perform a scroll up gesture"
- Notes:
  - AXe is installed via Homebrew: `brew tap cameroncooke/axe && brew install axe`
  - Most commands require a simulator UDID (use `axe list-simulators` to find it)
  - The simulator must be booted and running for most operations
  - AXe uses the iOS Simulator's accessibility framework
  - For VivaDicta project, the default simulator is: `iPhone 17 Pro Max, OS=26.4`
  - Save screenshots to `llmtemp/screenshots/` directory for temporary test artifacts

### 1. Determine the Required Action

**Touch/Tap Actions** if:
- Need to tap at specific coordinates
- Need to add delays before/after taps
- Need to simulate touch gestures

→ Continue with **Path A: Touch & Tap** (steps 2A-4A)

**Text Input** if:
- Need to type text into the simulator
- Need to test keyboard input
- Need to simulate user text entry

→ Continue with **Path B: Text Input** (step 2B)

**Gestures** if:
- Need to scroll, swipe, or perform system gestures
- Need to test gesture recognizers
- Need to navigate using gestures

→ Continue with **Path C: Gestures** (steps 2C-3C)

**Hardware Buttons** if:
- Need to press home, lock, volume buttons
- Need to test app lifecycle events
- Need to simulate device rotation

→ Continue with **Path D: Hardware Buttons** (steps 2D-3D)

**Video Operations** if:
- Need to record simulator video
- Need to stream simulator output
- Need to capture simulator for documentation

→ Continue with **Path E: Video Operations** (steps 2E-3E)

**List Simulators** if:
- Need to find available simulators
- Need to get a simulator UDID
- First time setup

→ Continue with **Path F: List Simulators** (step 2F)

## Path A: Touch & Tap

### 2A. Get Simulator UDID

```bash
# List available simulators
axe list-simulators

# Store the UDID for the target simulator
UDID="B34FF305-5EA8-412B-943F-1D0371CA17FF"
```

### 3A. Get Accurate Coordinates Using describe-ui

**IMPORTANT:** Always use `axe describe-ui` to get accurate coordinates instead of guessing from screenshots.

```bash
# Get the full UI accessibility tree
axe describe-ui --udid $UDID > ui_tree.json

# Example output for a button:
# {
#   "AXFrame" : "{{175, 741}, {52, 50}}",
#   "AXLabel" : "stop.circle.fill",
#   "type" : "Button",
#   ...
# }

# Calculate center coordinates:
# x_center = x + (width / 2)  →  175 + (52 / 2) = 201
# y_center = y + (height / 2)  →  741 + (50 / 2) = 766
```

**Why this matters:**
- Visual appearance in screenshots doesn't always match accessibility frame coordinates
- UI elements that change state (e.g., record → stop button) may have different positions than they appear
- The accessibility frame is what AXe actually uses for tap detection

### 4A. Perform Tap Action

```bash
# Simple tap at coordinates (use coordinates from describe-ui)
axe tap -x 201 -y 766 --udid $UDID

# Tap with delays before and after
axe tap -x 201 -y 766 --pre-delay 1.0 --post-delay 0.5 --udid $UDID
```

**Available tap options:**
- `-x` and `-y`: Coordinates (required) - get these from `describe-ui` output
- `--pre-delay`: Delay in seconds before tapping
- `--post-delay`: Delay in seconds after tapping
- `--udid`: Simulator UDID (required)

**Note:** The `tap` command does NOT support `--duration` for long press. Use `--pre-delay` and `--post-delay` for timing control.

### 5A. Verify the Action

- Check the simulator visually or via app logs
- If tap didn't register, ensure:
  - Simulator is in foreground
  - Coordinates are correct (origin is top-left)
  - Target element is interactive
  - You used coordinates from `describe-ui`, not visual estimates

## Path B: Text Input

### 2B. Type Text into Simulator

```bash
# Get simulator UDID first
UDID="B34FF305-5EA8-412B-943F-1D0371CA17FF"

# Type text (ensure a text field is focused first)
axe type 'Hello World!' --udid $UDID

# Type text with special characters (use single quotes)
axe type 'user@example.com' --udid $UDID
```

**Notes:**
- The text field must be focused before typing (tap it first if needed)
- Use single quotes to avoid shell interpretation
- Special characters and emojis are supported

## Path C: Gestures

### 2C. Choose Gesture Type

Available gestures:
- `scroll-up` / `scroll-down` / `scroll-left` / `scroll-right`
- `swipe-from-left-edge` / `swipe-from-right-edge`
- `swipe-from-top-edge` / `swipe-from-bottom-edge`

### 3C. Execute Gesture

```bash
# Get simulator UDID first
UDID="B34FF305-5EA8-412B-943F-1D0371CA17FF"

# Perform scroll gesture
axe gesture scroll-up --udid $UDID

# Perform edge swipe (for navigation)
axe gesture swipe-from-left-edge --udid $UDID

# Perform swipe gesture
axe gesture swipe-from-bottom-edge --udid $UDID
```

## Path D: Hardware Buttons

### 2D. Choose Button Action

Available buttons:
- `home` - Press home button
- `lock` - Press lock/power button
- `volume-up` / `volume-down`
- `siri` - Activate Siri

### 3D. Execute Button Press

```bash
# Get simulator UDID first
UDID="B34FF305-5EA8-412B-943F-1D0371CA17FF"

# Press home button
axe button home --udid $UDID

# Press lock button with custom duration
axe button lock --duration 2.0 --udid $UDID

# Press volume up
axe button volume-up --udid $UDID
```

**Notes:**
- Lock duration determines press-and-hold behavior
- Home button triggers app backgrounding
- Use for testing app lifecycle events

## Path E: Video Operations

### 2E. Choose Operation Type

**Stream Video** if:
- Need real-time video output
- Building automation tools
- Need MJPEG format

**Record Video** if:
- Need to save video file
- Creating documentation
- Need MP4 format

### 3E. Execute Video Operation

**Stream Video:**
```bash
UDID="B34FF305-5EA8-412B-943F-1D0371CA17FF"

# Stream at 10 FPS in MJPEG format
axe stream-video --udid $UDID --fps 10 --format mjpeg > stream.mjpeg
```

**Record Video:**
```bash
UDID="B34FF305-5EA8-412B-943F-1D0371CA17FF"

# Record at 15 FPS and save to file
axe record-video --udid $UDID --fps 15 --output recording.mp4

# Stop recording with Ctrl+C
```

## Path F: List Simulators

### 2F. List Available Simulators

```bash
# List all available simulators with their UDIDs
axe list-simulators

# Example output:
# iPhone 17 Pro Max (26.0) - B34FF305-5EA8-412B-943F-1D0371CA17FF
# iPhone 16 (25.0) - A12BC456-7DEF-89GH-IJKL-MNOPQRSTUVWX
```

**Notes:**
- Copy the UDID for use in other commands
- Only booted simulators can be controlled
- Use `xcrun simctl list` for more detailed simulator information

## Common Workflows

### Automated Testing Workflow

```bash
# 1. Get the simulator UDID
UDID=$(axe list-simulators | grep "iPhone 17 Pro Max" | awk '{print $NF}')

# 2. Tap to focus text field
axe tap -x 200 -y 300 --udid $UDID

# 3. Type text
axe type 'test@example.com' --udid $UDID

# 4. Tap submit button
axe tap -x 200 -y 400 --udid $UDID

# 5. Wait and verify (app-specific)
```

### Video Documentation Workflow

```bash
# 1. Get simulator UDID
UDID="B34FF305-5EA8-412B-943F-1D0371CA17FF"

# 2. Start recording
axe record-video --udid $UDID --fps 30 --output demo.mp4 &
RECORD_PID=$!

# 3. Perform actions
axe tap -x 100 -y 200 --udid $UDID
sleep 1
axe gesture scroll-up --udid $UDID
sleep 1
axe button home --udid $UDID

# 4. Stop recording
kill $RECORD_PID
```

## Known Limitations

### SwiftUI TabView Navigation

**Issue:** SwiftUI's modern `TabView` component (iOS 18+) doesn't expose individual tab buttons in the accessibility hierarchy.

**What you'll see:**
- `axe describe-ui` shows the tab bar as a single `AXGroup` with no children
- Individual tab buttons are NOT listed as separate accessible elements

**Example:**
```json
{
  "AXFrame" : "{{0, 791}, {402, 83}}",
  "AXLabel" : "Tab Bar",
  "type" : "Group",
  "children" : []  // ← No individual tab buttons exposed
}
```

**✅ However, tab navigation DOES work with calculated coordinates!**

Even though tab buttons aren't in the accessibility tree, you can still tap them using estimated positions within the Tab Bar frame:

```bash
# Tab Bar frame: x: 0, y: 791, width: 402, height: 83
# Calculate y-center: 791 + (83/2) = 832

# For a 3-tab layout (Record, Notes, Settings):
UDID="D28078F6-0BE9-4EB8-BEBE-BF8EBEA5CA75"

# Tap Record tab (left third)
axe tap -x 103 -y 832 --udid $UDID    # x ≈ 402 * 1/4

# Tap Notes tab (center)
axe tap -x 201 -y 832 --udid $UDID    # x ≈ 402 * 1/2

# Tap Settings tab (right third)
axe tap -x 268 -y 832 --udid $UDID    # x ≈ 402 * 2/3
```

**Key insight:** The Tab Bar frame tells you the tappable area. Calculate positions by:
1. Get y-center from frame: `y + (height / 2)`
2. Divide x-axis by number of tabs to estimate positions
3. Test and adjust x-coordinates based on actual tab spacing

**Alternative workarounds:**
- Use XCUITest for UI testing that requires guaranteed tab detection
- Add custom accessibility identifiers if you control the app code
- Use deep linking or keyboard shortcuts for tab navigation in automation

### Other SwiftUI Components

Some SwiftUI components may have limited accessibility exposure. Always use `axe describe-ui` to verify an element is accessible before attempting to interact with it.

## Troubleshooting

**"Simulator not found" error:**
- Ensure simulator is booted: `xcrun simctl list | grep Booted`
- Verify UDID is correct: `axe list-simulators`

**Tap not registering:**
- **FIRST:** Use `axe describe-ui` to get accurate coordinates (don't guess from screenshots)
- Check coordinates are within screen bounds
- Ensure element is visible and interactive
- Verify the element appears in the accessibility tree with `describe-ui`
- Try adding small delay between taps

**Text not appearing:**
- Tap text field first to focus it
- Check keyboard is visible in simulator
- Verify text encoding with single quotes

**Video recording issues:**
- Ensure sufficient disk space
- Check file permissions in output directory
- Verify FPS is reasonable (10-30 recommended)
