CLI + daemon for LLM-driven Android UI control on emulators and rooted devices
Project description
Android Emu Agent
A CLI + daemon system for LLM-driven Android UI control on emulators and rooted devices.
Overview
Android Emu Agent automates Android apps using a fast observe-act-verify loop:
- Observe: capture a compact UI snapshot (interactive elements only)
- Act: issue commands using ephemeral element refs like
@a1 - Verify: re-snapshot when needed
The CLI is a thin client. A long-running daemon handles all device I/O.
Inspiration
Inspired by agent-browser, a fast headless browser automation CLI for AI agents.
Requirements
- Python 3.11+
uvpackage manager- Android SDK with
adbon PATH - Android emulator or rooted device (primary target)
Install
# Clone the repository
git clone https://github.com/alehkot/android-emu-agent.git
cd android-emu-agent
# Install dependencies
uv sync
Inside this repo, prefer uv run android-emu-agent <command>.
Quick Start (2 minutes)
# 1. Start the daemon (optional, CLI will auto-start by default)
uv run android-emu-agent daemon start
# 2. List connected devices
uv run android-emu-agent device list
# 3. Start a session (prints the session id)
uv run android-emu-agent session start --device emulator-5554
# 4. Take a compact snapshot and read refs
uv run android-emu-agent ui snapshot s-abc123 --format text
# 5. Tap an element using a ref
uv run android-emu-agent action tap s-abc123 @a1
# 6. Stop the session
uv run android-emu-agent session stop s-abc123
Most commands accept --json for machine-readable output.
Example --json output for session start:
{
"status": "done",
"session_id": "s-abc123",
"device_serial": "emulator-5554",
"generation": 0
}
Core Concepts
Sessions
- Sessions tie actions to a specific device. Most commands accept a session id.
session startreturns a session id.session stopreleases it.
Snapshots and refs
ui snapshotreturns@refsthat are stable only for that snapshot.- If you get
ERR_STALE_REF, take a new snapshot and use fresh refs.
Selectors
action tapaccepts an@refor a selector.long-tap,set-text, andclearrequire an@ref.
Selector examples:
@a1
text:"Sign in"
id:com.example:id/login_btn
desc:"Open navigation"
coords:120,450
Snapshot Format
Compact snapshot output includes context and interactive elements only:
{
"schema_version": 1,
"session_id": "s-abc123",
"generation": 42,
"context": {
"package": "com.example.app",
"activity": ".MainActivity",
"orientation": "PORTRAIT",
"ime_visible": false
},
"elements": [
{
"ref": "@a1",
"role": "button",
"label": "Sign in",
"resource_id": "com.example:id/login_btn",
"bounds": [100, 200, 300, 250],
"state": { "clickable": true, "enabled": true }
}
]
}
Daemon and State
- Socket:
/tmp/android-emu-agent.sock - Logs:
~/.android-emu-agent/daemon.log - PID file:
~/.android-emu-agent/daemon.pid
The CLI auto-starts the daemon on first request. Use these to debug:
uv run android-emu-agent daemon status --json
uv run android-emu-agent daemon stop
uv run android-emu-agent daemon start
Common Workflows
Login flow
uv run android-emu-agent app launch s-abc123 com.example.app
uv run android-emu-agent wait idle s-abc123 --timeout-ms 5000
uv run android-emu-agent ui snapshot s-abc123 --format text
uv run android-emu-agent action set-text s-abc123 @a3 "user@example.com"
uv run android-emu-agent action set-text s-abc123 @a4 "hunter2"
uv run android-emu-agent action tap s-abc123 @a5
When elements are missing
uv run android-emu-agent ui snapshot s-abc123 --full
uv run android-emu-agent wait idle s-abc123 --timeout-ms 3000
uv run android-emu-agent ui snapshot s-abc123
Visual debug
uv run android-emu-agent ui screenshot --device emulator-5554 --pull --output ./screen.png
uv run android-emu-agent artifact bundle s-abc123
Emulator snapshots
uv run android-emu-agent emulator snapshot save emulator-5554 clean
uv run android-emu-agent emulator snapshot restore emulator-5554 clean
These commands require an emulator serial (emulator-5554). If you pass a non-emulator serial, you
will see ERR_NOT_EMULATOR.
Real Devices (Non-Root)
The project targets emulators and rooted devices, but many commands do not enforce root and can work
on real devices as long as adb is connected and uiautomator2 can attach (ATX server on port 7912).
In practice, these are usually safe on non-root devices:
- UI snapshots and screenshots
- Actions (tap, set-text, swipe, scroll, back/home/recents)
- Wait commands
- App list/launch/force-stop/reset/deeplink
- File
pushandpullto shared storage
Emulator-only commands are emulator snapshot save|restore. Root-required commands are listed
below.
Root-Required Operations
The following require a rooted device or emulator with root access:
reliability oom-adjreliability pull anrreliability pull tombstonesreliability pull dropboxfile findfile listfile app pushfile app pull
If root is missing, you will see ERR_PERMISSION.
Artifacts
Artifacts are written to ~/.android-emu-agent/artifacts by default.
- Reliability outputs:
~/.android-emu-agent/artifacts/reliability - File transfers:
~/.android-emu-agent/artifacts/files
Troubleshooting
Quick checks
uv run android-emu-agent device list
adb devices
uv run android-emu-agent daemon status --json
Common errors
| Error Code | Meaning | Fix |
|---|---|---|
ERR_STALE_REF |
Ref from an old snapshot | Take a new snapshot |
ERR_NOT_FOUND |
Element not found | Verify screen, use --full or a selector |
ERR_BLOCKED_INPUT |
Dialog/IME blocking | wait idle or back |
ERR_TIMEOUT |
Wait condition not met | Increase --timeout-ms or check condition |
ERR_DEVICE_OFFLINE |
Device disconnected | Reconnect and re-run device list |
ERR_SESSION_EXPIRED |
Session is gone | Start a new session |
ERR_PERMISSION |
Root required | Use a rooted device/emulator |
ERR_ADB_NOT_FOUND |
adb not on PATH |
Install Android SDK and ensure adb is on PATH |
ERR_ADB_COMMAND |
ADB command failed | Check device connectivity and retry |
For deeper guidance, see skills/android-emu-agent/references/troubleshooting.md.
CLI Reference
A concise command list lives at skills/android-emu-agent/references/command-reference.md.
If you prefer an interactive guide:
uv run android-emu-agent --help
uv run android-emu-agent <group> --help
Architecture
┌─────────────────┐ Unix Socket ┌──────────────────────────────────┐
│ │ ◄────────────────► │ Daemon │
│ CLI Client │ │ ┌────────────────────────────┐ │
│ │ │ │ Device Manager │ │
└─────────────────┘ │ │ (adbutils, uiautomator2) │ │
│ └────────────────────────────┘ │
│ ┌────────────────────────────┐ │
│ │ Session Manager │ │
│ │ (refs, state, SQLite) │ │
│ └────────────────────────────┘ │
│ ┌────────────────────────────┐ │
│ │ UI Snapshotter │ │
│ │ (lxml, filtering) │ │
│ └────────────────────────────┘ │
└──────────────────────────────────┘
│
▼
┌──────────────────────────────────┐
│ Android Device/Emulator │
│ (ATX Server on port 7912) │
└──────────────────────────────────┘
Development
# Install with dev dependencies
uv sync --all-extras
# Run tests
uv run pytest tests/unit -v
# Run linter
uv run ruff check .
# Format code
uv run ruff format .
# Type check
uv run mypy src/
# Run all checks
./scripts/dev.sh check
Agent Skills
This repo ships an android-emu-agent skill in skills/android-emu-agent/ for agent environments
that support skills. Use the install steps below.
Install for Codex
export CODEX_HOME="$HOME/.codex"
mkdir -p "$CODEX_HOME/skills"
ln -sfn "$(pwd)/skills/android-emu-agent" "$CODEX_HOME/skills/android-emu-agent"
Install for Claude Code
mkdir -p ~/.claude/skills
ln -sfn "$(pwd)/skills/android-emu-agent" ~/.claude/skills/android-emu-agent
If symlinks are not an option, copy the directory instead.
Using the Skill
After installation, the agent should be primed to start a session with your connected device before you ask for specific actions. Begin with a direct initialization request, for example:
I want to interact with my connected Android emulator.
Once the agent has initialized the session, you can proceed with normal requests (snapshots, tap/type actions, app launches, waits, etc.).
Prerequisites you may need (if the agent reports it cannot connect):
- Start the daemon:
uv run android-emu-agent daemon start - Confirm a device is visible:
uv run android-emu-agent device list - If needed, start a session explicitly:
uv run android-emu-agent session start --device emulator-5554
License
MIT. See LICENSE.
Project details
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.3.tar.gz.
File metadata
- Download URL: android_emu_agent-0.1.3.tar.gz
- Upload date:
- Size: 48.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.9
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b330841655f0022f640b0cd0f4e07b9fc452e738e54357584a62cc432f8733ca
|
|
| MD5 |
0448c7f9bde783a30294e84b8a07987c
|
|
| BLAKE2b-256 |
8845ff22d414962fb24e8c92073522f48cf22523f4d6962bf8fa373dec75eab9
|
File details
Details for the file android_emu_agent-0.1.3-py3-none-any.whl.
File metadata
- Download URL: android_emu_agent-0.1.3-py3-none-any.whl
- Upload date:
- Size: 66.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.9
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
2b1dc2e8b524c7488da2be6a581df4d30d8bb2baaa316245be97e0fb905b0945
|
|
| MD5 |
26f08d457c3819e85ec675773b517ea6
|
|
| BLAKE2b-256 |
1c4e4b838a51963a851347d06dbf85eef249c0e4a0b7e5e52ed4eeef8daf2c3e
|