Read this before running agent-device by hand against a simulator, emulator, or physical device.
Dev-loop staleness has three layers, and each produces a convincing false negative.
- After changing runtime code reached through
bin/agent-device.mjsor the daemon:pnpm build, thenpnpm clean:daemon— the daemon does not self-reload. - Before any Android verification from source:
pnpm build,pnpm build:android,pnpm clean:daemon.build:androidrefreshes and verifies both bundled Android helper artifacts for the current package version. shutdowndeliberately HANDS OFF a healthy simulator runner. The adopted runner keeps serving the old Swift binary until you kill its process or the source fingerprint changes, so "my change did nothing" measured against an adopted runner is a classic false negative. If Swift runner code changed, runpnpm build:xcuitest.
- Android: capture
snapshot -i --jsonand requireandroidSnapshot.backendto beandroid-helperwithhelperVersionequal topackage.json's version. A stock UIAutomator fallback is not valid verification unless the fallback itself is the behavior under test. - For repo-owned
Agent Device Testerwork,examples/test-app/README.mdis the source of truth for simulator, physical-device, Metro/dev-client, and app-surface steps. An already-installedcom.callstack.agentdevicelabis not sufficient — the README's Metro/dev-build andsnapshot -ichecks must prove the expected app surface is running. - For Android RN/Expo/dev-client apps on any local Metro port,
adb reverse tcp:<port> tcp:<port>is harmless and should be run before opening the app or URL.
Every manually opened session is a resource that must be closed — including exploratory sessions and failed verification attempts.
- Every
agent-device openneeds a matchingclosewith the same--session,--platform,--udid, and--state-dirbefore the agent finishes. - Use a purpose-specific session name for experiments, and an isolated
--state-dirunder/private/tmpwhen you need cleanup isolation beyond the current worktree's default daemon. - Track opened sessions in working notes; close each one before the final response.
- If
closeis blocked by stale daemon metadata, inspect processes first withps -ax | rg "agent-device|xcodebuild test-without-building". Stop only exact stale PIDs belonging to this verification run, thenpnpm clean:daemon. - If cleanup cannot be completed, report the remaining session name, state dir, PIDs, and metadata paths as a blocker.
Start the daemon outside the sandbox with escalation. The daemon binds localhost, and sandboxed runs
fail before any product code executes, with listen EPERM: operation not permitted 127.0.0.1 or
repeated Failed to start daemon/metadata cleanup messages. Those are not agent-device regressions —
rerun with escalation. Unit tests, typecheck, lint, and build can stay sandboxed unless they need
devices or listener access.