Skip to content

The agent loop

The point of this server is closing the loop: wrote the patchsaw it work on a device. A full session looks like this.

Always cheap, always available. Reports toolchains, Metro status, project kind (Expo vs bare) and React Native version, plus actionable problems.

2. Get a device — list_devicesboot_device

Section titled “2. Get a device — list_devices → boot_device”
list_devices → iPhone 16 Pro (booted) · avd:Pixel_8 (shutdown) · …
boot_device {deviceId: "avd:Pixel_8"} → booted as emulator-5554 in 38s

Device ids are unified: simctl UDIDs, adb serials, and avd:<name> for cold Android AVDs all work in every device tool.

3. Build & install — run_buildget_build_statusinstall_app

Section titled “3. Build & install — run_build → get_build_status → install_app”

Builds run in the background; run_build returns a job id immediately:

run_build {platform: "ios"} → job a1b2c3d4
get_build_status {jobId: "a1b2c3d4"} → running (2m10s elapsed)…
get_build_status {jobId: "a1b2c3d4"} → ✅ succeeded · artifact: …/MyApp.app
install_app {deviceId, appPath} → com.example.myapp
launch_app {deviceId, appId} → running

On failure you get structured diagnostics instead of a log dump. For pure JS changes skip the rebuild — reload_app is enough.

The runtime bridge buffers everything the app logs (plus uncaught errors). Reads are incremental — pass the previous nextCursor to get only what’s new:

read_console {level: "error"} → 2 errors · cursor 1287
read_console {cursor: 1287} → only new entries since
read_console {filter: "api|network"} → regex-filtered

Execute any expression inside the live app:

evaluate_js {expression: "globalThis.store.getState().auth"}
evaluate_js {expression: "Object.keys(require('react-native').NativeModules)"}
evaluate_js {expression: "fetch('http://localhost:3000/health').then(r => r.status)"}

Promises are awaited via polling (a Hermes CDP limitation), up to timeoutMs.

6. Verify — reload_appread_consoletake_screenshot

Section titled “6. Verify — reload_app → read_console → take_screenshot”

After editing code: reload, confirm the console is clean, and capture a screenshot (use set_status_bar_demo first for deterministic images). The screenshot comes back as an actual image the agent can look at.

open_url drives navigation from outside the app — custom schemes, universal links and Expo’s exp:// URLs all work on both platforms.