ghost-in-the-droid 1.0.0__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.
- ghost_in_the_droid-1.0.0/LICENSE +21 -0
- ghost_in_the_droid-1.0.0/PKG-INFO +404 -0
- ghost_in_the_droid-1.0.0/README.md +360 -0
- ghost_in_the_droid-1.0.0/ghost_in_the_droid.egg-info/PKG-INFO +404 -0
- ghost_in_the_droid-1.0.0/ghost_in_the_droid.egg-info/SOURCES.txt +83 -0
- ghost_in_the_droid-1.0.0/ghost_in_the_droid.egg-info/dependency_links.txt +1 -0
- ghost_in_the_droid-1.0.0/ghost_in_the_droid.egg-info/entry_points.txt +3 -0
- ghost_in_the_droid-1.0.0/ghost_in_the_droid.egg-info/requires.txt +28 -0
- ghost_in_the_droid-1.0.0/ghost_in_the_droid.egg-info/top_level.txt +1 -0
- ghost_in_the_droid-1.0.0/gitd/__init__.py +0 -0
- ghost_in_the_droid-1.0.0/gitd/alembic/alembic/env.py +89 -0
- ghost_in_the_droid-1.0.0/gitd/alembic/env.py +89 -0
- ghost_in_the_droid-1.0.0/gitd/app.py +126 -0
- ghost_in_the_droid-1.0.0/gitd/bots/__init__.py +0 -0
- ghost_in_the_droid-1.0.0/gitd/bots/common/__init__.py +0 -0
- ghost_in_the_droid-1.0.0/gitd/bots/common/adb.py +780 -0
- ghost_in_the_droid-1.0.0/gitd/bots/common/discover_rids.py +313 -0
- ghost_in_the_droid-1.0.0/gitd/bots/common/elements.py +290 -0
- ghost_in_the_droid-1.0.0/gitd/cli.py +578 -0
- ghost_in_the_droid-1.0.0/gitd/config.py +36 -0
- ghost_in_the_droid-1.0.0/gitd/mcp_server.py +560 -0
- ghost_in_the_droid-1.0.0/gitd/models/__init__.py +36 -0
- ghost_in_the_droid-1.0.0/gitd/models/base.py +50 -0
- ghost_in_the_droid-1.0.0/gitd/models/bot.py +42 -0
- ghost_in_the_droid-1.0.0/gitd/models/chat.py +36 -0
- ghost_in_the_droid-1.0.0/gitd/models/phone.py +34 -0
- ghost_in_the_droid-1.0.0/gitd/models/schedule.py +68 -0
- ghost_in_the_droid-1.0.0/gitd/models/skill_compat.py +50 -0
- ghost_in_the_droid-1.0.0/gitd/routers/__init__.py +0 -0
- ghost_in_the_droid-1.0.0/gitd/routers/agent_chat.py +186 -0
- ghost_in_the_droid-1.0.0/gitd/routers/bot.py +277 -0
- ghost_in_the_droid-1.0.0/gitd/routers/creator.py +356 -0
- ghost_in_the_droid-1.0.0/gitd/routers/emulators.py +311 -0
- ghost_in_the_droid-1.0.0/gitd/routers/explorer.py +210 -0
- ghost_in_the_droid-1.0.0/gitd/routers/misc.py +101 -0
- ghost_in_the_droid-1.0.0/gitd/routers/phone.py +501 -0
- ghost_in_the_droid-1.0.0/gitd/routers/scheduler.py +444 -0
- ghost_in_the_droid-1.0.0/gitd/routers/skills.py +502 -0
- ghost_in_the_droid-1.0.0/gitd/routers/stats.py +11 -0
- ghost_in_the_droid-1.0.0/gitd/routers/streaming.py +535 -0
- ghost_in_the_droid-1.0.0/gitd/routers/streaming_viewers.py +113 -0
- ghost_in_the_droid-1.0.0/gitd/routers/tests.py +370 -0
- ghost_in_the_droid-1.0.0/gitd/routers/tools_hub.py +155 -0
- ghost_in_the_droid-1.0.0/gitd/schemas/__init__.py +1 -0
- ghost_in_the_droid-1.0.0/gitd/schemas/common.py +16 -0
- ghost_in_the_droid-1.0.0/gitd/services/__init__.py +0 -0
- ghost_in_the_droid-1.0.0/gitd/services/_emulator_helpers.py +319 -0
- ghost_in_the_droid-1.0.0/gitd/services/_emulator_pool.py +161 -0
- ghost_in_the_droid-1.0.0/gitd/services/_job_helpers.py +209 -0
- ghost_in_the_droid-1.0.0/gitd/services/agent_chat.py +733 -0
- ghost_in_the_droid-1.0.0/gitd/services/agent_chat_claude_code.py +207 -0
- ghost_in_the_droid-1.0.0/gitd/services/agent_tools.py +486 -0
- ghost_in_the_droid-1.0.0/gitd/services/db_helpers.py +137 -0
- ghost_in_the_droid-1.0.0/gitd/services/device_context.py +903 -0
- ghost_in_the_droid-1.0.0/gitd/services/emulator_service.py +400 -0
- ghost_in_the_droid-1.0.0/gitd/services/job_engine.py +498 -0
- ghost_in_the_droid-1.0.0/gitd/services/scheduler_service.py +301 -0
- ghost_in_the_droid-1.0.0/gitd/skills/__init__.py +4 -0
- ghost_in_the_droid-1.0.0/gitd/skills/_base/__init__.py +18 -0
- ghost_in_the_droid-1.0.0/gitd/skills/_base/actions/__init__.py +10 -0
- ghost_in_the_droid-1.0.0/gitd/skills/_base/actions/core.py +168 -0
- ghost_in_the_droid-1.0.0/gitd/skills/_run_skill.py +235 -0
- ghost_in_the_droid-1.0.0/gitd/skills/auto_creator.py +424 -0
- ghost_in_the_droid-1.0.0/gitd/skills/base.py +483 -0
- ghost_in_the_droid-1.0.0/gitd/skills/gmail_utils.py +235 -0
- ghost_in_the_droid-1.0.0/gitd/skills/macro_recorder.py +196 -0
- ghost_in_the_droid-1.0.0/gitd/skills/play_store/__init__.py +19 -0
- ghost_in_the_droid-1.0.0/gitd/skills/play_store/actions/__init__.py +0 -0
- ghost_in_the_droid-1.0.0/gitd/skills/play_store/actions/core.py +140 -0
- ghost_in_the_droid-1.0.0/gitd/skills/play_store/workflows.py +68 -0
- ghost_in_the_droid-1.0.0/gitd/skills/send_gmail_email/__init__.py +1 -0
- ghost_in_the_droid-1.0.0/gitd/skills/send_gmail_email/actions/__init__.py +0 -0
- ghost_in_the_droid-1.0.0/gitd/skills/send_gmail_email/workflows/__init__.py +0 -0
- ghost_in_the_droid-1.0.0/gitd/skills/test_pic/__init__.py +1 -0
- ghost_in_the_droid-1.0.0/gitd/skills/tiktok/__init__.py +21 -0
- ghost_in_the_droid-1.0.0/gitd/skills/tiktok/actions/__init__.py +8 -0
- ghost_in_the_droid-1.0.0/gitd/skills/tiktok/actions/core.py +119 -0
- ghost_in_the_droid-1.0.0/gitd/skills/tiktok/workflows/__init__.py +1 -0
- ghost_in_the_droid-1.0.0/gitd/skills/tiktok/workflows/publish_draft.py +33 -0
- ghost_in_the_droid-1.0.0/gitd/skills/tiktok/workflows/upload_video.py +57 -0
- ghost_in_the_droid-1.0.0/gitd/tools/__init__.py +0 -0
- ghost_in_the_droid-1.0.0/gitd/tools/tts.py +124 -0
- ghost_in_the_droid-1.0.0/gitd/tools/video_overlay.py +198 -0
- ghost_in_the_droid-1.0.0/pyproject.toml +66 -0
- ghost_in_the_droid-1.0.0/setup.cfg +4 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Ghost in the Droid Contributors
|
|
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,404 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: ghost-in-the-droid
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
Summary: Give any AI agent an Android body. Open-source phone automation via ADB — tap, swipe, type, run skills, scale across devices.
|
|
5
|
+
License: MIT
|
|
6
|
+
Project-URL: Homepage, https://ghostinthedroid.com
|
|
7
|
+
Project-URL: Repository, https://github.com/ghost-in-the-droid/android-agent
|
|
8
|
+
Project-URL: Documentation, https://ghostinthedroid.com/getting-started/installation/
|
|
9
|
+
Project-URL: Issues, https://github.com/ghost-in-the-droid/android-agent/issues
|
|
10
|
+
Keywords: android,adb,automation,ghost,agent,mcp,fastapi,phone-farm
|
|
11
|
+
Classifier: Development Status :: 4 - Beta
|
|
12
|
+
Classifier: Framework :: FastAPI
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
16
|
+
Classifier: Topic :: Software Development :: Testing
|
|
17
|
+
Requires-Python: >=3.10
|
|
18
|
+
Description-Content-Type: text/markdown
|
|
19
|
+
License-File: LICENSE
|
|
20
|
+
Requires-Dist: fastapi>=0.115
|
|
21
|
+
Requires-Dist: uvicorn[standard]>=0.30
|
|
22
|
+
Requires-Dist: sqlalchemy>=2.0
|
|
23
|
+
Requires-Dist: alembic>=1.13
|
|
24
|
+
Requires-Dist: pydantic>=2.9
|
|
25
|
+
Requires-Dist: pydantic-settings>=2.5
|
|
26
|
+
Requires-Dist: requests>=2.31
|
|
27
|
+
Requires-Dist: python-dotenv>=1.0
|
|
28
|
+
Requires-Dist: pyyaml>=6.0
|
|
29
|
+
Requires-Dist: psutil>=5.9
|
|
30
|
+
Requires-Dist: openai>=1.0
|
|
31
|
+
Requires-Dist: mcp>=1.20
|
|
32
|
+
Provides-Extra: llm
|
|
33
|
+
Requires-Dist: anthropic>=0.30; extra == "llm"
|
|
34
|
+
Provides-Extra: analytics
|
|
35
|
+
Requires-Dist: google-analytics-data>=0.18; extra == "analytics"
|
|
36
|
+
Provides-Extra: ocr
|
|
37
|
+
Requires-Dist: rapidocr-onnxruntime>=1.3; extra == "ocr"
|
|
38
|
+
Provides-Extra: test
|
|
39
|
+
Requires-Dist: playwright>=1.40; extra == "test"
|
|
40
|
+
Requires-Dist: pytest>=7.0; extra == "test"
|
|
41
|
+
Provides-Extra: all
|
|
42
|
+
Requires-Dist: ghost-in-the-droid[analytics,llm,ocr,test]; extra == "all"
|
|
43
|
+
Dynamic: license-file
|
|
44
|
+
|
|
45
|
+
# Ghost in the Droid
|
|
46
|
+
|
|
47
|
+
<p align="center">
|
|
48
|
+
<img src="docs/assets/mascot/12-the-tap.png" alt="Ghost tapping a phone" width="200" />
|
|
49
|
+
</p>
|
|
50
|
+
|
|
51
|
+
<p align="center">
|
|
52
|
+
<strong>Summon a ghost into your Android.</strong><br/>
|
|
53
|
+
It sees the screen. It taps the buttons. It never sleeps.
|
|
54
|
+
</p>
|
|
55
|
+
|
|
56
|
+
<p align="center">
|
|
57
|
+
<a href="https://ghostinthedroid.com">Website</a> ·
|
|
58
|
+
<a href="https://ghostinthedroid.com/getting-started/installation/">Docs</a> ·
|
|
59
|
+
<a href="https://ghostinthedroid.com/skills/">Skill Hub</a>
|
|
60
|
+
</p>
|
|
61
|
+
|
|
62
|
+

