Android Emu Agent
Android Emu Agent lets a coding agent inspect and control an Android emulator or device. It provides a command-line interface (CLI) backed by a local daemon.
The daemon reads the current screen, assigns short refs such as ^g1a1 to UI elements, performs
actions, and can check the result. This gives an agent a repeatable loop:
observe the screen -> act on a known element -> verify the result -> save evidence
Documentation | CLI reference | Source
Why Use Android Emu Agent?
Raw adb commands and coordinate taps do not describe the current screen. They also do not confirm
that an action produced the expected result. Android Emu Agent adds observable targets, checks, and
failure evidence to Android automation.
| Task | Support |
|---|---|
| Inspect the current screen | Compact UI snapshots with refs such as ^g1a1 |
| Tap, type, swipe, and navigate | Refs, text and resource selectors, coordinates, and device capabilities |
| Wait for a state change | Wait commands and pass/fail expectations |
| Repeat an app flow | JSON task files and human-editable .aea scripts |
| Investigate a failure | Screenshots, logs, trace archives, and artifact bundles |
| Debug an app below the UI | Kotlin bridge for Java Debug Interface (JDI) commands |
| Integrate with an agent | JSON output, daemon-backed sessions, and a bundled agent skill |
Requirements
Install these tools before you start:
| Requirement | Purpose |
|---|---|
| Python 3.11 or later | Run the CLI and daemon |
uv |
Install and run the project from this repository |
Android SDK platform-tools |
Provide adb device access |
| Connected Android emulator or device | Provide the automation target |
Some workflows need more tools or access:
| Optional requirement | Needed for |
|---|---|
Android SDK emulator |
Start and stop Android Virtual Devices (AVDs) |
Android SDK cmdline-tools |
Use avdmanager and sdkmanager |
| Root access | Read private app files and collect some diagnostics |
| JDK 17 or later | Use debugger commands |
On macOS, you can add the Android SDK tools to PATH with these commands:
export ANDROID_SDK_ROOT="$HOME/Library/Android/sdk"
export PATH="$ANDROID_SDK_ROOT/platform-tools:$ANDROID_SDK_ROOT/emulator:$ANDROID_SDK_ROOT/cmdline-tools/latest/bin:$PATH"
adb version
emulator -list-avds
avdmanager list avd
Install From Source
Clone the repository and install all project dependencies:
git clone https://github.com/alehkot/android-emu-agent.git
cd android-emu-agent
uv sync --all-extras
In this repository, run the CLI through uv:
uv run android-emu-agent <command>
Complete the First Automation Loop
Use this procedure to confirm that the CLI, daemon, and target device work together.
In the commands:
- Replace
<avd-name>with an AVD name. - Replace
<device-serial>with the serial shown bydevice list. - Replace
<session-id>with the ID returned bysession start.
-
Connect an Android device or start an emulator.
Optional: start an existing AVD with Android Emu Agent:
uv run android-emu-agent emulator list-avds uv run android-emu-agent emulator start <avd-name> --wait-boot
-
Start the daemon.
uv run android-emu-agent daemon start
-
Verify that the daemon is running.
uv run android-emu-agent daemon status --json
-
Verify that
adbcan see the target device.uv run android-emu-agent device list
-
Start a session and copy the returned
session_id.uv run android-emu-agent session start --device <device-serial> --json
-
Capture the current screen.
uv run android-emu-agent ui snapshot <session-id> --format text
The snapshot lists actionable elements with refs such as
^g1a1. -
Tap an element from the snapshot.
uv run android-emu-agent action tap <session-id> ^g1a1
-
Check the result with an expectation.
uv run android-emu-agent expect exists <session-id> --text "<expected-text>" --timeout-ms 5000
Replace
<expected-text>with text that must appear after the tap. The expectation fails if the text does not appear before the timeout. -
Stop the session when the task is complete.
uv run android-emu-agent session stop <session-id>
This archives an active trace and releases debugger and ADB-forward resources before deleting the session.
Most commands support --json for machine-readable output. JSON responses include a
diagnostic_id. The daemon also returns this value in the x-diagnostic-id response header.
Choose the Next Task
| Goal | Start here |
|---|---|
| Follow complete workflow examples | Workflow examples |
| Write a reusable Android flow | Task script guide |
Look up .aea syntax |
.aea task script specification |
| Find an exact CLI option | Generated CLI reference |
| Install the bundled agent skill | Agent Skill |
| Understand sessions, refs, selectors, and traces | Core Concepts |
Core Concepts
Daemon and Sessions
The daemon owns device connections and session state. The CLI sends requests to the daemon through
the Unix socket at /tmp/android-emu-agent.sock.
Each session connects commands to one target device. Start a session before you inspect or control the device, and stop the session when the task is complete.
Important paths:
| Path | Purpose |
|---|---|
/tmp/android-emu-agent.sock |
Daemon socket |
~/.android-emu-agent/daemon.log |
Daemon log |
~/.android-emu-agent/daemon.pid |
Daemon process ID file |
~/.android-emu-agent/diagnostics/requests.ndjson |
Request diagnostics |
~/.android-emu-agent/artifacts |
Default artifact directory |
~/.android-emu-agent/traces |
Default trace archive directory |
Snapshots, Refs, and Selectors
A UI snapshot describes the current screen. The snapshot assigns a ref, such as ^g1a1, to each
actionable element. In that token, g1 identifies snapshot generation 1 and a1 identifies the
first actionable element. Copy the complete ref from the latest snapshot; the element number alone
is not stable across snapshots.
Refs belong to one snapshot generation. If the screen changes, take a new snapshot before you use another ref. The daemon can sometimes match a stale ref to the latest snapshot, but it returns a warning when it does this.
You can also select an element by text, resource ID, content description, coordinates, or a combined selector:
^g1a1
text:"Sign in"
text-contains:"Continue"
id:com.example:id/login_btn
desc:"Open navigation"
coords:540,1200
text:"Sign in" || id:com.example:id/login_btn
text:"Continue" enabled:true clickable:true
To see the selector forms and device features available to an automation planner, run:
uv run android-emu-agent device capabilities --session <session-id> --json
Tasks, Traces, and Evidence
Use a .aea script or JSON task file to repeat a flow. Validate the task before you run it:
uv run android-emu-agent task validate examples/tasks/checkout-smoke.aea
uv run android-emu-agent task run examples/tasks/checkout-smoke.aea --session <session-id> --json
A trace records the actions and observations in a session. Use a trace or artifact bundle when you need to reproduce or investigate a failure:
uv run android-emu-agent trace start <session-id> --label checkout-repro
uv run android-emu-agent trace stop <session-id> --output ./artifacts/checkout-repro.aea-trace.zip
uv run android-emu-agent trace replay ./artifacts/checkout-repro.aea-trace.zip --until-failure
uv run android-emu-agent artifact bundle <session-id> --json
Install the Agent Skill
The repository includes an android-emu-agent skill in skills/android-emu-agent/. The skill helps
coding agents select commands, follow the observe-act-verify loop, recover from errors, and apply
safety rules.
Install or refresh the skill links for a supported agent:
./scripts/dev.sh skills # all supported local agent targets
./scripts/dev.sh skills codex # Codex only
./scripts/dev.sh skills claude # Claude Code only
./scripts/dev.sh skills vscode # VS Code .agents/skills only
./scripts/dev.sh skills-validate
After installation, give the agent a specific target and task. For example:
Use Android Emu Agent to open Settings on emulator-5554 and verify that Wi-Fi is enabled.
If your environment cannot use symbolic links, copy skills/android-emu-agent/ into the agent's
skill directory. Python wheels also include the same files under
android_emu_agent/skills/android-emu-agent/; locate that installed copy with:
python -c "from importlib.resources import files; print(files('android_emu_agent') / 'skills' / 'android-emu-agent')"
Check Device Support and Safety
An emulator or rooted device provides the most features. Many UI operations also work on a non-root
device when adb is connected and uiautomator2 can attach.
These operations usually work without root access:
- Capture UI snapshots, screenshots, and visual grounding data.
- Tap, long-tap, enter text, clear text, swipe, scroll, and press system navigation buttons.
- Run wait and expectation commands.
- Install, uninstall, launch, stop, reset, or open a link in an app.
- List, grant, and revoke runtime permissions.
- Push and pull files in shared storage.
- Find and list files in shell-readable storage.
- Push and pull app-private files for debuggable apps via
run-as. - Collect supported reliability, process, memory, graphics, and performance data.
These operations require root or emulator access:
reliability oom-adjreliability pull anrreliability pull tombstonesreliability pull dropboxfile findandfile listfor paths the shell user cannot read.file app pushandfile app pullfor apps that do not permitrun-as.
Emulator snapshot save and restore commands require an emulator serial such as emulator-5554. A
non-emulator serial returns ERR_NOT_EMULATOR.
Debug an App
Debugger commands use a Kotlin bridge to connect the Java Debug Interface (JDI) to a debuggable
Android app. These commands require JDK 17 or later. They also require an app built with
android:debuggable=true, or a userdebug or eng target that permits debugging.
Use this minimal debugger flow:
uv run android-emu-agent debug ping <session-id>
uv run android-emu-agent app launch <session-id> com.example.app --wait-debugger
uv run android-emu-agent debug attach --session <session-id> --package com.example.app --keep-suspended
uv run android-emu-agent debug break set com.example.app.MainActivity 42 --session <session-id>
uv run android-emu-agent debug resume --session <session-id>
uv run android-emu-agent debug events --session <session-id>
uv run android-emu-agent debug detach --session <session-id>
During bridge development, build and test the bridge with these commands:
./scripts/dev.sh build-bridge
./scripts/dev.sh test-bridge
Troubleshoot a Connection or Action
Start with these checks:
uv run android-emu-agent device list
adb devices
uv run android-emu-agent daemon status --json
| Error code | Meaning | Next action |
|---|---|---|
ERR_STALE_REF |
The ref came from an old snapshot | Take a new snapshot and use a current ref or selector |
ERR_NOT_FOUND |
The target element was not found | Inspect the screen with --full or use another selector |
ERR_BLOCKED_INPUT |
A dialog, keyboard, or overlay blocked input | Dismiss the blocker or wait for the device to become idle |
ERR_TIMEOUT |
A wait or expectation did not complete | Check the condition or increase --timeout-ms |
ERR_SESSION_EXPIRED |
The session no longer exists | Start a new session |
ERR_DEVICE_OFFLINE |
The device disconnected | Reconnect the device and rerun device list |
ERR_PERMISSION |
The operation requires root access | Use a rooted target or skip the operation |
ERR_ADB_NOT_FOUND |
adb is not on PATH |
Install Android SDK platform-tools and update PATH |
ERR_SDK_TOOL_NOT_FOUND |
An Android SDK command is missing | Add emulator or avdmanager to PATH |
ERR_JDK_NOT_FOUND |
A Java runtime is missing | Install JDK 17 or later, or set JAVA_HOME |
ERR_JDK_UNSUPPORTED |
Java is too old or lacks the JDI module | Install JDK 17 or later, or update JAVA_HOME |
ERR_INVALID_SNAPSHOT_NAME |
Snapshot name contains unsupported input | Use only letters, digits, ., _, or - |
ERR_INVALID_EMULATOR_PORT |
Emulator console port is unsupported | Use an even port from 5554 through 5584 |
ERR_CONSOLE_AUTH |
Emulator console authentication failed | Check .emulator_console_auth_token permissions/content |
ERR_LOG_FOLLOW_UNSUPPORTED |
Artifact logs cannot stream over this API | Omit --follow or use adb -s <serial> logcat |
ERR_INVALID_ARTIFACT_NAME |
Managed artifact filename is unsafe | Use a plain filename without directories |
ERR_AMBIGUOUS_SELECTOR |
A single-target selector matched many nodes | Add filters or use a fresh ^ref |
ERR_DAEMON_IDENTITY |
A live PID does not own the daemon socket | Inspect the daemon log and process before manual cleanup |
ERR_TASK_INVALID |
A JSON task file is invalid | Fix the task and rerun task validate |
ERR_TASK_SCRIPT_INVALID |
A .aea script is invalid |
Fix the reported line and rerun task validate |
ERR_EXPECTATION_FAILED |
The expected state was not observed | Inspect the state, selector, and timeout |
For more recovery guidance, see the troubleshooting reference.
Understand the Architecture
CLI client
-> FastAPI daemon over /tmp/android-emu-agent.sock
-> sessions, snapshots, actions, waits, expectations, tasks, traces, and artifacts
-> adbutils and uiautomator2 for device communication
-> Kotlin JDI Bridge process for debugger commands
-> Android emulator or device
The CLI is a thin client. The daemon keeps device connections and session state, then sends device
commands through adbutils and uiautomator2. Debugger commands use a separate Kotlin process.
Develop Android Emu Agent
Use ./scripts/dev.sh as the main entry point for local development.
| Command | Purpose |
|---|---|
./scripts/dev.sh setup |
Install dependencies |
./scripts/dev.sh check |
Run format/lint, typing, Python/Kotlin tests, docs, and skill checks |
./scripts/dev.sh test-unit |
Run unit tests |
./scripts/dev.sh test-integration |
Run tests that require an emulator or device |
./scripts/dev.sh build-bridge |
Build the JDI Bridge JAR |
./scripts/dev.sh test-bridge |
Run Kotlin bridge tests |
./scripts/dev.sh docs-gen |
Regenerate docs/reference.md |
./scripts/dev.sh docs |
Build the documentation site in site/ |
./scripts/dev.sh md |
Format and lint Markdown |
./scripts/dev.sh skills-validate |
Validate the bundled skill metadata and references |
Useful direct commands:
uv run android-emu-agent --help
uv run android-emu-agent <group> --help
uv run pytest tests/unit -v
uv run ruff check .
uv run mypy src/
docs/reference.md is generated from the CLI. Run ./scripts/dev.sh docs-gen instead of editing
its command tables by hand. The documentation site navigation is defined in mkdocs.yml.
License
Android Emu Agent uses the MIT License. See the license.
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file android_emu_agent-0.1.17.tar.gz.
File metadata
- Download URL: android_emu_agent-0.1.17.tar.gz
- Upload date:
- Size: 163.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/7.0.0 CPython/3.13.9
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
aa72a4eef1235c97fb62ab36f62acb0eeff2816c9f5969f70d18230c707eafe3
|
|
| MD5 |
4138b4658c827dfb57c17d7817f03e48
|
|
| BLAKE2b-256 |
d3c2335a83d632e656977954ec6566b2f422bed74f8016591cfbc7c83706eafb
|
File details
Details for the file android_emu_agent-0.1.17-py3-none-any.whl.
File metadata
- Download URL: android_emu_agent-0.1.17-py3-none-any.whl
- Upload date:
- Size: 206.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/7.0.0 CPython/3.13.9
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d39af4ab4e4cc7454532456425d3d0e2ae0fa7c651b384d9d4e845a3ff636cd0
|
|
| MD5 |
de824991f53d47e87f85369e9d0df2ba
|
|
| BLAKE2b-256 |
2821e461251e364ec600fe19ac762af3975af8239890de9a8aa34c2b99a555d0
|