Environment Variables¶
AutoMobile reads a handful of environment variables to control where its SQLite database lives, how the migration lock behaves, and various diagnostic and runner-override paths. Most users never need to set any of these — the defaults work out of the box. They are primarily useful for isolating databases across worktrees/instances, opting into test-only behavior, and debugging.
Every AUTOMOBILE_* variable also accepts a legacy AUTO_MOBILE_* alias
(underscore after AUTO). The AUTOMOBILE_* spelling is preferred; the alias is
retained for backward compatibility and is used only when the preferred name is
unset.
Database location & behavior (AUTOMOBILE_DB_*)¶
These control where the SQLite database (auto-mobile.db) is stored and how the
cross-process migration lock behaves.
| Variable | Legacy alias | Purpose | Default |
|---|---|---|---|
AUTOMOBILE_DB_PATH |
AUTO_MOBILE_DB_PATH |
Explicit path to the database file. Relative paths resolve from the daemon’s launch working directory. Takes precedence over AUTOMOBILE_DB_DIR. |
~/.auto-mobile/auto-mobile.db |
AUTOMOBILE_DB_DIR |
AUTO_MOBILE_DB_DIR |
Directory that holds auto-mobile.db. Relative paths resolve from the daemon’s launch working directory. Ignored when AUTOMOBILE_DB_PATH is set. |
~/.auto-mobile |
AUTOMOBILE_ALLOW_IN_MEMORY_DB |
— | Test-only opt-in (1/true/yes) that permits AUTOMOBILE_DB_PATH=:memory:. Not for production. |
unset |
AUTOMOBILE_MIGRATION_LOCK_TIMEOUT_MS |
AUTO_MOBILE_MIGRATION_LOCK_TIMEOUT_MS |
Ceiling (ms) for the cross-process migration-lock busy-wait, mirroring the daemon timeout knobs. | 60000 (60s) |
Isolating a database per worktree/instance¶
Point AUTOMOBILE_DB_PATH (or AUTOMOBILE_DB_DIR) at a location unique to the
instance so concurrent daemons do not contend for one file:
# Explicit file
export AUTOMOBILE_DB_PATH="$PWD/.auto-mobile/auto-mobile.db"
# Or just the directory (auto-mobile.db is created inside it)
export AUTOMOBILE_DB_DIR="$PWD/.auto-mobile"
Relative paths are resolved from the daemon’s launch working directory, not the process CWD, so they stay stable even if the daemon later changes directories.
The :memory: sentinel is test-only¶
AUTOMOBILE_DB_PATH=:memory: is rejected in production. A SQLite :memory:
database is private per connection, so startup migrations run on a separate
in-memory database while the daemon’s own connection is left migrated-but-empty —
the first schema-dependent query (e.g. against tool_calls) then fails with
no such table. To avoid that footgun, setting :memory: without the opt-in
throws an ActionableError at path-resolution time:
AUTOMOBILE_DB_PATH=:memory: is not a valid production database. ...
The `:memory:` sentinel is for lifecycle tests only; set
AUTOMOBILE_ALLOW_IN_MEMORY_DB=1 to opt in from a test.
Set AUTOMOBILE_ALLOW_IN_MEMORY_DB=1 only from a test that deliberately wants a
private per-connection in-memory database. For production, point
AUTOMOBILE_DB_PATH at a real file or unset it to use the default.
Diagnostics & runner overrides¶
The following siblings are read elsewhere in the codebase. They are documented here for discoverability; most are diagnostic or for advanced testing.
| Variable | Purpose |
|---|---|
AUTOMOBILE_DAEMON_LAUNCH_CWD |
Overrides the working directory used to resolve relative AUTOMOBILE_DB_PATH / AUTOMOBILE_DB_DIR values. |
AUTOMOBILE_DEBUG |
Enables verbose debug logging. |
AUTOMOBILE_DEBUG_PERF |
Enables performance/timing debug output. |
AUTOMOBILE_OBSERVE_PERF_SNAPSHOT |
Opt-in (1/true/yes) to attach a windowed performance snapshot (perfSnapshot) to observe results — fps percentiles, jank, touch latency, CPU, memory. Off by default; enabling it starts continuous per-device sampling. Legacy alias AUTO_MOBILE_OBSERVE_PERF_SNAPSHOT (the AUTOMOBILE_* name wins when both are set). |
AUTOMOBILE_OBSERVE_PERF_WINDOW_MS |
Rolling window (ms) for perfSnapshot. Default 5000, clamped to 1000–30000. Legacy alias AUTO_MOBILE_OBSERVE_PERF_WINDOW_MS (the AUTOMOBILE_* name wins when both are set). |
AUTOMOBILE_CTRL_PROXY_APK_PATH |
Overrides the path to the Android CtrlProxy APK (for testing a locally-built runner). |
AUTOMOBILE_CTRL_PROXY_IOS_BUNDLE_PATH |
Overrides the iOS CtrlProxy bundle with a packaged .ipa file (alias of AUTOMOBILE_CTRL_PROXY_IOS_IPA_PATH). This is not the way to use a local xcodebuild output: a directory makes CtrlProxy iOS setup fail (bundle override is not a file) in every state except one, and is bypassed with no diagnostic only when the runner service is already running and responding (cached artifacts alone do not bypass it — setup still reaches the builder and fails). Use AUTOMOBILE_CTRL_PROXY_IOS_DERIVED_DATA for locally-built runners. |
AUTOMOBILE_CTRL_PROXY_IOS_DERIVED_DATA |
Derived-data root for a locally-built iOS runner (Build/Products is appended internally). Only needed when building to a non-default location. Defaults to /tmp/automobile-ctrl-proxy, which is where scripts/ios/ctrl-proxy-build-for-testing.sh writes. Pair it with AUTOMOBILE_SKIP_CTRL_PROXY_DOWNLOAD=true: on a host whose cached bundle metadata is missing or does not match the current version, the daemon downloads the released bundle and extracts it over this directory, replacing the local build. |
AUTOMOBILE_SKIP_CTRL_PROXY_DOWNLOAD |
Skips Android and iOS CtrlProxy downloads/prefetches when set to 1 or true. |
AUTOMOBILE_IOS_HELPER_REQUIRE_CODESIGN |
When 1/true, a failed codesign --verify --deep --strict, a failed spctl --assess (notarization), or a pinned-Team-ID mismatch on the downloaded iOS runner becomes a hard refusal to launch instead of the default warning. Off by default so dev / self-built / unsigned local helpers still run; code signing is not OS-enforced on the simulator, so this is defense-in-depth on physical devices alongside the SHA-256 integrity re-check. macOS-only (no-op elsewhere). |
AUTOMOBILE_IOS_HELPER_TEAM_ID |
Optional Apple Team ID to pin for the downloaded iOS runner. When set, the runner bundle’s TeamIdentifier must match; a mismatch warns (or refuses launch under AUTOMOBILE_IOS_HELPER_REQUIRE_CODESIGN). Unset by default (no canonical Team ID is shipped). macOS-only. |
AUTOMOBILE_SKIP_ACCESSIBILITY_DOWNLOAD_IF_INSTALLED |
Skips the accessibility service download when it is already installed. |
Tool capability defaults (AUTOMOBILE_TOOLSET_*)¶
Advanced tools are hidden behind opt-in tool capabilities — off by default so
a fresh MCP session sees only the core surface. These variables set which
capabilities are enabled the moment a session connects; both forms are consulted
and their effects union. Unlike most AUTOMOBILE_* variables, they have no
legacy AUTO_MOBILE_* alias.
| Variable | Purpose |
|---|---|
AUTOMOBILE_TOOLSET_DEFAULTS |
Comma-separated capability names to enable by default (e.g. clipboard,telephony). Unknown names are ignored. |
AUTOMOBILE_TOOLSET_<CAP> |
Enable one capability when set to 1. <CAP> is the capability name upper-cased with hyphens replaced by underscores (e.g. AUTOMOBILE_TOOLSET_ADVANCED_INTERACTION=1). |
These are only a fallback: an explicit setToolCapability choice for a session is
persisted and overrides the default. See
Tool Capabilities & Registration Flags for the full list
of capabilities, the tools each one exposes, and how to toggle them at runtime.
Device provisioning opt-in¶
AutoMobile never creates a simulator or emulator by default — spawning devices on a developer’s machine is a side effect they did not ask for. Turn it on explicitly, per run or per environment.
| Variable | Purpose | Default |
|---|---|---|
AUTOMOBILE_ALLOW_DEVICE_CREATE |
When 1 or true, startDevice creates a device (iOS: simctl create; Android: avdmanager create avd) instead of failing when nothing matches the requested criteria. |
unset (off) |
The equivalent per-call flag is --create-if-missing on the device-start path:
auto-mobile --cli startDevice --platform ios --create-if-missing
Precedence: an explicit flag wins over the env var, in both directions —
--create-if-missing false disables creation even when
AUTOMOBILE_ALLOW_DEVICE_CREATE=1. With no flag, the env var decides. With
neither, creation is off.
Created devices are named AutoMobile-<model>-<id> so they are easy to find and
clean up (xcrun simctl delete <udid> / avdmanager delete avd -n <name>), and
the resolved device type and runtime are logged at creation time.
Managed-device recovery¶
| Variable | Legacy alias | Purpose | Default |
|---|---|---|---|
AUTOMOBILE_DEVICE_RECOVERY_ON_LOSS |
AUTO_MOBILE_DEVICE_RECOVERY_ON_LOSS |
Enables managed-device recovery after confirmed loss. Only exact 1 enables it; exact 0 disables it. Invalid values warn and disable recovery. |
0 |
AUTOMOBILE_DEVICE_RECOVERY_MAX_ATTEMPTS |
AUTO_MOBILE_DEVICE_RECOVERY_MAX_ATTEMPTS |
Canonical positive decimal attempt budget per stable AutoMobile-owned device identity. Values are bounded to 1 through 10; invalid values warn and use the default. |
2 |
These settings are read once when the daemon starts, logged with their effective
values, and reported by device-pool status. Existing
AUTOMOBILE_ANDROID_REBOOT_ON_DEATH / AUTO_MOBILE_ANDROID_REBOOT_ON_DEATH
remain migration fallbacks for the enablement setting.
Only AutoMobile-owned virtual devices are eligible. Android restarts its owned
AVD today; externally started emulators, physical devices, and iOS simulators
are never restarted. A confirmed device loss cancels and releases the active
session and returns the machine-readable device_lost tool outcome rather than
continuing the in-flight operation.
WebRTC screen streaming (AUTOMOBILE_WEBRTC_*)¶
Defaults for pushing a device’s screen to a WHIP ingest server (the supported
fanout is MediaMTX) over WebRTC/WHIP.
See the CI worker guide and the
design doc. Any value can be
overridden per request on the webrtc-stream.sock control socket.
| Variable | Purpose | Default |
|---|---|---|
AUTOMOBILE_WEBRTC_WHIP_ENDPOINT |
WHIP ingest URL. For MediaMTX use a per-stream path, e.g. https://host:8889/<stream>/whip. Policy (issue #4751): https: is required; plaintext http: is permitted only for loopback hosts (127.0.0.0/8, localhost, ::1) because the bearer token and SDP would otherwise travel in cleartext. Set AUTOMOBILE_WEBRTC_ALLOW_INSECURE_WHIP=1 to re-permit non-loopback http:. Required to start a stream unless passed per request. |
unset |
AUTOMOBILE_WEBRTC_WHIP_TOKEN |
Bearer token sent as Authorization: Bearer <token> on WHIP ingest. |
unset |
AUTOMOBILE_WEBRTC_ICE_SERVERS |
Comma-separated STUN/TURN URLs, or a JSON array of {urls,username,credential}. |
stun:stun.l.google.com:19302 |
AUTOMOBILE_WEBRTC_BITRATE_KBPS |
Target encoder bitrate (kbps). | encoder default |
AUTOMOBILE_WEBRTC_MAX_SIZE |
Capture downscale as WIDTHxHEIGHT (e.g. 720x1280). |
native |
AUTOMOBILE_WEBRTC_IOS_SIMULATOR_FPS |
iOS Simulator WebRTC capture rate. Integer in [5, 60]; values outside the range are rejected at stream start. Separate from the generic screen-capture rate used for MCP observation. |
15 |
AUTOMOBILE_WEBRTC_ANDROID_FPS |
Android video-server WebRTC capture rate, forwarded to the on-device encoder as --fps. Integer in [1, 60]; values outside the range are rejected at stream start. Decoupled from the quality preset so the rate can be tuned without changing resolution/bitrate. |
30 |
AUTOMOBILE_VIDEO_SERVER_JAR |
Explicit path to a built automobile-video.jar (persistent on-device encoder). Highest resolution precedence: when set it is used directly, ahead of the cached/downloaded release jar and the Gradle build output. |
(resolution precedence, see below) |
AUTOMOBILE_REQUIRE_VIDEO_SERVER |
When 1/true, a degrade-to-screenrecord case returns success: false with a typed capture_start_failed screenshot fallback instead. For CI that must run the persistent encoder. A checksum mismatch has the same typed failure and is never accepted. |
unset |
AUTOMOBILE_SKIP_VIDEO_SERVER_DOWNLOAD |
When 1/true, never fetch the jar from the network: resolve from the local override or Gradle build output only. Dedicated flag — not AUTOMOBILE_SKIP_CTRL_PROXY_DOWNLOAD (the CtrlProxy APK is mandatory; the jar is optional and degrades). |
unset |
AUTOMOBILE_IOS_SCREEN_CAPTURE_HELPER |
Explicit local development path to screen-capture-helper for iOS WebRTC capture. Build with swift build in ios/screen-capture, then set this to the resulting absolute path. |
verified signed helper downloaded from the matching GitHub Release |
AUTOMOBILE_IOS_WEBRTC_FFMPEG |
Path to the ffmpeg binary used to encode iOS helper BGRA frames into H.264 Annex-B. |
ffmpeg on PATH |
AUTOMOBILE_WEBRTC_TRICKLE_ICE |
Enable trickle ICE: publish the WHIP offer immediately and PATCH candidates incrementally instead of blocking on ICE gathering. Requires an ingest server supporting the WHIP trickle extension. | false |
AUTOMOBILE_WEBRTC_AUDIO |
Enable optional audio alongside video. Android requires the persistent video-server jar and captures shell-privileged REMOTE_SUBMIX; iOS supports Simulator-window audio through ScreenCaptureKit. Both emit 8 kHz mono PCM16LE and publish as PCMU. Physical iOS playback capture is unavailable through public APIs. |
false |
AUTOMOBILE_WEBRTC_WHIP_ALLOWED_ORIGINS |
Comma-separated allow-list of origins (or bare host[:port]) that a whipEndpoint supplied over the wire to the webrtc-stream socket may target (issue #4751). Loopback and the daemon’s own AUTOMOBILE_WEBRTC_WHIP_ENDPOINT origin are always trusted. An override to any other origin is rejected so a local process cannot exfiltrate the screen to a destination of its choosing. |
unset (only the configured endpoint + loopback allowed) |
AUTOMOBILE_WEBRTC_ALLOW_INSECURE_WHIP |
Escape hatch (issue #4751). When 1/true, re-permits non-loopback plaintext http: WHIP endpoints and accepts an arbitrary (non allow-listed) whipEndpoint override from the wire. For advanced setups only — the bearer token and SDP travel in cleartext over http:. |
false |
AUTOMOBILE_DAEMON_STREAM_AUTH |
Governs authentication of the two live-screen daemon sockets (webrtc-stream, video-stream). When enabled (the default), a start/subscribe request must carry a sessionUuid that resolves to a live daemon session, and may only target a device owned by that same session (issue #4751, extending the #4655 session mechanism). Set to 0/false to disable the check for clients that cannot yet supply a session UUID. |
enabled |
automobile-video.jar resolution¶
The persistent on-device encoder jar is resolved once at stream start, in this
order: AUTOMOBILE_VIDEO_SERVER_JAR override → a valid cached download at
~/.auto-mobile/video-server/ → a fresh, sha256-verified download from the
GitHub release → the local Gradle build output → else screenrecord. The jar is
optional, so an unverifiable version degrades to screenrecord; a checksum
mismatch returns a typed capture_start_failed screenshot fallback and is
never accepted. AUTOMOBILE_VERSION (pin one coherent version) and
AUTOMOBILE_ASSET_BASE_URL (offline mirror host) apply to the jar download just
as they do to the CtrlProxy APK/IPA. See
WebRTC streaming — persistent-encoder delivery.
screen-capture-helper resolution (iOS)¶
The iOS WebRTC capture helper is resolved at stream start, in this order:
AUTOMOBILE_IOS_SCREEN_CAPTURE_HELPER override → a valid cached download at
~/.auto-mobile/screen-capture-helper/ → a fresh, sha256-verified
download of the prebuilt universal (arm64+x86_64) helper from the GitHub
release. A normal macOS install therefore needs no Swift toolchain — the
helper is downloaded and verified like the CtrlProxy APK/IPA and the
automobile-video.jar. AUTOMOBILE_VERSION and AUTOMOBILE_ASSET_BASE_URL
apply to this download too; a checksum mismatch is always fatal. Screen
Recording permission and the ffmpeg requirement still apply. Non-macOS installs
never invoke this path.