๐งฐ Tools¶
Every tool works from the CLI (bunx @kaeawc/auto-mobile --cli <tool>), MCP, or the daemon HTTP endpoint โ same names, same arguments.
๐ Full arguments: the registered schema (schemas/tool-definitions.json) or automobile:tools. Availability varies by platform and feature gates.
๐ท๏ธ Tool discovery metadata¶
- ๐
tools/listentries carry a human-readabletitleand SDKToolAnnotations. - ๐ก๏ธ Hints are untrusted client guidance, never authorization.
- ๐๏ธ Classification lives in
src/server/toolAnnotations.ts. - ๐ Mixed-action tools take the conservative union of all supported actions.
- ๐ฆ The wire omits default
readOnlyHint: false,idempotentHint: false, andopenWorldHint: true. - ๐ Read-only tools omit the meaningless destructive and idempotent hints.
- ๐๏ธ Controls always declare
destructiveHintexplicitly. - ๐ Metadata is independent of
deviceReadOnlydispatch and ownership enforcement. - ๐งช
readOnlyHintfollowsdeviceReadOnly, except tools that also write host state (compareScreenshotrecord mode).
๐ Shared options¶
- ๐
sessionUuidโ run on a held device session (device tools) - ๐ก
keepScreenAwakeโ wake and keep a physical Android device awake (default on at session setup) - ๐ช
raw/project(skeletondefault,full) /includeExtrasโ observation output on action tools - ๐
resourceLinkโgetLogs,exportPlan, andvideoRecordingstop: return the complete result as anautomobile:tool-outputresource and aresource_linkblock, keeping onlysuccess,error, and the result’s required fields (a stop’saction,count,recordings, each bounded) inline (default off, inline) - ๐ฑ
deviceIdโ target a device explicitly on reads
Reading a device you do not own (deviceId)¶
A read never writes settings on a device another session holds. A sessionless read of an unheld running device may ready it (install CtrlProxy / runner) to answer. See which read tools ready an unheld device.
๐ Observe & navigate¶
| Tool | What it does |
|---|---|
๐ธ snapshotOf |
Save a PNG crop of an element or screen rectangle |
๐ compareScreenshot |
Record or compare a named screenshot baseline |
๐๏ธ observe |
Read the current screen, hierarchy, and screenshot |
๐ฏ hitTest |
Preview what a tap at a point would hit, without tapping |
๐งญ explore |
Automatically explore app to build navigation graph |
๐บ๏ธ navigateTo |
Navigate to screen using navigation graph |
๐ธ๏ธ getNavigationGraph |
Get navigation graph for debugging |
๐ identifyInteractions |
Suggest likely interactions |
๐งช prototype |
Show agent-authored UI on the device |
๐ฆ highlight |
Draw a red hand-drawn circle around a UI element |
๐ Interact¶
| Tool | What it does |
|---|---|
๐ tapAt |
Tap, long press, or double tap at screen coordinates in native, normalized, or percent units |
๐ tapOn |
Tap an element by text, id, or test tag |
๐ค tapAny |
Tap any clickable element; scope with container or scrollableContainer |
๐ swipeOn |
Swipe/scroll on screen or elements |
โ๏ธ swipeAt |
Swipe between two screen points |
๐ซณ dragAndDrop |
Drag and drop element |
ใฐ๏ธ dragPath |
Drag a finger along a timed path |
๐ฑ๏ธ hoverAt |
Hover a stylus or mouse over a path with no contact (Android) |
๐ค pinchOn |
Pinch to zoom |
๐๏ธ multiTouch |
Simultaneous 2-5 finger tap, long press, or swipe at a screen point |
โจ๏ธ sendKeys |
Execute ordered typing, clear, raw-key, and semantic IME commands |
๐งญ focusNavigate |
Move D-pad focus to an element on Android TV; stops focused, max_steps or stuck |
๐๏ธ setUIState |
Set multiple form fields by desired state |
๐ selectAllText |
Select all text in focused input |
๐ pressButton |
Press a device or navigation button |
โจ๏ธ keyboard |
Open, close, detect, or switch the keyboard / IME |
๐ clipboard |
Clipboard operations (copy/paste/clear/get) |
๐ฃ๏ธ siri |
iOS: activate Siri with a phrase (off by default: setToolEnabled; needs the siriAndAppIntents service) (e.g. an App Shortcut), returns the observation; Android returns unsupported |
๐ฆ Apps, files & data¶
| Tool | What it does |
|---|---|
๐๏ธ listApps |
List installed apps |
๐ launchApp |
Launch app by package name |
๐ terminateApp |
Terminate app by package name |
๐ฅ crashApp |
Intentionally crash a running app through the platform crash path |
๐ appLifecycle |
Background-kill an app to test state restoration (Android; iOS background and SIGKILL) |
โฌ๏ธ installApp |
Install app on device (.apk, split APKs, .apks, .aab, .app, or .ipa) |
๐๏ธ uninstallApp |
Uninstall app by package name or bundle identifier |
๐ inspectPackageSigning |
Fresh read of one app’s presence (installed/absent/unknown) and signing |
๐ getDeepLinks |
Query app deep links |
๐ฅ putAppFile |
Write files into a bounded logical storage target |
๐งน resetAppLogs |
Reset named app log files |
โ๏ธ getPreference |
Read an Android system property, Android SharedPreferences key, or iOS UserDefaults key |
โ๏ธ setPreference |
Write a system property, SharedPreferences, or UserDefaults key |
๐๏ธ deleteKeychainItem |
Delete one allowlisted app-owned iOS Keychain item (SDK opt-in, requires confirm) |
๐ setKeyValue |
Set app key-value storage entry |
โ removeKeyValue |
Remove app key-value storage entry |
๐งผ clearKeyValueFile |
Clear app key-value storage file |
๐๏ธ listDataStores |
List app Jetpack DataStore instances (Android, requires AutoMobile SDK adapter) |
๐๏ธ getDataStore |
Read entries from an app Jetpack DataStore instance (Android, requires AutoMobile SDK adapter) |
๐งฎ sqlQuery |
Execute SQL on app SQLite database |
๐ resetKeychain |
Reset an app’s Keychain/Keystore state (scoped by appId) |
๐ setAppLinks |
Android 12+: change an app’s App Links state so https links open the app directly (or not) |
โฑ๏ธ measureStartup |
Measure cold/warm/hot app startup |
๐ getLogs |
Read device logs with filters |
๐ก sendBroadcast |
Send an Android broadcast to the app under test |
๐ ๏ธ backgroundWork |
Android: read and trigger an app’s background work without waiting hours |
๐ฑ Devices & system¶
| Tool | What it does |
|---|---|
๐ listDevices |
List booted devices |
๐ฟ listDeviceImages |
List device images |
๐ค getAndroid |
Find or recover an Android AVD and prepare it for automation |
๐ getApple |
Find or recover an iOS Simulator and prepare it for automation |
๐๏ธ provisionDevice |
Provision exact virtual device |
๐งฐ setDeviceResources |
Set selected device resources and verify native state |
โ๏ธ reconcileDeviceResources |
Compare a simulator to a requested resource map |
โ
setActiveDevice |
Pick the active device for this connection |
๐ killDevice |
Kill device |
๐๏ธ deleteDevice |
Stop and permanently delete a device, with verified platform-inventory absence |
๐พ deviceSnapshot |
Capture or restore device snapshot |
๐ rotate |
Rotate device orientation |
๐ setPosture |
Set foldable / Duo posture |
๐ถ statusBar |
Pin status-bar time, battery, and signal for clean screenshots |
๐ช windowMode |
Fullscreen, PiP, or split-screen an Android task |
๐๏ธ rotaryScroll |
Wear OS crown scroll with read-back; reports every attempted method |
โ rotateCrown |
watchOS: rotate the Digital Crown by a signed delta with optional velocity |
๐ openLink |
Open URL in browser |
๐ homeScreen |
Go to home screen |
๐ recentApps |
Open recent apps |
๐ systemTray |
System tray actions for notifications (open/close/list/find/tap/dismiss/clearAll) |
๐ wakeAndUnlock |
Wake a device and unlock its keyguard |
๐ changeLocalization |
Change locale, time zone, text direction, time format, and calendar system |
๐ฉบ getDeviceState |
Read clock, DND, connectivity, and other device state |
๐ง setDeviceState |
Set DND, airplane mode, and other device state |
๐ฅ๏ธ displayConfig |
Read or set font scale, density, and display size |
๐จ displayProfile |
Apply an OEM-style display profile (Android) |
๐ getIosSimulatorCapabilities |
Discover biometric capabilities for a selected iOS Simulator device type and runtime |
๐ชช biometricAuth |
Simulate biometric success or failure |
๐ณ shake |
Shake the device (simulator/emulator) |
๐งฒ setSensor |
Set an emulator sensor (accelerometer, gyro, โฆ) |
๐๏ธ injectAudioInput |
Emulator or simulator: play a WAV file or tone into the microphone. Off by default |
โน๏ธ stopAudioInput |
Stop an audio injection. Off by default |
๐ captureAudio |
Emulator or simulator: record audio output and report its level. Off by default |
๐ phoneCall |
Simulate an incoming phone call |
๐ฌ sendSms |
Simulate an incoming SMS |
๐ต mediaSession |
Read or control Android media sessions |
๐ฃ postNotification |
Post notification via Android SDK hooks or iOS Simulator simctl push |
๐ getNotificationPolicy |
Read app notification/DND policy state |
๐ setNotificationPolicy |
Set app notification/DND policy state |
๐ getAppPermissions |
Read app permission state |
๐ setAppPermissions |
userId grant/revoke; device-wide reset [‘all’]; Android notification state |
โ ๏ธ killProfile |
Simulate an OEM background-kill policy (Android) |
๐ญ manufacturerProfile |
Approximate an OEM device (Android) |
โ ๏ธ systemAlerts |
Auto-answer OS permission and system alerts |
๐ Network, plans & recording¶
| Tool | What it does |
|---|---|
๐ถ network |
Control network capture and error simulation |
๐ญ mockNetwork |
Add mock network response rule |
๐งฝ clearMockNetwork |
Clear mock network response rules |
๐ธ๏ธ getNetworkGraph |
Get aggregate captured network graph |
โถ๏ธ executePlan |
Execute YAML plan steps; stops on first failed step |
๐ criticalSection |
Synchronize multiple devices at a barrier, then run steps serially |
๐ง barrier |
Sync multiple devices at a point in a plan |
โบ๏ธ recordToolCalls |
Record MCP tool calls to YAML |
๐ฌ recordDeviceGestures |
Start recording on-device user input (not tool calls) for exportPlan |
๐ค exportPlan |
Stop active recording and export a YAML plan |
๐ฅ videoRecording |
Start or stop device video recording |
๐ performanceTrace |
Record an xctrace / Perfetto trace; read it back at automobile:device-session/{sessionUuid}/performance-traces/{traceId}{?offset,maxBytes} |
๐ฌ captureTrace |
Android: record a Perfetto trace from typed categories (sched, gfx, view, am, wm, binder_driver, memory, app); stop pulls the .perfetto-trace. Off by default |
๐ง heapDump |
Android: dump a debuggable or profileable app’s heap to a host .hprof (heap_dump_not_debuggable otherwise). Off by default |
โฟ Accessibility & tooling¶
| Tool | What it does |
|---|---|
๐ฆฎ accessibility |
Check or control accessibility services |
๐ฏ accessibilityFocus |
Set or clear Android TalkBack focus by resourceId, text, or contentDesc |
๐ซถ accessibilityAction |
Perform a TalkBack-style accessibility action (Android) |
โ
accessibilityAudit |
Run the platform’s own accessibility audit engine on the current screen |
๐งพ audit |
Audit the current screen on demand |
๐งฉ setToolEnabled |
Show or hide tools in discovery |
๐บ Android TV focus navigation¶
focusNavigate({ until, direction?, maxSteps?, settleMs? }) (#14947) drives focus-based UIs. It observes, and
while the input-focused element (focusedElement) does not match until (text, contentDesc and/or resourceId) it
presses the D-pad arrow toward the nearest match, or direction when given, then observes again. With no focused
element or no match on screen it presses down. It returns the path of focused elements and a status: focused,
max_steps (default 30, at most 100) or stuck (every direction toward the nearest match is blocked on the current element; an explicit direction stops after two unchanged presses). A direction that leaves focus unchanged is skipped for that element for the rest of the call, so steering tries the next-best axis. Activate the focused item
afterwards with sendKeys key enter; Android treats KEYCODE_ENTER and KEYCODE_DPAD_CENTER both as select, so no
separate select key exists. Android only; not yet verified on a TV image
(see docs/design-docs/plat/android/form-factors.md).
๐ Notes¶
- โจ๏ธ Compact observations fold soft-keyboard keys into one
keyboard: { visible: true, package: "โฆ" }summary plus at most one skeleton row (<ime> | Keyboard (โฆ) | input). The row appears only with at least one bounded accessible descendant. - ๐ธ Screenshot paths are kept for at least 10 minutes after return unless evicted early under capacity pressure; each path has a
screenshotExpiresAt/expiresAt(host epoch ms, not a promise). Retention starts at 128 MiB and scales by 64 MiB per active device up to 1 GiB, within a limit of 4096 files. Each deviceโs newest 3 screenshots (counting its incoming frame) are evicted only as a last resort, and a capture is admitted even if nothing fits. The byte limits and per-device allowance are configurable. After a restart, existing files get a process-start grace of ten minutes. - ๐งน
holdSessionOnFailurekeeps plan sessions instead of auto-releasing them.
No audio input (audio_input_unavailable)¶
When a device cannot record audio, observe returns diagnostics: [{ code: "audio_input_unavailable", message, retryable: false }],
and a setAppPermissions grant of microphone (iOS) or RECORD_AUDIO (Android) still succeeds but carries the same
diagnostics entry. This applies to an iOS simulator on a host with no audio input device, and to an Android emulator launched
with -no-audio (AUTOMOBILE_EMULATOR_AUDIO=false) or with hw.audioInput=no. Recordings on that device contain no audio.
Treat this as an environment limitation: do not retry, and do not report it as an app failure. Fix the host (for example, make a
virtual loopback device the default input) or the AVD audio settings. The message names the cause.
Stylus pointer on tapAt, swipeAt and dragPath¶
pointer: { toolType: "stylus" } injects a stylus instead of a finger (Android only; never falls back to a finger).
pointer shape |
Route | Needs |
|---|---|---|
{ toolType: "stylus" }, pressure omitted or 1 (tapAt, swipeAt) |
adb shell input stylus |
Android 12+ (API 31) |
pressure other than 1, tilt (radians, 0 to PI/2), orientation (radians), or buttons (primary, secondary) |
CtrlProxy instrumentation | stylus_input_v1 (Android 12+) |
dragPath with any pointer |
CtrlProxy instrumentation | stylus_input_v1 (Android 12+) |
On an emulator or userdebug build whose adb shell already runs as root (after adb root) and has the uinput tool, a stylus
stroke with pressure and a dragPath also work without stylus_input_v1, through a virtual pen; tilt,
orientation and buttons still need the runner, and each stroke starts about 4 seconds later while the pen attaches.
pointer: { toolType: "eraser" } touches with the pen’s eraser end (apps see TOOL_TYPE_ERASER) on tapAt, swipeAt and
dragPath, with optional pressure. It needs that same root adb shell with the uinput tool, and is refused before any
input everywhere else; tilt, orientation and buttons are refused with an eraser.
dragPath points also take pressure and tilt (they need pointer), interpolated between points; holdMs and
releaseHoldMs become holds at the first and last point. A device or runner that cannot honour the request is refused before
anything is sent, naming the missing capability. tilt, orientation and buttons are Android only; doubleTap and a panel
display are not supported with a stylus yet. Details and the unverified parts are in the
stylus design note.
hoverAt¶
Hover enter, move and exit over points with no contact (Android only; the reasons iOS is refused are in the
stylus design note). It takes the dragPath point shape
(x, y, per-point durationMs) plus an optional per-point distance (stylus only), and the same
coordinateSpace, display, snapshotId and layer.
toolType chooses who hovers, and apps see the difference:
toolType |
What the app receives |
|---|---|
stylus (default) |
ACTION_HOVER_* with TOOL_TYPE_STYLUS, SOURCE_STYLUS and an AXIS_DISTANCE value |
mouse |
ACTION_HOVER_* with TOOL_TYPE_MOUSE and SOURCE_MOUSE; no distance; desktop-style UI |
It needs the hover_input_v1 runner capability, or, for a stylus hover, an adb shell that already runs as
root with a writable /dev/uinput (after adb root on an emulator or userdebug build). A device or runner without either, and iOS, are refused before
anything is sent with the missing capability named, and a hover is never turned into a touch. CtrlProxy
advertises the capability and injects the hover through its UiAutomation instrumentation (see the
stylus design note); the semantics above
are the documented intent and still need on-device confirmation (#13082).
prototype¶
Show agent-authored UI on a device: show, patch, inspect, dismiss {id} / {all: true}, status. Android can hold up to four prototypes (replaceOthers: false); iOS shows one at a time. Features (data model, gestures, checks) require the matching device capability and are refused before upload otherwise. Spec: prototype UX. Camera and media support per runtime: camera and media guide.
Watch-sized mockups¶
Prototypes cannot run on watchOS, but a watch-sized spec gives a quick visual mockup of a watch
screen on an iPhone simulator or Android emulator. Float the window in the centre and give the root
box the watch screen’s size, a large corner radius (which also clips its content) and a black
background:
| Case | width ร height (dp/pt) |
cornerRadius |
|---|---|---|
| 41 mm | 176 ร 215 | 36 |
| 45 mm | 198 ร 242 | 40 |
| 49 mm Ultra | 205 ร 251 | 44 |
{
"id": "watch-41mm",
"window": {
"placement": { "type": "floating", "gravity": "center", "offset": { "x": 0, "y": 0 } }
},
"components": {
"watchRow": {
"root": {
"type": "row",
"style": {
"width": "fill",
"background": "#222222",
"cornerRadius": 16,
"padding": { "start": 10, "end": 10, "top": 8, "bottom": 8 }
},
"children": [{ "type": "text", "text": "{props.title}", "style": { "color": "#FFFFFF" } }]
}
}
},
"root": {
"type": "box",
"style": {
"width": { "dp": 176 },
"height": { "dp": 215 },
"cornerRadius": 36,
"background": "#000000"
},
"children": [
{
"type": "scroll",
"child": {
"type": "column",
"style": { "spacing": 6, "padding": { "start": 8, "end": 8, "top": 12 } },
"children": [
{ "type": "use", "component": "watchRow", "props": { "title": "Drink water" } },
{ "type": "use", "component": "watchRow", "props": { "title": "Stand up" } }
]
}
}
]
}
}
Put each common watch pattern in components and reuse it with use: a vertically scrolling list
of rows, a full-screen metric (one large number with a label and unit), a two-button confirmation
(two buttons with weight: 1 in a row, swapped in with visibleWhen), and a now-playing card
(title, artist, previous / play-pause / next iconButtons and a linear progress).
The mockup is a phone overlay sized like a watch. It does not simulate the Digital Crown, Always-On or wrist-down dimming, real watchOS or Wear OS fonts and controls, or the round Wear OS screen, and nothing runs on a watch. Check the final design on a real watch.