Trigger UI elements programmatically via HTTP automation. Use when you need to press buttons, interact with UI, or verify UI changes...
This skill allows Claude to programmatically trigger UI elements in the running iOS or Android app by sending HTTP requests to the test server. Each UI element is registered with a unique ID and can be triggered remotely, enabling automated UI interaction and testing workflows.
Invoke this skill when you need to:
Trigger phrases:
Port forwarding must be active: The test server on port 8081 must be forwarded from the device to localhost:
# iOS (keep running in background)
pymobiledevice3 usbmux forward 8081 8081 &
# Android
adb forward tcp:8081 tcp:8081
App must be running: The iOS or Android app must be running on the connected device with the test server active.
Element must be registered: The UI element must have been registered with the UIAutomationRegistry using a unique ID. Common registered elements include:
toolbar-home - Home button in toolbartoolbar-plus - New post button in toolbartoolbar-search - Search button in toolbartoolbar-profile - Profile button in toolbarCheck that port forwarding is active and the app is running:
curl http://localhost:8081/test/ping
Should return "succeeded". If not, set up port forwarding first.
Determine the ID of the UI element you want to trigger. Element IDs are defined in the app code when registering with UIAutomationRegistry. Common patterns:
toolbar-[icon-name] (e.g., toolbar-plus, toolbar-home)Send a POST request to the test server:
curl -X POST 'http://localhost:8081/test/tap?id=ELEMENT_ID'
Replace ELEMENT_ID with the actual element identifier.
The response will be JSON indicating success or failure:
Success:
{"status": "success", "id": "toolbar-plus"}
Failure (element not found):
{"status": "error", "message": "Element not found: invalid-id"}
After triggering the element, capture a screenshot to verify the UI change:
# iOS
/Users/asnaroo/Desktop/experiments/miso/miso/platforms/ios/development/screen-capture/imp/screenshot.sh /tmp/ui-result.png
# Android
adb exec-out screencap -p > /tmp/ui-result.png
Then read the screenshot to verify the expected UI change occurred.
# Tap the + button to open new post editor
curl -X POST 'http://localhost:8081/test/tap?id=toolbar-plus'
# Capture screenshot to verify editor appeared
/Users/asnaroo/Desktop/experiments/miso/miso/platforms/ios/development/screen-capture/imp/screenshot.sh /tmp/new-post-editor.png
# Tap home button to return to recent posts view
curl -X POST 'http://localhost:8081/test/tap?id=toolbar-home'
# Verify we're on the home view
/Users/asnaroo/Desktop/experiments/miso/miso/platforms/ios/development/screen-capture/imp/screenshot.sh /tmp/home-view.png
# 1. Navigate to profile
curl -X POST 'http://localhost:8081/test/tap?id=toolbar-profile'
sleep 0.5 # Wait for navigation
# 2. Open new post editor from profile
curl -X POST 'http://localhost:8081/test/tap?id=toolbar-plus'
sleep 0.5 # Wait for sheet to appear
# 3. Verify final state
/Users/asnaroo/Desktop/experiments/miso/miso/platforms/ios/development/screen-capture/imp/screenshot.sh /tmp/profile-new-post.png
Problem: Port forwarding is not active or test server is not running.
Solutions:
pymobiledevice3 usbmux forward 8081 8081adb forward tcp:8081 tcp:8081curl http://localhost:8081/test/pingProblem: The element ID is not registered or misspelled.
Solutions:
.onAppear)[TESTSERVER] prefixProblem: The registered action doesn't match expectations.
Solutions:
Problem: Screenshot captured before UI update completed.
Solutions:
sleep 0.5sleep 1.0UIAutomationRegistry.shared.register(id:action:)POST /test/tap?id=X requestsDispatchQueue.main.asyncRecommended: View Modifier Pattern (Clean, declarative)
In SwiftUI views, use the .uiAutomationId() modifier directly on buttons or other interactive elements:
Button(action: {
// Normal button action
isEditing = true
}) {
Image(systemName: "pencil.circle.fill")
}
.uiAutomationId("edit-button") {
// Automation action (usually same as button action)
isEditing = true
}
Benefits:
.onAppear, no manual registration neededLegacy: Manual Registration Pattern (Verbose, requires plumbing)
In SwiftUI views:
.onAppear {
UIAutomationRegistry.shared.register(id: "unique-id") {
// Action to perform (state changes, navigation, etc.)
}
}
Note: Manual registration is still useful for non-button elements like gesture recognizers or complex views. For buttons, prefer the modifier pattern.
In Kotlin composables (recommended pattern):
@Composable
fun MyButton() {
// Register for automation (auto-unregisters on dispose)
RegisterUIElement("my-button") {
// Action to perform
}
Button(onClick = { /* same action */ }) {
Text("Click")
}
}
Or using the modifier extension:
Button(
onClick = { /* action */ },
modifier = Modifier.uiAutomationId("my-button") { /* action */ }
) {
Text("Click")
}
toolbar-plus, profile-edit)ios-deploy-usb - Deploy app with new UI elementsiphone-screen-capture - Continuous screen mirroringupdate-skill - Improve this skill based on usagecurl http://localhost:8081/test/list-elements
Response:
{"elements": ["toolbar-plus", "refresh-button"], "textFields": ["search-field"]}
curl -X POST 'http://localhost:8081/test/set-text?id=search-field&text=hello'
Response:
{"status": "success", "id": "search-field", "text": "hello"}