
Axe
- 57 installs
- 2.1k repo stars
- Updated July 21, 2026
- cameroncooke/axe
axe is a skill that provides agent-ready guidance for using the AXe CLI to automate and inspect an iOS Simulator.
About
axe is a skill that teaches an agent how to drive the AXe CLI against an iOS Simulator. It covers identifying the simulator UDID, inspecting the screen with describe-ui, and issuing tap, swipe, drag, type, slider, screenshot, and record-video commands. Developers use it to automate simulator interaction and verify iOS app UI during testing. It also documents batch mode for running multi-step flows in a single process invocation.
- Agent-ready reference for the AXe CLI to automate an iOS Simulator
- Covers tap, swipe, drag, type, slider, screenshot, video and batch flows
- Prefers resilient --id/--label selectors over raw coordinates
Axe by the numbers
- 57 all-time installs (skills.sh)
- Ranked #1,182 of 2,153 Testing & QA skills by installs in the Skillselion catalog
- Data as of Aug 4, 2026 (Skillselion catalog sync)
axe capabilities & compatibility
- Capabilities
- ui automation · simulator control · screenshot capture · ui inspection
- Use cases
- testing
- Platforms
- macOS
What axe says it does
Provides agent-ready AXe CLI usage guidance for iOS Simulator automation.
Prefer selectors (`tap --id` / `tap --label`, `slider --id` / `slider --label`) over raw coordinates.
**Prefer `axe batch`** for multi-step flows. Batch executes every step in a single process invocation
npx skills add https://github.com/cameroncooke/axe --skill axeAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 57 |
|---|---|
| repo stars | ★ 2.1k |
| Last updated | July 21, 2026 |
| Repository | cameroncooke/axe ↗ |
What it does
Automate and verify iOS app UI on the Simulator by scripting taps, swipes, text input, and screenshots via the AXe CLI.
Who is it for?
Agents automating iOS Simulator UI interactions and verifying app behavior during testing.
Skip if: Automating real physical iOS devices or non-Apple platforms.
When should I use this skill?
When asked to use AXe, automate a simulator, tap/swipe/type on a simulator, set a slider, describe UI, take a screenshot, record video, or batch simulator steps.
What you get
The agent can script and verify iOS Simulator UI interactions using AXe commands and batch workflows.
By the numbers
- Documents roughly 20 AXe commands including tap, slider, swipe, drag, gesture, touch, type, button, key, batch, describe
Files
Step 1: Confirm runtime context
1. Identify simulator UDID target first (axe list-simulators). 2. Simulator-interaction AXe commands require --udid <UDID>. Commands like list-simulators and init do not. 3. Run axe describe-ui --udid <UDID> to inspect the full current screen. Use axe describe-ui --point <X,Y> --udid <UDID> to inspect the element at a specific coordinate. Use the output to discover available --id and --label values for selector taps and slider setting, and to confirm coordinates for coordinate-based taps. 4. Prefer selectors (tap --id / tap --label, slider --id / slider --label) over raw coordinates. Selectors are resilient to layout changes, work across device sizes, and support element waiting where documented. For UIKit UISwitch and SwiftUI Toggle rows, selector taps activate the contained switch/toggle when the match contains exactly one such control. Default tap style is automatic: switches/toggles use physical touch down/up, while normal taps use simulator tapAt.
Step 2: Choose the right command
Available commands: init, tap, slider, swipe, drag, gesture, touch, type, button, key, key-sequence, key-combo, batch, describe-ui, screenshot, record-video, stream-video, list-simulators. Run axe --help or axe <command> --help for full options.
Common examples:
axe tap --id <identifier> --udid <UDID>
axe tap --label <text> --udid <UDID>
axe tap --label 'Weather Alerts' --udid <UDID>
axe slider --id <identifier> --value 75 --udid <UDID>
axe slider --label <text> --value 40 --element-type Slider --udid <UDID>
axe drag --start-x <X1> --start-y <Y1> --end-x <X2> --end-y <Y2> --udid <UDID>
axe tap -x <X> -y <Y> --tap-style physical --udid <UDID>
axe tap -x <X> -y <Y> --udid <UDID>
axe type 'text' --udid <UDID>
axe describe-ui --udid <UDID>
axe describe-ui --point <X,Y> --udid <UDID>
axe screenshot --udid <UDID> --output screenshot.pngStep 3: Understand the execution model
Most HID commands (tap, swipe, drag, type, key, etc.) are fire-and-forget — AXe confirms the event was dispatched to the simulator but cannot verify the app actually processed it. A tap may land before a view is interactive, or during a transition. slider is the exception: it performs one selector-resolved low-level HID drag, re-reads the matched slider AXValue, and fails if the observed 0-100 value is outside tolerance. iOS slider controls quantize values to their rendered track resolution, so AXe does not retry correction gestures to chase unreachable decimals. This means:
- Always verify outcomes separately with
describe-uiorscreenshotwhen app behavior matters beyond the direct command result. - Use
--wait-timeoutin batch to wait for tap elements to appear, andsleepsteps or--pre-delay/--post-delayto allow animations to settle.
Step 4: Apply timing and input best practices
- Use
--pre-delay/--post-delayon tap, swipe, and gesture commands for fixed delays around actions. - Use
--durationto control how long a swipe, gesture, button press, or key press lasts. - Coordinate-based
tap,swipe,drag, andtouchaccept coordinates fromdescribe-uidirectly; AXe detects rotated landscape simulator orientation and letterboxed landscape-only app layouts automatically. - Use
axe slider --id <identifier> --value <0-100>for sliders instead of approximating with raw swipe coordinates; it uses one calibrated low-level HID drag from the resolved slider frame/current AXValue, through the same composite touch-move path asdrag, verifies the result within tolerance, and fails clearly if the observed AXValue remains outside tolerance. - For text with shell-sensitive characters, prefer
--stdinor--fileover inline quotes. - Use single quotes for inline text arguments to avoid shell expansion issues.
Step 5: Batch vs discrete commands
Prefer `axe batch` for multi-step flows. Batch executes every step in a single process invocation, which means:
- One tool call and one AI turn instead of many — significantly reduces agent latency and cost.
- A single HID session is reused across all steps, lowering per-step overhead.
- Steps execute sequentially — each step runs before the next is resolved, so earlier taps can trigger navigation and later selector taps will find newly appeared elements (with
--wait-timeout).
Fall back to discrete commands when:
- A step's parameters depend on runtime inspection of a previous step's result (e.g. parsing
describe-uiJSON to choose coordinates dynamically). - Using
slider; batch steps do not support slider verification.
Handling animations and transitions in batch:
- Use
--wait-timeout <seconds>so selector taps (--id/--label) poll the accessibility tree until the element appears or the timeout expires. This is the primary mechanism for multi-screen flows. - Use
--poll-interval <seconds>to control polling frequency during waiting (default 0.25s). - Use
--ax-cache perStepwhen not using--wait-timeoutbut the UI still changes between steps — this ensures each selector tap gets a fresh accessibility snapshot rather than a stale cached one. - Insert explicit
sleep <seconds>steps when coordinate-based taps need the UI to be stable (selectors with--wait-timeoutare preferred over sleep where possible). - Keep batch output quiet by default. Add
--verboseonly when troubleshooting. - Selector taps in batch share direct
tapsemantics, including switch/toggle activation-point handling and--tap-style automaticbehavior. Use batch-level--tap-style physical|simulatoras the default for tap steps, or step-leveltap --tap-style ...to override one step. - If
tap --labelreports multiple matches and noAXUniqueIdvalues are exposed, fall back totap -x/-yfor that step.
Key rules:
- Use exactly one step source per run:
--step,--file, or--stdin. - Steps run in order; default is fail-fast.
- Add
--continue-on-errorfor best-effort execution. - Do not pass
--udidinside step lines; keep it at batch level.
Step 6: Verify outcomes
Batch and individual commands are execution-focused, not assertion-focused. Always suggest verification when outcomes matter:
axe describe-ui --udid <UDID>
axe describe-ui --point <X,Y> --udid <UDID>
# or
axe screenshot --udid <UDID> --output post-state.pngStep 7: Exit criteria
Before finalising guidance, verify:
- Every command includes
--udid. - Only valid AXe commands and flags are used.
- Shell quoting is correct (single quotes for literals,
--stdin/--filefor complex text). - Verification is suggested as a separate step when results matter.
AXe Batch Reference
Use this reference when generating or reviewing axe batch commands.
Supported step commands
tapswipegesturetouchtypebuttonkeykey-sequencekey-combosleep <seconds>(batch pseudo-step)
Batch flags
--udid <UDID>: required simulator target.--step "...": repeatable inline step source.--file <path>: read one step per line from file.--stdin: read one step per line from stdin.--continue-on-error: keep running after a failed step; report failures at end.--ax-cache perBatch|perStep|none: selector tap AX snapshot reuse policy.--type-submission chunked|composite: submission mode fortypesteps.--type-chunk-size <n>: chunk size when using chunked submission.--tap-style automatic|simulator|physical: default tap event style for tap steps.--wait-timeout <seconds>: maximum seconds to poll for selector-based elements before failing (0 = no waiting, default).--poll-interval <seconds>: seconds between accessibility tree polls when--wait-timeoutis active (default 0.25).--verbose: enable detailed stderr logs for troubleshooting (default quiet output).
Input rules
- Use exactly one source:
--stepOR--fileOR--stdin. - Empty lines are ignored.
#comment lines are ignored in file/stdin input.- Do not pass
--udidinside step lines; keep it at batch command level.
Example: inline steps
axe batch --udid SIMULATOR_UDID \
--step "tap --id EmailField" \
--step "type 'cam@example.com'" \
--step "key 43" \
--step "type 'super-secret'" \
--step "key 40"Example: stdin steps
cat <<'EOF' | axe batch --udid SIMULATOR_UDID --stdin
tap --id EmailField
type 'cam@example.com'
key 43
type 'super-secret'
key 40
EOFExample: file steps
login.steps
# login flow
tap --id EmailField
type 'cam@example.com'
key 43
type 'super-secret'
key 40Run:
axe batch --udid SIMULATOR_UDID --file login.stepsExample: explicit timing and policy
axe batch --udid SIMULATOR_UDID \
--ax-cache perStep \
--type-submission chunked \
--type-chunk-size 150 \
--continue-on-error \
--step "tap --label Settings" \
--step "sleep 0.5" \
--step "tap --id SaveButton"Example: multi-screen flow with element waiting
axe batch --udid SIMULATOR_UDID \
--wait-timeout 5 \
--step "tap --id LoginButton" \
--step "tap --id WelcomeMessage"The second step polls for up to 5 seconds for WelcomeMessage to appear after the login tap triggers navigation.
Example: toggling a setting switch
axe batch --udid SIMULATOR_UDID \
--step "tap --label 'Weather Alerts'"Batch selector taps share direct axe tap behavior. If the matched row or label contains exactly one UIKit UISwitch or SwiftUI Toggle/switch control, AXe taps that control's activation point. With default --tap-style automatic, switch/toggle activations use physical touch down/up and normal taps use simulator tapAt.
If label selectors are ambiguous and AXe reports no AXUniqueId values for matches, switch that step to coordinates (tap -x/-y). For coordinate taps that need physical touch, use tap -x/-y --tap-style physical or batch-level --tap-style physical.
AXe CLI Reference
Comprehensive reference for all AXe commands. Most simulator-interaction commands require --udid <UDID> unless noted.
Simulator discovery
axe list-simulatorsNo --udid needed. Lists all available simulators with their UDIDs and boot state.
Tap
# By coordinates
axe tap -x 100 -y 200 --udid <UDID>
# By accessibility identifier (preferred)
axe tap --id "SearchField" --udid <UDID>
# By accessibility label
axe tap --label "Safari" --udid <UDID>
axe tap --label "Weather Alerts" --udid <UDID> # Auto physical touch for switches/toggles
axe tap --label "Submit" --tap-style simulator --udid <UDID>
axe tap -x 320 -y 780 --tap-style physical --udid <UDID>
# With timing
axe tap -x 100 -y 200 --pre-delay 1.0 --post-delay 0.5 --udid <UDID>Slider
# Value is a percentage from 0 to 100
axe slider --id "volume-slider" --value 75 --udid <UDID>
axe slider --label "Volume" --value 40 --element-type Slider --udid <UDID>slider resolves the matched accessibility slider, uses its frame/current AXValue for one calibrated low-level HID drag through the same composite touch-move path as drag, and re-reads AXValue. Since iOS slider controls quantize values to their rendered track resolution, AXe verifies that the observed value is within tolerance rather than retrying correction gestures to chase unreachable decimals. If the observed value remains outside tolerance, the command fails clearly.
Swipe
axe swipe --start-x 100 --start-y 300 --end-x 300 --end-y 100 --udid <UDID>
# With duration and delta
axe swipe --start-x 50 --start-y 500 --end-x 350 --end-y 500 --duration 2.0 --delta 25 --udid <UDID>
# With timing
axe swipe --start-x 100 --start-y 300 --end-x 300 --end-y 100 --pre-delay 1.0 --post-delay 0.5 --udid <UDID>Drag (low-level)
axe drag --start-x 100 --start-y 400 --end-x 300 --end-y 400 --udid <UDID>
axe drag --start-x 100 --start-y 400 --end-x 300 --end-y 400 --duration 0.4 --steps 40 --udid <UDID>drag emits one composite low-level HID event: touch down at the start point, a sequence of explicit touch move events, then touch up at the end point.
Touch (low-level)
axe touch -x 150 -y 250 --down --udid <UDID> # Touch down only
axe touch -x 150 -y 250 --up --udid <UDID> # Touch up only
axe touch -x 150 -y 250 --down --up --udid <UDID> # Tap
axe touch -x 150 -y 250 --down --up --delay 1.0 --udid <UDID> # Long pressGesture presets
axe gesture scroll-up --udid <UDID>
axe gesture scroll-down --udid <UDID>
axe gesture scroll-left --udid <UDID>
axe gesture scroll-right --udid <UDID>
axe gesture swipe-from-left-edge --udid <UDID>
axe gesture swipe-from-right-edge --udid <UDID>
axe gesture swipe-from-top-edge --udid <UDID>
axe gesture swipe-from-bottom-edge --udid <UDID>
# With custom screen dimensions
axe gesture scroll-up --screen-width 430 --screen-height 932 --udid <UDID>
# With custom duration/delta
axe gesture scroll-up --duration 2.0 --delta 100 --udid <UDID>
# With timing
axe gesture scroll-down --pre-delay 1.0 --post-delay 0.5 --udid <UDID>Preset reference
| Preset | Description | Default Duration | Default Delta |
|---|---|---|---|
scroll-up | Scroll up in centre | 0.5s | 25px |
scroll-down | Scroll down in centre | 0.5s | 25px |
scroll-left | Scroll left in centre | 0.5s | 25px |
scroll-right | Scroll right in centre | 0.5s | 25px |
swipe-from-left-edge | Left edge to right | 0.3s | 50px |
swipe-from-right-edge | Right edge to left | 0.3s | 50px |
swipe-from-top-edge | Top to bottom | 0.3s | 50px |
swipe-from-bottom-edge | Bottom to top | 0.3s | 50px |
Text input
# Inline (use single quotes)
axe type 'Hello World!' --udid <UDID>
# From stdin (best for automation / special characters)
echo "Complex text with any characters!" | axe type --stdin --udid <UDID>
# From file
axe type --file input.txt --udid <UDID>Keyboard
# Single key press by HID keycode
axe key 40 --udid <UDID> # Enter
axe key 42 --duration 1.0 --udid <UDID> # Hold Backspace
# Key sequence
axe key-sequence --keycodes 11,8,15,15,18 --udid <UDID> # "hello"
axe key-sequence --keycodes 40,40,40 --delay 0.5 --udid <UDID>
# Key combo (modifier + key, atomic)
axe key-combo --modifiers 227 --key 4 --udid <UDID> # Cmd+A
axe key-combo --modifiers 227 --key 6 --udid <UDID> # Cmd+C
axe key-combo --modifiers 227 --key 25 --udid <UDID> # Cmd+V
axe key-combo --modifiers 227,225 --key 4 --udid <UDID> # Cmd+Shift+ACommon keycodes
| Key | Code | Key | Code | Key | Code |
|---|---|---|---|---|---|
| Enter | 40 | Escape | 41 | Backspace | 42 |
| Tab | 43 | Space | 44 | a | 4 |
| LeftGUI (Cmd) | 227 | LeftShift | 225 | LeftCtrl | 224 |
| LeftAlt | 226 | F1 | 58 | F12 | 69 |
Hardware buttons
axe button home --udid <UDID>
axe button lock --udid <UDID>
axe button lock --duration 3.0 --udid <UDID> # Long press
axe button side-button --udid <UDID>
axe button siri --udid <UDID>
axe button apple-pay --udid <UDID>Batch (multi-step workflows)
# Inline steps
axe batch --udid <UDID> \
--step "tap --id SearchField" \
--step "type 'hello world'" \
--step "key 40"
# From stdin
cat <<'EOF' | axe batch --udid <UDID> --stdin
tap --id SearchField
type 'hello world'
key 40
EOF
# From file
axe batch --udid <UDID> --file steps.txt
# With options
axe batch --udid <UDID> \
--continue-on-error \
--ax-cache perStep \
--type-submission chunked \
--type-chunk-size 150 \
--tap-style automatic \
--step "tap --label Settings" \
--step "sleep 0.5" \
--step "tap --id SaveButton"
# With element waiting (polls for elements that appear after navigation)
axe batch --udid <UDID> \
--wait-timeout 5 \
--step "tap --id LoginButton" \
--step "tap --id WelcomeMessage"
# Toggle a setting switch by label
axe batch --udid <UDID> \
--step "tap --label 'Weather Alerts'"See batch-reference.md for full batch semantics.
Accessibility / UI inspection
axe describe-ui --udid <UDID> # Full screen
axe describe-ui --point 100,200 --udid <UDID> # Specific pointScreenshot
axe screenshot --udid <UDID> # Auto-named
axe screenshot --output ~/Desktop/shot.png --udid <UDID> # Specific file
axe screenshot --output ~/Desktop/ --udid <UDID> # Directory (auto-named)Video recording
axe record-video --udid <UDID> --fps 15 --output recording.mp4
axe record-video --udid <UDID> --fps 10 --quality 60 --scale 0.5 --output low-bw.mp4Press Ctrl+C to stop recording. AXe finalises the MP4 before exiting.
Video streaming
axe stream-video --udid <UDID> --fps 10 --format mjpeg > stream.mjpeg
axe stream-video --udid <UDID> --fps 30 --format ffmpeg | \
ffmpeg -f image2pipe -framerate 30 -i - -c:v libx264 -preset ultrafast output.mp4Timing parameters
| Parameter | Range | Description | Available on |
|---|---|---|---|
--pre-delay | 0–10s | Delay before action | tap, swipe, drag, gesture |
--post-delay | 0–10s | Delay after action | tap, swipe, drag, gesture |
--duration | 0–10s | Action duration | swipe, drag, gesture, button, key |
--steps | 1–1000 | Touch move event count | drag |
--value | 0–100 | Target slider percentage | slider |
--delay | 0–5s | Between-item delay | key-sequence, touch |
Best practices
- Prefer
--id/--labelselectors over coordinates for resilience; usesliderfor selector-resolved low-level HID slider dragging with AXValue tolerance verification instead of raw swipe coordinates, and usedragwhen you specifically need raw point-to-point HID drag behavior. - Selector taps activate a contained UIKit
UISwitchor SwiftUITogglewhen the matched row or label contains exactly one switch/toggle. - Default
--tap-style automaticuses physical touch for matched switches/toggles and simulatortapAtfor normal taps; use--tap-style physical|simulatorto override. - Use single quotes for inline text to avoid shell expansion.
- Use
--stdinor--filewhen input contains shell-sensitive characters. - Keep verification (
describe-ui,screenshot) separate from execution.
Related skills
FAQ
How does axe select UI elements?
It prefers --id and --label selectors over raw coordinates because selectors are resilient to layout changes and work across device sizes.
Why use axe batch?
Batch executes every step in a single process invocation, reusing one HID session, so a multi-step flow uses one tool call instead of many.