Install
Requires Rust 1.85+ and ~/.cargo/bin on your PATH.
Verify:
# or
Debug install (faster compile, larger binary):
Run without installing:
Quickstart
Requires the Android SDK (emulator, platform-tools) and an installed system
image (dorker pull installs one). macOS Apple Silicon and Linux x86_64 with KVM are
validated. No Docker needed.
Describe your environment in a Dorkerfile
A Dorkerfile (next to your app, like a Dockerfile) declares the Android environment: the
base image, resources, the APK to install, settings, and a snapshot to start from.
# Dorkerfile
FROM android:35 # Android 35 system image (install it with: dorker pull)
MEMORY 2GB # guest RAM
CPUS 2
DISK 4GB
DEVICE pixel_7
RESOLUTION 1080x2400
HEADLESS true # no emulator window
INSTALL ./app/build/outputs/apk/debug/app-debug.apk # path is relative to this file's folder
SETTING window_animation_scale 0 # make UI tests faster and less flaky
SETTING transition_animation_scale 0
SETTING animator_duration_scale 0
SNAPSHOT ready # save a snapshot, so instances start in a few seconds
CMD launch com.example.app # open this app once an instance is ready
Then build the image once and run it as many times as you like:
An identical rebuild is a cache hit (instant), and every dorker run gets its own isolated
copy, so instances never share state. To try it without your own app, use the sample:
&&
Every directive is documented in docs/dorkerfile.md. More examples:
examples/basic, examples/instrumentation and
examples/counter-app, a real Gradle app with Espresso tests
(./dev.sh runs Gradle, dorker build, run, a screenshot and the tests). The example APKs
are not committed: build them with each example's make-apk.sh (or Gradle for the counter app).
Each instance gets its own private AVD under ~/.dorker (override with
DORKER_HOME). Your existing AVDs are never touched. dorker run --rm removes the
instance when it stops. ps, images and doctor accept --json.
Measured on an Apple M4 Pro, API 35, 2GB: cold boot about 15s, snapshot restore about 4s. Host memory is about 2.5GB after a cold boot and 3.3GB after a restore. Details and caveats: docs/benchmarks.md.
Test, benchmark, automate
dorker test prints a summary, preserves the raw instrumentation output and logcat
under the instance directory, and exits 7 if anything failed.
See examples/instrumentation for a runnable example.
Tests
Use it from AI agents
dorker mcp is a Model Context Protocol server: an agent can start instances, install apps,
run commands, take screenshots, read logs and run tests, all with structured results.
See docs/mcp.md for the tools, other clients and security notes. The same
operations are available to scripts as --json on run, start, exec, install,
screenshot, test, ps, images, doctor and bench.
Diagnostics
dorker -v <command> (or DORKER_VERBOSE=1) prints what dorker decides and runs to stderr: the
located SDK, the boot mode and why, the exact emulator command line and environment, state
transitions and timings. Each instance also keeps its raw emulator output in
~/.dorker/instances/<id>/emulator.log.
Exit codes
| Code | Meaning |
|---|---|
| 0 | success |
| 1 | other error |
| 2 | invalid configuration or arguments (including Dorkerfile errors) |
| 3 | missing dependency (SDK, emulator, adb, system image); doctor failures |
| 4 | image build failed |
| 5 | instance failed to start or boot |
| 6 | adb operation failed |
| 7 | instrumentation tests failed |
| 8 | name, port or build conflict, or not enough free disk space |
dorker exec returns the guest command's own exit status.
See docs/architecture.md for design and limitations.
Limitations
- Platform: validated on macOS Apple Silicon (primary) and Linux x86_64 with KVM (Ubuntu 24.04, an Azure VM with nested virtualisation; unit tests and the full emulator end-to-end suite pass). Linux arm64 and bare-metal Linux are untested; Windows is unsupported. Linux is slower in our measurements (cold boot about 29s, snapshot restore about 9s; see docs/benchmarks.md).
- System images are installed on request, not automatically.
dorker pull android:35runs the SDK'ssdkmanager(needs the command-line tools and may prompt for licences);dorker run/buildprint this command when an image is missing. The download path itself was only verified for the already-installed and nonexistent-package cases, not a real multi-GB download. - Snapshots are strict. A change of emulator version, system-image revision, memory or CPUs invalidates an image's snapshot. dorker then cold boots (about 15s) and says so. Snapshots are host-specific and not portable between machines.
- Memory: a 2GB guest used about 2.5GB of host memory after a cold boot and 3.3GB after a snapshot restore on macOS (3-3.7GB on Linux). Idle CPU is dominated by Android background work and takes about a minute to settle.
- Builds take about 45s because dorker reboots the guest to persist provisioned state.
CMDonly supportslaunch <package>.dorker startalways cold boots (about 14s) because restoring the image snapshot would roll back the instance's data. There is software rendering (swiftshader_indirect) is the default;GPU <mode>in the Dorkerfile selects another, but none was faster for snapshot restore in our measurements (see docs/benchmarks.md) and no automatic test-APK discovery.- Concurrency: creating instances concurrently is safe, and
stop,rmandstarton the same instance are serialised by a per-instance lock (the second command waits up to 60s, then exits 8). - Orphans: emulator processes that dorker started but lost track of (CLI killed mid-start) are reported by
dorker ps, not adopted or killed automatically. examples/basicandexamples/instrumentationuse tiny hand-built APKs;examples/counter-appis the realistic one.
Development
Common tasks via the Makefile:
Releasing (requires cargo-release and git-cliff):
The pre-release hook regenerates CHANGELOG.md with git-cliff from your conventional-commit history (grouped into Features, Bug Fixes, etc. per cliff.toml) and commits it alongside the version bump. Pushing the resulting v* tag triggers the release workflow, which builds the multi-platform binaries and publishes a GitHub Release whose notes are generated by git-cliff from the same config.
License
MIT