| name | qa-device-management |
| description | Boot and control iOS Simulators and Android Emulators for QA testing using agent-device CLI. Manage sessions, capture screenshots, launch apps, and control devices across platforms. Invoke when user says "bring up simulators", "boot the device", "take a screenshot", "launch the app", "compare iOS and Android", "test both platforms", "visual parity check", or any task requiring device/simulator lifecycle management.
|
| allowed-tools | Bash(agent-device:*) Bash(xcrun:*) Bash(adb:*) Bash(open:*) Bash(find:*) Bash(npx:*) Read |
qa-device-management
Side-by-side iOS Simulator and Android Emulator control using the agent-device CLI. Manages the device lifecycle for all QA Automation skills.
When to Use
- Bringing up simulators/emulators for testing
- Launching your app on one or both platforms
- Capturing baseline or comparison screenshots
- Checking device state, app state, or accessibility tree
- Managing agent-device sessions across platforms
Configuration
All device settings are in qa.config.sh. Set these before using:
export APP_BUNDLE_ID="com.yourapp.dev"
export SIMULATOR_UDID="auto"
export SIMULATOR_DEVICE_NAME="iPhone 16 Pro"
export ANDROID_AVD="Pixel_8"
export ANDROID_SERIAL="emulator-5554"
Quick Start — Full Startup Sequence
Boot iOS Simulator
source .pi/skills/qa-automation/qa.config.sh
UDID=$(qa_detect_simulator_udid)
xcrun simctl boot "$SIMULATOR_UDID" 2>&1 || true
open -a Simulator
Boot Android Emulator
nohup $EMULATOR_PATH -avd "$ANDROID_AVD" -no-snapshot-load > /tmp/qa-emu.log 2>&1 &
for i in $(seq 1 30); do
BOOT=$($ADB_PATH shell getprop sys.boot_completed 2>/dev/null | tr -d '\r')
if [ "$BOOT" = "1" ]; then
echo "Android emulator booted after ~$((i*2))s"
break
fi
sleep 2
done
Verify Both Devices
agent-device devices --json
Launch App on iOS
agent-device open "$APP_BUNDLE_ID" --platform ios --session default
Launch App on Android
agent-device open "$APP_BUNDLE_ID" --platform android --serial "$ANDROID_SERIAL" --session android
Capture Baseline Screenshots
agent-device screenshot /tmp/qa-ios-baseline.png --session default
agent-device screenshot /tmp/qa-android-baseline.png --session android
Session Management
agent-device binds each session to one platform. Use the correct session flag:
| Platform | Session Flag | Example |
|---|
| iOS | --session default (or omit) | agent-device snapshot --session default |
| Android | --session android | agent-device snapshot --session android |
agent-device session list
agent-device close --session default
Common Operations
Screenshots (Both Platforms)
agent-device screenshot /tmp/qa-ios.png --session default
agent-device screenshot /tmp/qa-android.png --session android
Accessibility Snapshots
agent-device snapshot --session default
agent-device snapshot --session android
agent-device snapshot -i --session default
agent-device snapshot --depth 3
Navigate and Interact
agent-device click 200 400 --session default
agent-device swipe 200 800 200 200 --session default
agent-device scroll down --session default
agent-device fill @e3 "hello world" --session default
Go Home / Go Back
agent-device home --session default
agent-device back --session android
Check Foreground App
agent-device appstate --session default
agent-device appstate --session android
Relaunch App (Fresh State)
agent-device open "$APP_BUNDLE_ID" --session default --relaunch
Building and Installing Your App
iOS — Expo
cd "$PROJECT_DIR"
npx expo run:ios --device "$SIMULATOR_DEVICE_NAME"
iOS — React Native CLI
cd "$PROJECT_DIR"
npx react-native run-ios --simulator "$SIMULATOR_DEVICE_NAME"
Android — Expo
cd "$PROJECT_DIR"
npx expo run:android
Android — React Native CLI
cd "$PROJECT_DIR"
npx react-native run-android
Check If App Is Installed
xcrun simctl listapps booted 2>/dev/null | grep "$APP_BUNDLE_ID"
$ADB_PATH shell pm list packages | grep "$APP_BUNDLE_ID"
Shutdown Sequence
agent-device close --session default
agent-device close --session android
xcrun simctl shutdown "$SIMULATOR_UDID"
$ADB_PATH emu kill
CDP Connection (for React Native apps)
When coordinate-based tapping fails (e.g., full-screen video players intercept touches), use CDP to control navigation directly via the React Native Hermes runtime.
Prerequisites
- Dev server running (e.g.,
npx expo start)
ws npm package available
Discover CDP Endpoints
curl -s http://localhost:$METRO_PORT/json
source qa.config.sh
qa_detect_cdp_ws_url
Navigate via CDP
source .pi/skills/qa-automation/qa-test-flows/lib/cdp-helpers.sh
cdp_navigate "SettingsScreen"
cdp_navigate_tab "ProfileScreen"
cdp_get_route
Troubleshooting
| Problem | Solution |
|---|
| "No device found" | Verify simulator is booted: xcrun simctl list devices | grep Booted |
| Session bound to wrong platform | Use --session android for Android, close session and rebind |
| Simulator already booted (error 149) | Safe to ignore — simulator is already running |
| App not installed | Build and install: npx expo run:ios or npx expo run:android |
| agent-device click hangs | Wrap with timeout: timeout 5 agent-device click 100 200 |
| CDP "Connection refused" | Ensure dev server is running: curl http://localhost:$METRO_PORT/status |