|
|
63
|
+

|
|
64
|
+

|
|
65
|
+
|
|
66
|
+
---
|
|
67
|
+
|
|
68
|
+
## What It Does
|
|
69
|
+
|
|
70
|
+
Open-source Python framework for controlling real Android phones via ADB. No app installed. No footprint. Pure automation.
|
|
71
|
+
|
|
72
|
+
Define **skills** for any app, run them from the dashboard or API, scale across a phone farm.
|
|
73
|
+
|
|
74
|
+
**The ghost taps what you'd tap**
|
|
75
|
+
- 50+ ADB methods — tap, swipe, type, clipboard, stealth variants
|
|
76
|
+
- Live phone screen streaming (MJPEG and WebRTC)
|
|
77
|
+
- Interactive touch-to-tap on the streamed screen
|
|
78
|
+
- Multi-device phone farm with per-device job queues
|
|
79
|
+
|
|
80
|
+
**Forge reusable skills for any app**
|
|
81
|
+
- YAML-based UI element definitions per app
|
|
82
|
+
- Python action classes with precondition checks
|
|
83
|
+
- Multi-step workflows that chain actions together
|
|
84
|
+
- Built-in skills for TikTok and Play Store
|
|
85
|
+
- **Skill Hub** — browse, search, and install skills from the community registry
|
|
86
|
+
- Install from CLI: `android-agent skill install tiktok`
|
|
87
|
+
|
|
88
|
+
**Teach the ghost new tricks**
|
|
89
|
+
- BFS-based auto app explorer — discovers every screen and transition
|
|
90
|
+
- LLM-assisted Skill Creator — chat with AI while viewing the live device stream
|
|
91
|
+
- The AI identifies UI elements and generates action/workflow code
|
|
92
|
+
|
|
93
|
+
**Scale the haunting**
|
|
94
|
+
- Multi-device phone farm with per-device job queues
|
|
95
|
+
- Bot runner: queue, schedule, and monitor automation jobs
|
|
96
|
+
- Per-device integration tests with ADB screen recording
|
|
97
|
+
|
|
98
|
+
---
|
|
99
|
+
|
|
100
|
+
## Requirements
|
|
101
|
+
|
|
102
|
+
- **Python 3.10+**
|
|
103
|
+
- **Android phone** with USB debugging enabled (Settings > Developer Options > USB Debugging)
|
|
104
|
+
- **ADB** installed and on PATH (`adb devices` should list your phone)
|
|
105
|
+
- **Node.js 18+** (for the frontend dev server)
|
|
106
|
+
|
|
107
|
+
---
|
|
108
|
+
|
|
109
|
+
## Quick Start
|
|
110
|
+
|
|
111
|
+
```bash
|
|
112
|
+
# 1. Clone the repo
|
|
113
|
+
git clone https://github.com/ghost-in-the-droid/android-agent.git
|
|
114
|
+
cd ghost-in-the-droid
|
|
115
|
+
|
|
116
|
+
# 2. Install Python dependencies
|
|
117
|
+
pip install -e ".[all]"
|
|
118
|
+
|
|
119
|
+
# 3. Verify ADB sees your device
|
|
120
|
+
adb devices
|
|
121
|
+
|
|
122
|
+
# 4. Start the backend
|
|
123
|
+
python3 run.py
|
|
124
|
+
# API running at http://localhost:5055
|
|
125
|
+
# Interactive API docs at http://localhost:5055/docs
|
|
126
|
+
|
|
127
|
+
# 5. Start the frontend (separate terminal)
|
|
128
|
+
cd frontend
|
|
129
|
+
npm install
|
|
130
|
+
npx vite --host 0.0.0.0 --port 6175
|
|
131
|
+
# Dashboard at http://localhost:6175
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
### Environment Variables
|
|
135
|
+
|
|
136
|
+
Copy `.env.example` to `.env` (if provided) or create a `.env` file in the project root. The server reads configuration via Pydantic Settings. Optional variables include:
|
|
137
|
+
|
|
138
|
+
| Variable | Purpose |
|
|
139
|
+
|----------|---------|
|
|
140
|
+
| `OPENAI_API_KEY` | LLM features (Skill Creator, Agent Chat) |
|
|
141
|
+
| `ANTHROPIC_API_KEY` | Alternative LLM provider |
|
|
142
|
+
| `OPENROUTER_API_KEY` | OpenRouter LLM provider |
|
|
143
|
+
| `DEFAULT_DEVICE` | ADB serial (auto-detected if empty) |
|
|
144
|
+
|
|
145
|
+
---
|
|
146
|
+
|
|
147
|
+
## Architecture
|
|
148
|
+
|
|
149
|
+
```
|
|
150
|
+
android-agent/
|
|
151
|
+
run.py # Entry point: Uvicorn on :5055
|
|
152
|
+
gitd/
|
|
153
|
+
app.py # FastAPI app factory + plugin hook
|
|
154
|
+
config.py # Pydantic settings from .env
|
|
155
|
+
models/ # SQLAlchemy 2.0 ORM
|
|
156
|
+
schemas/ # Pydantic v2 request/response validation
|
|
157
|
+
routers/ # FastAPI route handlers
|
|
158
|
+
services/ # Business logic helpers
|
|
159
|
+
skills/ # Skill packages per app
|
|
160
|
+
_base/ # Base classes (Skill, Action, Workflow)
|
|
161
|
+
tiktok/ # TikTok skill (elements, actions, workflows)
|
|
162
|
+
play_store/ # Play Store skill (install, update, search)
|
|
163
|
+
bots/
|
|
164
|
+
common/
|
|
165
|
+
adb.py # Device class: tap, swipe, dump XML, wait_for
|
|
166
|
+
mcp_server.py # MCP server — expose tools for any LLM agent
|
|
167
|
+
alembic/ # Database migrations
|
|
168
|
+
frontend/ # Vue 3 + Vite + TypeScript + Tailwind CSS
|
|
169
|
+
src/
|
|
170
|
+
App.vue # Tab shell (9 tabs)
|
|
171
|
+
views/ # One view per tab
|
|
172
|
+
composables/ # Typed API fetch wrapper
|
|
173
|
+
portal/ # Kotlin companion app (WebRTC, accessibility)
|
|
174
|
+
site/ # Docs site (Astro + Starlight)
|
|
175
|
+
tests/ # Integration tests (require a connected phone)
|
|
176
|
+
docs/ # Architecture docs
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
### How It Fits Together
|
|
180
|
+
|
|
181
|
+
1. **Backend** (`run.py`) starts a FastAPI server on port 5055 with routers covering device control, skills, bots, scheduling, and streaming.
|
|
182
|
+
2. **Frontend** (`frontend/`) is a Vue 3 SPA that talks to the backend via `/api/*`. Vite proxies API calls to the backend during development.
|
|
183
|
+
3. **Skills** define how to interact with a specific app. Each skill has a `elements.yaml` (UI elements), Python actions (atomic operations), and workflows (multi-step sequences).
|
|
184
|
+
4. **Bots** are long-running subprocess scripts that use the `Device` class from `bots/common/adb.py` to control the phone. The backend spawns and manages them.
|
|
185
|
+
5. **Database** is SQLite with SQLAlchemy 2.0 ORM and Alembic migrations.
|
|
186
|
+
|
|
187
|
+
---
|
|
188
|
+
|
|
189
|
+
## API Documentation
|
|
190
|
+
|
|
191
|
+
The backend auto-generates interactive API docs via FastAPI:
|
|
192
|
+
|
|
193
|
+
- **Swagger UI**: [http://localhost:5055/docs](http://localhost:5055/docs)
|
|
194
|
+
- **ReDoc**: [http://localhost:5055/redoc](http://localhost:5055/redoc)
|
|
195
|
+
|
|
196
|
+
API domains: phone, streaming, skills, creator, explorer, agent-chat, bot, scheduler, tests, tools, misc.
|
|
197
|
+
|
|
198
|
+
---
|
|
199
|
+
|
|
200
|
+
## Dashboard Tabs
|
|
201
|
+
|
|
202
|
+
| Tab | What It Does |
|
|
203
|
+
|-----|-------------|
|
|
204
|
+
| Phone Agent | Live device stream (MJPEG/WebRTC), tap/swipe on screen, multi-device view |
|
|
205
|
+
| Scheduler | Cron-style job scheduling with queue management |
|
|
206
|
+
| Skill Hub | Browse installed skills, run actions and workflows, export/delete |
|
|
207
|
+
| Skill Creator | LLM-assisted skill builder with live device stream |
|
|
208
|
+
| Skill Miner | Auto app explorer — BFS state discovery with screenshots |
|
|
209
|
+
| Tools | Utility tools hub |
|
|
210
|
+
| Manual Run | Start/stop bot jobs, queue management, logs |
|
|
211
|
+
| Tests | Per-device test runner with screen recording playback |
|
|
212
|
+
| Emulators | Create, boot, snapshot, and manage Android emulators |
|
|
213
|
+
|
|
214
|
+
---
|
|
215
|
+
|
|
216
|
+
## MCP Server — Give Any AI Agent an Android Body
|
|
217
|
+
|
|
218
|
+
The project ships an [MCP](https://modelcontextprotocol.io) server with 35 tools for Android control. Any MCP-compatible AI client (Claude Code, Claude Desktop, Cursor, VS Code Copilot, Windsurf) can use them.
|
|
219
|
+
|
|
220
|
+
### Install
|
|
221
|
+
|
|
222
|
+
One command — works with Claude Code, Codex, Cursor, VS Code Copilot, Windsurf:
|
|
223
|
+
|
|
224
|
+
```bash
|
|
225
|
+
claude mcp add android-agent -- uvx --from ghost-in-the-droid android-agent-mcp
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
That's it. `uvx` installs the package, creates an isolated env, and runs the MCP server. No clone, no venv, no manual setup.
|
|
229
|
+
|
|
230
|
+
**Other clients** — same command, different registration:
|
|
231
|
+
|
|
232
|
+
```bash
|
|
233
|
+
# Codex (OpenAI)
|
|
234
|
+
codex mcp add android-agent -- uvx --from ghost-in-the-droid android-agent-mcp
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
**Claude Desktop** (`~/Library/Application Support/Claude/claude_desktop_config.json`):
|
|
238
|
+
```json
|
|
239
|
+
{
|
|
240
|
+
"mcpServers": {
|
|
241
|
+
"android-agent": {
|
|
242
|
+
"command": "uvx",
|
|
243
|
+
"args": ["--from", "ghost-in-the-droid", "android-agent-mcp"]
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
```
|
|
248
|
+
|
|
249
|
+
**VS Code Copilot** (`.vscode/mcp.json`):
|
|
250
|
+
```json
|
|
251
|
+
{
|
|
252
|
+
"servers": {
|
|
253
|
+
"android-agent": {
|
|
254
|
+
"command": "uvx",
|
|
255
|
+
"args": ["--from", "ghost-in-the-droid", "android-agent-mcp"]
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
**Cursor** (`.cursor/mcp.json`) / **Windsurf** (`~/.codeium/windsurf/mcp_config.json`):
|
|
262
|
+
```json
|
|
263
|
+
{
|
|
264
|
+
"mcpServers": {
|
|
265
|
+
"android-agent": {
|
|
266
|
+
"command": "uvx",
|
|
267
|
+
"args": ["--from", "ghost-in-the-droid", "android-agent-mcp"]
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
```
|
|
272
|
+
|
|
273
|
+
**For contributors** who clone the repo: the `.mcp.json` is already there — 35 tools available on first `claude` launch.
|
|
274
|
+
|
|
275
|
+
### Available tools
|
|
276
|
+
|
|
277
|
+
| Category | Tools |
|
|
278
|
+
|----------|-------|
|
|
279
|
+
| Screen | `screenshot`, `get_elements`, `get_screen_tree`, `get_screen_xml`, `screenshot_annotated`, `screenshot_cropped` |
|
|
280
|
+
| Interaction | `tap`, `tap_element`, `swipe`, `long_press`, `type_text`, `type_unicode`, `press_back`, `press_home`, `press_key` |
|
|
281
|
+
| Apps | `launch_app`, `search_apps`, `list_apps`, `launch_intent` |
|
|
282
|
+
| Context | `get_phone_state`, `classify_screen`, `find_on_screen`, `ocr_screen`, `ocr_region` |
|
|
283
|
+
| Device | `list_devices`, `clipboard_get`, `clipboard_set`, `get_notifications`, `open_notifications`, `toggle_overlay` |
|
|
284
|
+
| Skills | `list_skills`, `run_workflow`, `run_action`, `create_skill`, `explore_app` |
|
|
285
|
+
|
|
286
|
+
---
|
|
287
|
+
|
|
288
|
+
## Skill Hub CLI
|
|
289
|
+
|
|
290
|
+
```bash
|
|
291
|
+
# Search the public registry
|
|
292
|
+
android-agent skill search tiktok
|
|
293
|
+
|
|
294
|
+
# Install a skill
|
|
295
|
+
android-agent skill install tiktok
|
|
296
|
+
|
|
297
|
+
# Install from any GitHub repo
|
|
298
|
+
android-agent skill install github.com/someone/their-skill
|
|
299
|
+
|
|
300
|
+
# List installed skills
|
|
301
|
+
android-agent skill list
|
|
302
|
+
|
|
303
|
+
# Update a skill
|
|
304
|
+
android-agent skill update tiktok
|
|
305
|
+
|
|
306
|
+
# Remove a skill
|
|
307
|
+
android-agent skill remove tiktok
|
|
308
|
+
|
|
309
|
+
# Validate before publishing
|
|
310
|
+
android-agent skill validate ./my-skill/
|
|
311
|
+
```
|
|
312
|
+
|
|
313
|
+
The skill registry lives in [`registry/`](registry/) in this repo. Community skills are auto-discovered nightly from repos tagged `android-agent-skill`.
|
|
314
|
+
|
|
315
|
+
## Teach the Ghost a New App
|
|
316
|
+
|
|
317
|
+
Two ways to forge a skill:
|
|
318
|
+
|
|
319
|
+
**Community skill** (your own repo):
|
|
320
|
+
1. Create a new repo with `skill.yaml`, `elements.yaml`, actions, workflows
|
|
321
|
+
2. Tag your repo with the `android-agent-skill` topic
|
|
322
|
+
3. It appears on the hub automatically (nightly scraper)
|
|
323
|
+
|
|
324
|
+
**Official skill** (PR to this repo):
|
|
325
|
+
1. Build and test as a community skill first
|
|
326
|
+
2. Open a PR adding your skill to [`registry/`](registry/)
|
|
327
|
+
3. CI validates, maintainer reviews, gets "Official" badge
|
|
328
|
+
|
|
329
|
+
Each skill needs:
|
|
330
|
+
- `skill.yaml` — metadata (name, version, app package, actions, workflows)
|
|
331
|
+
- `elements.yaml` — UI element resource IDs and descriptions
|
|
332
|
+
- `actions/` — Python classes extending `Action` with `precondition()` and `execute()`
|
|
333
|
+
- `workflows/` — Python classes extending `Workflow` with `steps()`
|
|
334
|
+
|
|
335
|
+
See [CONTRIBUTING.md](CONTRIBUTING.md) for the full guide.
|
|
336
|
+
|
|
337
|
+
---
|
|
338
|
+
|
|
339
|
+
## Tech Stack
|
|
340
|
+
|
|
341
|
+
| Layer | Technology |
|
|
342
|
+
|-------|-----------|
|
|
343
|
+
| Backend | FastAPI, Uvicorn, Python 3.10+ |
|
|
344
|
+
| ORM | SQLAlchemy 2.0 (Mapped types) |
|
|
345
|
+
| Migrations | Alembic |
|
|
346
|
+
| Validation | Pydantic v2 |
|
|
347
|
+
| Database | SQLite (WAL mode) |
|
|
348
|
+
| Frontend | Vue 3 (Composition API), TypeScript, Vite, Tailwind CSS 4 |
|
|
349
|
+
| Charts | Chart.js 4, Plotly.js |
|
|
350
|
+
| Device Control | ADB (Android Debug Bridge) |
|
|
351
|
+
| Streaming | MJPEG, WebRTC (via Ghost Portal companion app) |
|
|
352
|
+
| LLM | OpenAI, Anthropic (optional) |
|
|
353
|
+
| Linting | Ruff |
|
|
354
|
+
| Testing | pytest, Playwright (optional) |
|
|
355
|
+
|
|
356
|
+
---
|
|
357
|
+
|
|
358
|
+
## Running Tests
|
|
359
|
+
|
|
360
|
+
Tests are integration tests that require a connected Android phone:
|
|
361
|
+
|
|
362
|
+
```bash
|
|
363
|
+
# Run all tests on a specific device
|
|
364
|
+
DEVICE=<serial> python3 -m pytest tests/ -v --tb=short
|
|
365
|
+
|
|
366
|
+
# Run a single test file
|
|
367
|
+
DEVICE=<serial> python3 -m pytest tests/test_00_baseline.py -v
|
|
368
|
+
```
|
|
369
|
+
|
|
370
|
+
Get your device serial from `adb devices`.
|
|
371
|
+
|
|
372
|
+
---
|
|
373
|
+
|
|
374
|
+
## Database Migrations
|
|
375
|
+
|
|
376
|
+
The project uses Alembic for schema migrations:
|
|
377
|
+
|
|
378
|
+
```bash
|
|
379
|
+
# Generate a migration after editing a model
|
|
380
|
+
alembic revision --autogenerate -m "add new_field to my_table"
|
|
381
|
+
|
|
382
|
+
# Apply pending migrations
|
|
383
|
+
alembic upgrade head
|
|
384
|
+
|
|
385
|
+
# Rollback one migration
|
|
386
|
+
alembic downgrade -1
|
|
387
|
+
```
|
|
388
|
+
|
|
389
|
+
---
|
|
390
|
+
|
|
391
|
+
## Contributing
|
|
392
|
+
|
|
393
|
+
The ghost gets stronger with every skill. See [CONTRIBUTING.md](CONTRIBUTING.md) for:
|
|
394
|
+
|
|
395
|
+
- Adding skills for new apps (highest impact)
|
|
396
|
+
- Writing actions and workflows
|
|
397
|
+
- Backend architecture and code style
|
|
398
|
+
- PR process
|
|
399
|
+
|
|
400
|
+
---
|
|
401
|
+
|
|
402
|
+
## License
|
|
403
|
+
|
|
404
|
+
[MIT](LICENSE) — The ghost is free. The ghost is open source. The ghost is yours.
|