android-emu-agent 0.1.3__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- android_emu_agent-0.1.3/.gitignore +76 -0
- android_emu_agent-0.1.3/LICENSE +21 -0
- android_emu_agent-0.1.3/PKG-INFO +375 -0
- android_emu_agent-0.1.3/README.md +345 -0
- android_emu_agent-0.1.3/pyproject.toml +116 -0
- android_emu_agent-0.1.3/src/android_emu_agent/__init__.py +3 -0
- android_emu_agent-0.1.3/src/android_emu_agent/actions/__init__.py +1 -0
- android_emu_agent-0.1.3/src/android_emu_agent/actions/executor.py +288 -0
- android_emu_agent-0.1.3/src/android_emu_agent/actions/selector.py +122 -0
- android_emu_agent-0.1.3/src/android_emu_agent/actions/wait.py +193 -0
- android_emu_agent-0.1.3/src/android_emu_agent/artifacts/__init__.py +1 -0
- android_emu_agent-0.1.3/src/android_emu_agent/artifacts/manager.py +125 -0
- android_emu_agent-0.1.3/src/android_emu_agent/artifacts/py.typed +0 -0
- android_emu_agent-0.1.3/src/android_emu_agent/cli/__init__.py +1 -0
- android_emu_agent-0.1.3/src/android_emu_agent/cli/commands/__init__.py +1 -0
- android_emu_agent-0.1.3/src/android_emu_agent/cli/commands/action.py +158 -0
- android_emu_agent-0.1.3/src/android_emu_agent/cli/commands/app_cmd.py +95 -0
- android_emu_agent-0.1.3/src/android_emu_agent/cli/commands/artifact.py +81 -0
- android_emu_agent-0.1.3/src/android_emu_agent/cli/commands/daemon.py +62 -0
- android_emu_agent-0.1.3/src/android_emu_agent/cli/commands/device.py +122 -0
- android_emu_agent-0.1.3/src/android_emu_agent/cli/commands/emulator.py +46 -0
- android_emu_agent-0.1.3/src/android_emu_agent/cli/commands/file.py +139 -0
- android_emu_agent-0.1.3/src/android_emu_agent/cli/commands/reliability.py +310 -0
- android_emu_agent-0.1.3/src/android_emu_agent/cli/commands/session.py +65 -0
- android_emu_agent-0.1.3/src/android_emu_agent/cli/commands/ui.py +112 -0
- android_emu_agent-0.1.3/src/android_emu_agent/cli/commands/wait.py +132 -0
- android_emu_agent-0.1.3/src/android_emu_agent/cli/daemon_client.py +185 -0
- android_emu_agent-0.1.3/src/android_emu_agent/cli/main.py +52 -0
- android_emu_agent-0.1.3/src/android_emu_agent/cli/utils.py +171 -0
- android_emu_agent-0.1.3/src/android_emu_agent/daemon/__init__.py +1 -0
- android_emu_agent-0.1.3/src/android_emu_agent/daemon/core.py +62 -0
- android_emu_agent-0.1.3/src/android_emu_agent/daemon/health.py +177 -0
- android_emu_agent-0.1.3/src/android_emu_agent/daemon/models.py +244 -0
- android_emu_agent-0.1.3/src/android_emu_agent/daemon/server.py +1644 -0
- android_emu_agent-0.1.3/src/android_emu_agent/db/__init__.py +1 -0
- android_emu_agent-0.1.3/src/android_emu_agent/db/models.py +229 -0
- android_emu_agent-0.1.3/src/android_emu_agent/device/__init__.py +1 -0
- android_emu_agent-0.1.3/src/android_emu_agent/device/manager.py +522 -0
- android_emu_agent-0.1.3/src/android_emu_agent/device/session.py +129 -0
- android_emu_agent-0.1.3/src/android_emu_agent/errors.py +232 -0
- android_emu_agent-0.1.3/src/android_emu_agent/files/__init__.py +1 -0
- android_emu_agent-0.1.3/src/android_emu_agent/files/manager.py +311 -0
- android_emu_agent-0.1.3/src/android_emu_agent/py.typed +0 -0
- android_emu_agent-0.1.3/src/android_emu_agent/reliability/__init__.py +1 -0
- android_emu_agent-0.1.3/src/android_emu_agent/reliability/manager.py +244 -0
- android_emu_agent-0.1.3/src/android_emu_agent/ui/__init__.py +1 -0
- android_emu_agent-0.1.3/src/android_emu_agent/ui/context.py +169 -0
- android_emu_agent-0.1.3/src/android_emu_agent/ui/ref_resolver.py +149 -0
- android_emu_agent-0.1.3/src/android_emu_agent/ui/snapshotter.py +236 -0
- android_emu_agent-0.1.3/src/android_emu_agent/validation.py +59 -0
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
# Python
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
*$py.class
|
|
5
|
+
*.so
|
|
6
|
+
.Python
|
|
7
|
+
build/
|
|
8
|
+
develop-eggs/
|
|
9
|
+
dist/
|
|
10
|
+
downloads/
|
|
11
|
+
eggs/
|
|
12
|
+
.eggs/
|
|
13
|
+
lib/
|
|
14
|
+
lib64/
|
|
15
|
+
parts/
|
|
16
|
+
sdist/
|
|
17
|
+
var/
|
|
18
|
+
wheels/
|
|
19
|
+
*.egg-info/
|
|
20
|
+
.installed.cfg
|
|
21
|
+
*.egg
|
|
22
|
+
|
|
23
|
+
# Virtual environments
|
|
24
|
+
.venv/
|
|
25
|
+
venv/
|
|
26
|
+
ENV/
|
|
27
|
+
|
|
28
|
+
# uv
|
|
29
|
+
.python-version
|
|
30
|
+
|
|
31
|
+
# IDE
|
|
32
|
+
.idea/
|
|
33
|
+
.vscode/
|
|
34
|
+
.claude/
|
|
35
|
+
*.swp
|
|
36
|
+
*.swo
|
|
37
|
+
*~
|
|
38
|
+
|
|
39
|
+
# Node
|
|
40
|
+
node_modules/
|
|
41
|
+
|
|
42
|
+
# Testing
|
|
43
|
+
.pytest_cache/
|
|
44
|
+
.coverage
|
|
45
|
+
htmlcov/
|
|
46
|
+
.tox/
|
|
47
|
+
.nox/
|
|
48
|
+
|
|
49
|
+
# Type checking
|
|
50
|
+
.mypy_cache/
|
|
51
|
+
.dmypy.json
|
|
52
|
+
dmypy.json
|
|
53
|
+
|
|
54
|
+
# Ruff
|
|
55
|
+
.ruff_cache/
|
|
56
|
+
|
|
57
|
+
# Project specific
|
|
58
|
+
.android-agent/
|
|
59
|
+
.android-agent-artifacts/
|
|
60
|
+
*.db
|
|
61
|
+
|
|
62
|
+
# Logs
|
|
63
|
+
*.log
|
|
64
|
+
logs/
|
|
65
|
+
|
|
66
|
+
# Environment
|
|
67
|
+
.env
|
|
68
|
+
.env.local
|
|
69
|
+
.env.*.local
|
|
70
|
+
|
|
71
|
+
# OS
|
|
72
|
+
.DS_Store
|
|
73
|
+
Thumbs.db
|
|
74
|
+
|
|
75
|
+
docs/plan/
|
|
76
|
+
/artifacts/
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Android Agent Team
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,375 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: android-emu-agent
|
|
3
|
+
Version: 0.1.3
|
|
4
|
+
Summary: CLI + daemon for LLM-driven Android UI control on emulators and rooted devices
|
|
5
|
+
Project-URL: Homepage, https://github.com/alehkot/android-emu-agent
|
|
6
|
+
Author-email: Oleg Kot <kot.oleg@gmail.com>
|
|
7
|
+
License-Expression: MIT
|
|
8
|
+
License-File: LICENSE
|
|
9
|
+
Keywords: android,automation,llm,ui-testing
|
|
10
|
+
Requires-Python: >=3.11
|
|
11
|
+
Requires-Dist: adbutils>=2.0.0
|
|
12
|
+
Requires-Dist: aiosqlite>=0.19.0
|
|
13
|
+
Requires-Dist: fastapi>=0.128.1
|
|
14
|
+
Requires-Dist: httpx>=0.27.0
|
|
15
|
+
Requires-Dist: lxml>=5.0.0
|
|
16
|
+
Requires-Dist: pydantic>=2.5.0
|
|
17
|
+
Requires-Dist: structlog>=24.0.0
|
|
18
|
+
Requires-Dist: typer>=0.9.0
|
|
19
|
+
Requires-Dist: uiautomator2>=3.0.0
|
|
20
|
+
Requires-Dist: uvicorn[standard]>=0.27.0
|
|
21
|
+
Provides-Extra: dev
|
|
22
|
+
Requires-Dist: lxml-stubs>=0.5.0; extra == 'dev'
|
|
23
|
+
Requires-Dist: mypy>=1.8.0; extra == 'dev'
|
|
24
|
+
Requires-Dist: pyright>=1.1.0; extra == 'dev'
|
|
25
|
+
Requires-Dist: pytest-asyncio>=0.23.0; extra == 'dev'
|
|
26
|
+
Requires-Dist: pytest-cov>=4.1.0; extra == 'dev'
|
|
27
|
+
Requires-Dist: pytest>=8.0.0; extra == 'dev'
|
|
28
|
+
Requires-Dist: ruff>=0.2.0; extra == 'dev'
|
|
29
|
+
Description-Content-Type: text/markdown
|
|
30
|
+
|
|
31
|
+
# Android Emu Agent
|
|
32
|
+
|
|
33
|
+
A CLI + daemon system for LLM-driven Android UI control on emulators and rooted devices.
|
|
34
|
+
|
|
35
|
+
## Overview
|
|
36
|
+
|
|
37
|
+
Android Emu Agent automates Android apps using a fast observe-act-verify loop:
|
|
38
|
+
|
|
39
|
+
1. Observe: capture a compact UI snapshot (interactive elements only)
|
|
40
|
+
2. Act: issue commands using ephemeral element refs like `@a1`
|
|
41
|
+
3. Verify: re-snapshot when needed
|
|
42
|
+
|
|
43
|
+
The CLI is a thin client. A long-running daemon handles all device I/O.
|
|
44
|
+
|
|
45
|
+
## Inspiration
|
|
46
|
+
|
|
47
|
+
Inspired by [agent-browser](https://github.com/vercel-labs/agent-browser), a fast headless browser
|
|
48
|
+
automation CLI for AI agents.
|
|
49
|
+
|
|
50
|
+
## Requirements
|
|
51
|
+
|
|
52
|
+
- Python 3.11+
|
|
53
|
+
- `uv` package manager
|
|
54
|
+
- Android SDK with `adb` on PATH
|
|
55
|
+
- Android emulator or rooted device (primary target)
|
|
56
|
+
|
|
57
|
+
## Install
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
# Clone the repository
|
|
61
|
+
git clone https://github.com/alehkot/android-emu-agent.git
|
|
62
|
+
cd android-emu-agent
|
|
63
|
+
|
|
64
|
+
# Install dependencies
|
|
65
|
+
uv sync
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
Inside this repo, prefer `uv run android-emu-agent <command>`.
|
|
69
|
+
|
|
70
|
+
## Quick Start (2 minutes)
|
|
71
|
+
|
|
72
|
+
```bash
|
|
73
|
+
# 1. Start the daemon (optional, CLI will auto-start by default)
|
|
74
|
+
uv run android-emu-agent daemon start
|
|
75
|
+
|
|
76
|
+
# 2. List connected devices
|
|
77
|
+
uv run android-emu-agent device list
|
|
78
|
+
|
|
79
|
+
# 3. Start a session (prints the session id)
|
|
80
|
+
uv run android-emu-agent session start --device emulator-5554
|
|
81
|
+
|
|
82
|
+
# 4. Take a compact snapshot and read refs
|
|
83
|
+
uv run android-emu-agent ui snapshot s-abc123 --format text
|
|
84
|
+
|
|
85
|
+
# 5. Tap an element using a ref
|
|
86
|
+
uv run android-emu-agent action tap s-abc123 @a1
|
|
87
|
+
|
|
88
|
+
# 6. Stop the session
|
|
89
|
+
uv run android-emu-agent session stop s-abc123
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
Most commands accept `--json` for machine-readable output.
|
|
93
|
+
|
|
94
|
+
Example `--json` output for `session start`:
|
|
95
|
+
|
|
96
|
+
```json
|
|
97
|
+
{
|
|
98
|
+
"status": "done",
|
|
99
|
+
"session_id": "s-abc123",
|
|
100
|
+
"device_serial": "emulator-5554",
|
|
101
|
+
"generation": 0
|
|
102
|
+
}
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
## Core Concepts
|
|
106
|
+
|
|
107
|
+
Sessions
|
|
108
|
+
|
|
109
|
+
- Sessions tie actions to a specific device. Most commands accept a session id.
|
|
110
|
+
- `session start` returns a session id. `session stop` releases it.
|
|
111
|
+
|
|
112
|
+
Snapshots and refs
|
|
113
|
+
|
|
114
|
+
- `ui snapshot` returns `@refs` that are stable only for that snapshot.
|
|
115
|
+
- If you get `ERR_STALE_REF`, take a new snapshot and use fresh refs.
|
|
116
|
+
|
|
117
|
+
Selectors
|
|
118
|
+
|
|
119
|
+
- `action tap` accepts an `@ref` or a selector.
|
|
120
|
+
- `long-tap`, `set-text`, and `clear` require an `@ref`.
|
|
121
|
+
|
|
122
|
+
Selector examples:
|
|
123
|
+
|
|
124
|
+
```text
|
|
125
|
+
@a1
|
|
126
|
+
text:"Sign in"
|
|
127
|
+
id:com.example:id/login_btn
|
|
128
|
+
desc:"Open navigation"
|
|
129
|
+
coords:120,450
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
## Snapshot Format
|
|
133
|
+
|
|
134
|
+
Compact snapshot output includes context and interactive elements only:
|
|
135
|
+
|
|
136
|
+
```json
|
|
137
|
+
{
|
|
138
|
+
"schema_version": 1,
|
|
139
|
+
"session_id": "s-abc123",
|
|
140
|
+
"generation": 42,
|
|
141
|
+
"context": {
|
|
142
|
+
"package": "com.example.app",
|
|
143
|
+
"activity": ".MainActivity",
|
|
144
|
+
"orientation": "PORTRAIT",
|
|
145
|
+
"ime_visible": false
|
|
146
|
+
},
|
|
147
|
+
"elements": [
|
|
148
|
+
{
|
|
149
|
+
"ref": "@a1",
|
|
150
|
+
"role": "button",
|
|
151
|
+
"label": "Sign in",
|
|
152
|
+
"resource_id": "com.example:id/login_btn",
|
|
153
|
+
"bounds": [100, 200, 300, 250],
|
|
154
|
+
"state": { "clickable": true, "enabled": true }
|
|
155
|
+
}
|
|
156
|
+
]
|
|
157
|
+
}
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
## Daemon and State
|
|
161
|
+
|
|
162
|
+
- Socket: `/tmp/android-emu-agent.sock`
|
|
163
|
+
- Logs: `~/.android-emu-agent/daemon.log`
|
|
164
|
+
- PID file: `~/.android-emu-agent/daemon.pid`
|
|
165
|
+
|
|
166
|
+
The CLI auto-starts the daemon on first request. Use these to debug:
|
|
167
|
+
|
|
168
|
+
```bash
|
|
169
|
+
uv run android-emu-agent daemon status --json
|
|
170
|
+
uv run android-emu-agent daemon stop
|
|
171
|
+
uv run android-emu-agent daemon start
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
## Common Workflows
|
|
175
|
+
|
|
176
|
+
Login flow
|
|
177
|
+
|
|
178
|
+
```bash
|
|
179
|
+
uv run android-emu-agent app launch s-abc123 com.example.app
|
|
180
|
+
uv run android-emu-agent wait idle s-abc123 --timeout-ms 5000
|
|
181
|
+
uv run android-emu-agent ui snapshot s-abc123 --format text
|
|
182
|
+
uv run android-emu-agent action set-text s-abc123 @a3 "user@example.com"
|
|
183
|
+
uv run android-emu-agent action set-text s-abc123 @a4 "hunter2"
|
|
184
|
+
uv run android-emu-agent action tap s-abc123 @a5
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
When elements are missing
|
|
188
|
+
|
|
189
|
+
```bash
|
|
190
|
+
uv run android-emu-agent ui snapshot s-abc123 --full
|
|
191
|
+
uv run android-emu-agent wait idle s-abc123 --timeout-ms 3000
|
|
192
|
+
uv run android-emu-agent ui snapshot s-abc123
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
Visual debug
|
|
196
|
+
|
|
197
|
+
```bash
|
|
198
|
+
uv run android-emu-agent ui screenshot --device emulator-5554 --pull --output ./screen.png
|
|
199
|
+
uv run android-emu-agent artifact bundle s-abc123
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
Emulator snapshots
|
|
203
|
+
|
|
204
|
+
```bash
|
|
205
|
+
uv run android-emu-agent emulator snapshot save emulator-5554 clean
|
|
206
|
+
uv run android-emu-agent emulator snapshot restore emulator-5554 clean
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
These commands require an emulator serial (`emulator-5554`). If you pass a non-emulator serial, you
|
|
210
|
+
will see `ERR_NOT_EMULATOR`.
|
|
211
|
+
|
|
212
|
+
## Real Devices (Non-Root)
|
|
213
|
+
|
|
214
|
+
The project targets emulators and rooted devices, but many commands do not enforce root and can work
|
|
215
|
+
on real devices as long as `adb` is connected and uiautomator2 can attach (ATX server on port 7912).
|
|
216
|
+
In practice, these are usually safe on non-root devices:
|
|
217
|
+
|
|
218
|
+
- UI snapshots and screenshots
|
|
219
|
+
- Actions (tap, set-text, swipe, scroll, back/home/recents)
|
|
220
|
+
- Wait commands
|
|
221
|
+
- App list/launch/force-stop/reset/deeplink
|
|
222
|
+
- File `push` and `pull` to shared storage
|
|
223
|
+
|
|
224
|
+
Emulator-only commands are `emulator snapshot save|restore`. Root-required commands are listed
|
|
225
|
+
below.
|
|
226
|
+
|
|
227
|
+
## Root-Required Operations
|
|
228
|
+
|
|
229
|
+
The following require a rooted device or emulator with root access:
|
|
230
|
+
|
|
231
|
+
- `reliability oom-adj`
|
|
232
|
+
- `reliability pull anr`
|
|
233
|
+
- `reliability pull tombstones`
|
|
234
|
+
- `reliability pull dropbox`
|
|
235
|
+
- `file find`
|
|
236
|
+
- `file list`
|
|
237
|
+
- `file app push`
|
|
238
|
+
- `file app pull`
|
|
239
|
+
|
|
240
|
+
If root is missing, you will see `ERR_PERMISSION`.
|
|
241
|
+
|
|
242
|
+
## Artifacts
|
|
243
|
+
|
|
244
|
+
Artifacts are written to `~/.android-emu-agent/artifacts` by default.
|
|
245
|
+
|
|
246
|
+
- Reliability outputs: `~/.android-emu-agent/artifacts/reliability`
|
|
247
|
+
- File transfers: `~/.android-emu-agent/artifacts/files`
|
|
248
|
+
|
|
249
|
+
## Troubleshooting
|
|
250
|
+
|
|
251
|
+
Quick checks
|
|
252
|
+
|
|
253
|
+
```bash
|
|
254
|
+
uv run android-emu-agent device list
|
|
255
|
+
adb devices
|
|
256
|
+
uv run android-emu-agent daemon status --json
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
Common errors
|
|
260
|
+
|
|
261
|
+
| Error Code | Meaning | Fix |
|
|
262
|
+
| --------------------- | ------------------------ | ----------------------------------------------- |
|
|
263
|
+
| `ERR_STALE_REF` | Ref from an old snapshot | Take a new snapshot |
|
|
264
|
+
| `ERR_NOT_FOUND` | Element not found | Verify screen, use `--full` or a selector |
|
|
265
|
+
| `ERR_BLOCKED_INPUT` | Dialog/IME blocking | `wait idle` or `back` |
|
|
266
|
+
| `ERR_TIMEOUT` | Wait condition not met | Increase `--timeout-ms` or check condition |
|
|
267
|
+
| `ERR_DEVICE_OFFLINE` | Device disconnected | Reconnect and re-run `device list` |
|
|
268
|
+
| `ERR_SESSION_EXPIRED` | Session is gone | Start a new session |
|
|
269
|
+
| `ERR_PERMISSION` | Root required | Use a rooted device/emulator |
|
|
270
|
+
| `ERR_ADB_NOT_FOUND` | `adb` not on PATH | Install Android SDK and ensure `adb` is on PATH |
|
|
271
|
+
| `ERR_ADB_COMMAND` | ADB command failed | Check device connectivity and retry |
|
|
272
|
+
|
|
273
|
+
For deeper guidance, see `skills/android-emu-agent/references/troubleshooting.md`.
|
|
274
|
+
|
|
275
|
+
## CLI Reference
|
|
276
|
+
|
|
277
|
+
A concise command list lives at `skills/android-emu-agent/references/command-reference.md`.
|
|
278
|
+
|
|
279
|
+
If you prefer an interactive guide:
|
|
280
|
+
|
|
281
|
+
```bash
|
|
282
|
+
uv run android-emu-agent --help
|
|
283
|
+
uv run android-emu-agent <group> --help
|
|
284
|
+
```
|
|
285
|
+
|
|
286
|
+
## Architecture
|
|
287
|
+
|
|
288
|
+
```text
|
|
289
|
+
┌─────────────────┐ Unix Socket ┌──────────────────────────────────┐
|
|
290
|
+
│ │ ◄────────────────► │ Daemon │
|
|
291
|
+
│ CLI Client │ │ ┌────────────────────────────┐ │
|
|
292
|
+
│ │ │ │ Device Manager │ │
|
|
293
|
+
└─────────────────┘ │ │ (adbutils, uiautomator2) │ │
|
|
294
|
+
│ └────────────────────────────┘ │
|
|
295
|
+
│ ┌────────────────────────────┐ │
|
|
296
|
+
│ │ Session Manager │ │
|
|
297
|
+
│ │ (refs, state, SQLite) │ │
|
|
298
|
+
│ └────────────────────────────┘ │
|
|
299
|
+
│ ┌────────────────────────────┐ │
|
|
300
|
+
│ │ UI Snapshotter │ │
|
|
301
|
+
│ │ (lxml, filtering) │ │
|
|
302
|
+
│ └────────────────────────────┘ │
|
|
303
|
+
└──────────────────────────────────┘
|
|
304
|
+
│
|
|
305
|
+
▼
|
|
306
|
+
┌──────────────────────────────────┐
|
|
307
|
+
│ Android Device/Emulator │
|
|
308
|
+
│ (ATX Server on port 7912) │
|
|
309
|
+
└──────────────────────────────────┘
|
|
310
|
+
```
|
|
311
|
+
|
|
312
|
+
## Development
|
|
313
|
+
|
|
314
|
+
```bash
|
|
315
|
+
# Install with dev dependencies
|
|
316
|
+
uv sync --all-extras
|
|
317
|
+
|
|
318
|
+
# Run tests
|
|
319
|
+
uv run pytest tests/unit -v
|
|
320
|
+
|
|
321
|
+
# Run linter
|
|
322
|
+
uv run ruff check .
|
|
323
|
+
|
|
324
|
+
# Format code
|
|
325
|
+
uv run ruff format .
|
|
326
|
+
|
|
327
|
+
# Type check
|
|
328
|
+
uv run mypy src/
|
|
329
|
+
|
|
330
|
+
# Run all checks
|
|
331
|
+
./scripts/dev.sh check
|
|
332
|
+
```
|
|
333
|
+
|
|
334
|
+
## Agent Skills
|
|
335
|
+
|
|
336
|
+
This repo ships an `android-emu-agent` skill in `skills/android-emu-agent/` for agent environments
|
|
337
|
+
that support skills. Use the install steps below.
|
|
338
|
+
|
|
339
|
+
### Install for Codex
|
|
340
|
+
|
|
341
|
+
```bash
|
|
342
|
+
export CODEX_HOME="$HOME/.codex"
|
|
343
|
+
mkdir -p "$CODEX_HOME/skills"
|
|
344
|
+
ln -sfn "$(pwd)/skills/android-emu-agent" "$CODEX_HOME/skills/android-emu-agent"
|
|
345
|
+
```
|
|
346
|
+
|
|
347
|
+
### Install for Claude Code
|
|
348
|
+
|
|
349
|
+
```bash
|
|
350
|
+
mkdir -p ~/.claude/skills
|
|
351
|
+
ln -sfn "$(pwd)/skills/android-emu-agent" ~/.claude/skills/android-emu-agent
|
|
352
|
+
```
|
|
353
|
+
|
|
354
|
+
If symlinks are not an option, copy the directory instead.
|
|
355
|
+
|
|
356
|
+
### Using the Skill
|
|
357
|
+
|
|
358
|
+
After installation, the agent should be primed to start a session with your connected device before
|
|
359
|
+
you ask for specific actions. Begin with a direct initialization request, for example:
|
|
360
|
+
|
|
361
|
+
`I want to interact with my connected Android emulator.`
|
|
362
|
+
|
|
363
|
+
Once the agent has initialized the session, you can proceed with normal requests (snapshots,
|
|
364
|
+
tap/type actions, app launches, waits, etc.).
|
|
365
|
+
|
|
366
|
+
Prerequisites you may need (if the agent reports it cannot connect):
|
|
367
|
+
|
|
368
|
+
1. Start the daemon: `uv run android-emu-agent daemon start`
|
|
369
|
+
2. Confirm a device is visible: `uv run android-emu-agent device list`
|
|
370
|
+
3. If needed, start a session explicitly:
|
|
371
|
+
`uv run android-emu-agent session start --device emulator-5554`
|
|
372
|
+
|
|
373
|
+
## License
|
|
374
|
+
|
|
375
|
+
MIT. See `LICENSE`.
|