Metadata-Version: 2.4
Name: mobilerun-core-cli
Version: 0.1.0
Summary: Slim async Portal client + Android device driver, extracted from mobilerun.
Project-URL: Homepage, https://github.com/droidrun/mobilerun-core-cli
Project-URL: Repository, https://github.com/droidrun/mobilerun-core-cli
Project-URL: Bug Tracker, https://github.com/droidrun/mobilerun-core-cli/issues
Project-URL: Upstream, https://github.com/droidrun/mobilerun
Author: droidrun
License: MIT
License-File: LICENSE
Classifier: Development Status :: 3 - Alpha
Classifier: Framework :: AsyncIO
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Classifier: Topic :: System :: Hardware
Requires-Python: <3.14,>=3.11
Requires-Dist: async-adbutils
Requires-Dist: httpx>=0.27.0
Requires-Dist: requests>=2.31
Requires-Dist: rich>=14.1.0
Description-Content-Type: text/markdown

<picture align="center">
  <source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/droidrun/mobilerun/main/static/mobilerun-dark.png">
  <source media="(prefers-color-scheme: light)" srcset="https://raw.githubusercontent.com/droidrun/mobilerun/main/static/mobilerun.png">
  <img src="https://raw.githubusercontent.com/droidrun/mobilerun/main/static/mobilerun.png" width="full">
</picture>

<p align="center">
  <strong>mobilerun-core-cli is the slim async Portal + Android device driver core of <a href="https://github.com/droidrun/mobilerun">mobilerun</a>.</strong><br>
  No CLI, no agent, no LLM providers — just enough to drive a real Android device through the Mobilerun Portal app over ADB. Intended as an embedding library for higher-level tools.
</p>

<div align="center">

<a href="https://docs.mobilerun.ai">📕 Documentation</a>
·
<a href="https://github.com/droidrun/mobilerun">🧠 mobilerun framework</a>
·
<a href="https://pypi.org/project/mobilerun-core-cli/">📦 PyPI</a>

[![PyPI version](https://img.shields.io/pypi/v/mobilerun-core-cli?style=flat-square)](https://pypi.org/project/mobilerun-core-cli/)
[![Python](https://img.shields.io/pypi/pyversions/mobilerun-core-cli?style=flat-square)](https://pypi.org/project/mobilerun-core-cli/)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg?style=flat-square)](./LICENSE)
[![Discord](https://img.shields.io/discord/1360219330318696488?color=white&label=Discord&logo=discord&logoColor=white&style=flat-square)](https://discord.gg/ZZbKEZZkwK)

</div>

---

- 📱 Drive a real Android device — `tap`, `swipe`, `type`, `screenshot`, `get_ui_tree`, `start_app`, `install_app`, …
- ⚡ TCP-with-content-provider fallback — fast HTTP path over `adb forward`, transparent fallback to content-provider RPC.
- 🛠 Portal lifecycle — download, install, accessibility enablement, auto-upgrade.
- 🪶 Slim — four files, four runtime deps (`async_adbutils`, `httpx`, `requests`, `rich`).
- 🔌 Embeddable — designed to be wrapped by sync facades (e.g. `mobilerun-core`) or used directly.
- 🤝 In sync with upstream — verbatim slice of [`droidrun/mobilerun`](https://github.com/droidrun/mobilerun); behaviour and API track upstream.

## 📦 Installation

> **Note:** Python `>=3.11,<3.14`. Requires [ADB](https://developer.android.com/studio/releases/platform-tools) on `PATH` and a device with USB debugging enabled.

```bash
uv pip install mobilerun-core-cli
```

## 🚀 Quick usage

```python
import asyncio
from async_adbutils import adb
from mobilerun_core_cli import AndroidDriver, ensure_portal_ready


async def main():
    # 1. Make sure Portal is installed + accessibility is on.
    device = await adb.device()
    await ensure_portal_ready(device)

    # 2. Drive the device.
    driver = AndroidDriver(serial=device.serial, use_tcp=True)
    await driver.connect()

    await driver.tap(540, 1200)
    await driver.swipe(540, 1600, 540, 400, duration_ms=300)
    await driver.input_text("hello", clear=True)
    png_bytes = await driver.screenshot()
    tree = await driver.get_ui_tree()


asyncio.run(main())
```

## 🧱 Layout

```
mobilerun_core_cli/
├── __init__.py            Re-exports the public surface
├── portal.py              Portal APK lifecycle + content-provider helpers
├── driver/
│   ├── base.py            DeviceDriver ABC, DeviceDisconnectedError
│   └── android.py         AndroidDriver — ADB-backed concrete driver
└── transport/
    └── portal_client.py   PortalClient — TCP-with-content-provider fallback
```

## 📚 Public API

Re-exported from `mobilerun_core_cli`:

| Symbol | What it is |
|---|---|
| `AndroidDriver` | ADB+Portal device driver. Async methods: `tap`, `swipe`, `input_text`, `press_button`, `start_app`, `install_app`, `screenshot`, `get_ui_tree`, `get_apps`, `list_packages`, `get_date`. |
| `DeviceDriver` | Abstract base for drivers. `supported: set[str]` declares which verbs a subclass implements. |
| `DeviceDisconnectedError` | Raised when the device drops mid-call. |
| `PortalClient` | HTTP-or-content-provider client for the on-device Portal. Used internally by `AndroidDriver`; can be constructed directly for low-level access. |
| `setup_portal(device)` | Download + install + enable the Portal APK on a device. |
| `ensure_portal_ready(device)` | Idempotent: install/upgrade Portal and enable accessibility if needed. |
| `setup_keyboard(device)` | Switch the device to the Mobilerun IME. |
| `ping_portal(device)` | Verify Portal is installed and reachable. |
| `PORTAL_PACKAGE_NAME`, `A11Y_SERVICE_NAME` | Portal identifiers. |
| `portal_content_uri(pkg, path)` | Build `content://<pkg>/<path>` URIs. |
| `portal_a11y_service(pkg)`, `portal_ime_id(pkg)` | Accessibility service / IME component names. |

`AndroidDriver` accepts:

- `serial: str | None` — ADB serial; `None` picks the only connected device.
- `use_tcp: bool = False` — when `True`, the underlying `PortalClient` port-forwards Portal's HTTP server (`localhost:N → device:8080`) and uses it instead of the content provider. Faster but requires a working forward; falls back transparently.

## 🪵 Logging

All output goes through the `"mobilerun_core_cli"` logger. Configure it yourself; the package attaches no handlers.

```python
import logging
logging.basicConfig(level=logging.INFO)
logging.getLogger("mobilerun_core_cli").setLevel(logging.DEBUG)
```

## 🔗 Relationship to upstream `mobilerun`

This package is a verbatim slice of the upstream framework's Android driver + Portal modules, with imports rewritten under `mobilerun_core_cli` and loggers renamed. It tracks the upstream API for those four files; new features (iOS driver, recording driver, cloud driver, agent/CLI) stay upstream.

Use `mobilerun-core-cli` when you only need to drive a real Android device and want to keep the dependency footprint small.
Use [`mobilerun`](https://github.com/droidrun/mobilerun) when you want the full LLM-agent experience, CLI/TUI, and multi-platform support out of the box.

## 📄 License

MIT — see [`LICENSE`](./LICENSE).
