warden

Golden images

Clone new simulators from a settled golden for ~16 s boots.

A golden image is a settled simulator warden clones new pool devices from, so a claim that needs a new iOS sim boots in seconds instead of minutes; you only touch it to pre-build one or prune old ones.

warden golden ensure --profile iphone-17

A brand-new simulator's first boot takes 1–10 min, and about 80% of that is the one-time data migration. Measured:

ScenarioTime
fresh create + first boot146–239 s
clone of a settled golden + boot3.7 s + 11.9 s
3 clones booted in parallel~20 s

So when warden claim ios needs a new pool device, it clones it (simctl clone) from a golden image: a sim warden booted once, waited on until its data migration finished (DMLastMigrationResults, since bootstatus -b can return early) and its CPU settled, then shut down.

  • The golden is built on first use and keyed by Xcode build + runtime + runtime build + device type + recipe. An Xcode or runtime upgrade simply builds a new one.
  • The golden also has the e2e driver's accessibility switch (AutomationEnabled) written in it, so a fresh clone's first driver open skips that in-sim defaults write. This is recipe 2: after upgrading to it, every machine builds a recipe-2 golden once (a few minutes) on its next claim; run warden golden ensure to pay that ahead of time. Golden names carry their recipe (warden-golden-<profile>-<key>-r2), so two warden versions on one machine (say an older npm install and a checkout) each keep their own golden instead of deleting each other's on every claim: a claim keeps the previous recipe's golden of the same target and never deletes a newer recipe's. Each kept golden costs disk (a full simulator, ~1.5 GB); warden golden prune deletes the older recipes' goldens once you no longer run the older version.
  • Clones are APFS copy-on-write (~30 MB each).
  • If cloning fails, warden falls back to simctl create. WARDEN_GOLDEN=0 turns cloning off.
  • A pool device that already exists is always reused first; a second boot takes ~6.5 s.
  • Goldens are never allocated, adopted, booted by gc or counted in the pool; warden devices labels them golden.

Commands

warden golden ensure --profile iphone-17   # build ahead of time, so the first claim doesn't pay
warden golden ls
warden golden prune                        # delete stale goldens; --all deletes every one

Android: warden's quick-boot snapshot

Claimed emulators launch -read-only -snapshot warden-<key> from a quick-boot snapshot warden owns when it exists, instead of whatever default_boot your last Android Studio run left (or a full cold boot). A claim never builds it: a claim that finds no current snapshot cold-boots read-only exactly as before, logs one line, and marks the AVD. The next warden gc (auto-gc runs it in the background) builds the snapshot of one marked AVD per pass, only while no emulator of that AVD is running and never when CI is set; warden golden ensure --platform android --profile <slug> builds it now.

The build boots your AVD writable once: warden cold-boots it headless with -no-snapshot-load -no-snapshot-save (your default_boot is neither loaded nor overwritten), waits for sys.boot_completed plus a short settle, runs adb emu avd snapshot save warden-<key> and stops it (emu kill, then SIGKILL after a minute). That first boot does write first-boot state into the AVD's userdata, as an Android Studio run would, and the snapshot lands in the AVD's snapshots/ folder (about the AVD's RAM in disk). While it runs, Android Studio cannot start that AVD. To keep warden from ever booting your AVD writable, turn snapshots off with android: { snapshot: false } in warden.config.ts or WARDEN_ANDROID_SNAPSHOT=0 (0/1/true/false/on/off/yes/no; =1 overrides the config, any other value is warned about and ignored).

The key covers the system image revision and build fingerprint, the emulator version, the AVD's hw.* and guest-shaping settings (data partition, ABI, tag, Play Store, SD card), the headless launch flags and a recipe number, so an emulator or image update builds a new snapshot and warden golden prune --platform android (or the next build) deletes the stale one. A snapshot a claim's emulator logs as failing to load is deleted, so the next build replaces it; a launch from the snapshot that fails is retried once as a cold boot. It needs ANDROID_HOME (or ANDROID_SDK_ROOT; warden says so once when neither is set). Claimed emulators also run -no-audio -no-metrics (an emulator that rejects them is relaunched without); WARDEN_EMULATOR_AUDIO=1 keeps audio. warden golden ensure|ls|prune --platform android builds, lists and prunes the snapshots.

Cloning your own sim

warden clone <udid|name> [--name x] duplicates any shut-down sim — e.g. one you've set up by hand — into warden's pool. warden refuses a booted source rather than shutting it down.

On this page