AXe CLI Documentation

repository·main·Indexed 24 days ago

https://github.com/cameroncooke/axe

A comprehensive CLI tool for interacting with iOS Simulators using Apple's HID functionality. AXe enables automation tasks including UI inspection, tapping, typing, screenshotting, and complex gesture control. It features a batch mode for executing multi-step workflows via inline flags, files, or stdin, and supports advanced element selection using accessibility identifiers and labels.

Tokens
11.8K
Snippets
25
Records
79
Agent score
82%

What's inside AXe

  1. Automate iOS Simulator interactions with AXe

    main

    AXe is a CLI tool designed for automating iOS Simulator interactions. It supports touch gestures, text input, slider adjustments, UI inspection, and batching multi-step workflows.

    Core Workflow:

    1. Identify Target: Use axe list-simulators to find the simulator UDID.
    2. Inspect UI: Use axe describe-ui --udid <UDID> to discover element IDs, labels, and coordinates.
    3. Interact: Use commands like tap, swipe, type, or slider using the discovered selectors or coordinates.
    4. Verify: Use describe-ui or screenshot to confirm the app state changed as expected.
  2. Configure element waiting with --wait-timeout

    main

    To handle asynchronous UI changes (like screen transitions), use the --wait-timeout <seconds> flag. This tells AXe to poll the accessibility tree for a specified number of seconds for a selector-based element to appear before failing. The frequency of polling is controlled by --poll-interval <seconds> (defaulting to 0.25s).

    # Wait up to 5 seconds for 'WelcomeMessage' to appear after tapping 'LoginButton'
    axe batch --udid SIMULATOR_UDID \
      --wait-timeout 5 \
      --step "tap --id LoginButton" \
      --step "tap --id WelcomeMessage"
  3. Configure tap styles (Automatic vs Physical vs Simulator)

    main

    The --tap-style option determines how the tap is physically executed on the simulator:

    • automatic: The preferred mode. It intelligently chooses between physical touch (down/up) for switch-like controls and simulator taps for other elements.
    • simulator: Uses FBSimulator's tapAt method. This is a standard simulator-level tap.
    • physical: Uses actual HID touch down and up events. This is more reliable for interacting with toggles and switches that require a specific touch sequence.
  4. Structure of a Compatibility Golden Cell

    main

    Each compatibility cell directory (named using the format xcode-[version]-[build]_ios-[version]-[build]) contains three primary components:

    • contract.json: Stores the stable matrix identity, including schema version, Xcode version/build, runtime build, and the fixture used.
    • stable/: Contains the recorded command execution data, including argv, stdout, stderr, stdin, and exit status. This covers help text, unknown-option behavior, subcommand validation, and output-path contracts. Note that hierarchy values (labels, frames, identifiers) are excluded to prevent churn from host-specific data; instead, stable/hierarchy/schema-types.json defines the normalized JSON paths and types.
    • provenance.json: Stores volatile run identity, including the exact AXe payload SHA-256, the simulator UDID/device name, and the SHA-256 of the stable/contract.json.
  5. Toggling switches and toggles in AXe Batch

    main

    When using tap on a selector that matches a row or label containing exactly one UIKit UISwitch or SwiftUI Toggle, AXe will automatically tap the control's activation point.

    • Default Behavior: With --tap-style automatic, switch/toggle activations use physical touch down/up, while normal taps use the simulator tapAt method.
    • Coordinate Taps: If label selectors are ambiguous and no AXUniqueId is found, you may need to use coordinate taps (tap -x/-y). For these to work with physical touch, use --tap-style physical at the batch level or for the specific step.
  6. Understand the AXe execution model and limitations

    main

    Most HID commands (tap, swipe, drag, type, key, etc.) are fire-and-forget. AXe confirms the event was dispatched to the simulator, but it cannot verify if the app actually processed the event (e.g., a tap might land during a transition).

    The Exception: slider slider is the only command that performs verification. It executes a low-level HID drag, re-reads the matched slider's AXValue, and fails if the observed 0-100 value is outside tolerance. Note that iOS slider controls quantize values, so AXe will not attempt to chase unreachable decimal values.

    Best Practice: Always verify critical outcomes separately using describe-ui or screenshot.

  7. Wait for an element to appear before tapping

    main

    When targeting an element via --id, --label, or --value, you can use --wait-timeout to poll the accessibility tree until the element is found. This is useful for handling asynchronous UI updates or animations.

    • --wait-timeout <seconds>: The maximum time to wait. Set to 0 to disable waiting (default).
    • --poll-interval <seconds>: The frequency of polling (default 0.25). Must be greater than 0 if --wait-timeout is used.
  8. Regenerate Compatibility Goldens

    main

    To regenerate a specific compatibility cell in the Tests/Goldens directory, use the scripts/regenerate-goldens.sh script. You must provide an absolute path to the AXe payload, the specific developer directory for the target Xcode version, the UDID of a booted simulator containing AxePlayground, and the target matrix ID.

    Note: The AXe payload must be a clean, release-shaped, versioned payload. Using a development build will result in an invalid version record in the golden cell.

    scripts/regenerate-goldens.sh \
      --axe /absolute/path/to/axe \
      --developer-dir /Applications/Xcode-26.5.0.app/Contents/Developer \
      --udid SIMULATOR_UDID \
      --matrix-id xcode-26.5-17F42_ios-26.5-23F77 \
      --update
  9. Check Compatibility Goldens

    main

    To validate that a current AXe payload matches a checked-in compatibility cell, use the --check flag with the same arguments used for regeneration. The script will regenerate the cell into a temporary directory and compare it against the checked-in version.

    For a successful check, the AXe payload must be byte-identical to the one used during capture, as provenance validation relies on the payload's SHA-256. The generated stable/contract.json SHA-256 must also match the value recorded in provenance.json.

    scripts/regenerate-goldens.sh \
      --axe /absolute/path/to/axe \
      --developer-dir /Applications/Xcode-26.5.0.app/Contents/Developer \
      --udid SIMULATOR_UDID \
      --matrix-id xcode-26.5-17F42_ios-26.5-23F77 \
      --check
  10. Use AXe Batch to automate simulator interactions

    main

    The axe batch command allows you to execute a sequence of automation steps on a specific iOS simulator. You can provide steps via inline flags, a file, or standard input (stdin).

    Input Rules:

    • You must use exactly one source: --step, --file, or --stdin.
    • Empty lines and lines starting with # are ignored in file/stdin input.
    • Do not include the --udid inside step lines; it must be provided at the batch command level.
    # Example using inline steps
    axe batch --udid SIMULATOR_UDID \
      --step "tap --id EmailField" \
      --step "type 'cam@example.com'"
  11. Apply timing and input best practices

    main

    To ensure reliable automation, use the following timing controls:

    • Delays: Use --pre-delay and --post-delay on tap, swipe, and gesture commands to add fixed delays around actions.
    • Duration: Use --duration to control how long a swipe, gesture, button press, or key press lasts.
    • Text Input: For text containing shell-sensitive characters, use --stdin or --file instead of inline quotes. Use single quotes for inline text to avoid shell expansion.
    • Stability: In batch flows, use --wait-timeout for selectors. If the UI changes but you aren't using --wait-timeout, use --ax-cache perStep to ensure each step gets a fresh accessibility snapshot.