Slim async local device drivers for Android Portal and iOS Portal, extracted from mobilerun.
Project description
mobilerun-core-local is the slim async local-driver core of mobilerun.
No CLI, no agent, no LLM providers โ just local Android/iOS drivers for higher-level tools such as mobilerun-core.
- ๐ฑ Drive local devices โ Android over ADB with optional Portal, Android Portal HTTP-only, or iOS Portal HTTP.
- โก TCP-with-content-provider fallback โ fast Android HTTP path over
adb forward, transparent fallback to content-provider RPC. - ๐ HTTP-only drivers โ connect to already-running Android/iOS portals without taking over setup.
- ๐ Portal lifecycle โ download, install, accessibility enablement, auto-upgrade.
- ๐ชถ Slim โ a small async driver package with 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; behaviour and API track upstream.
๐ฆ Installation
Note: Python
>=3.11,<3.14. The Android ADB driver requires ADB onPATHand a device with USB debugging enabled. HTTP-only drivers require an already-running portal URL.
uv pip install mobilerun-core-local
๐ Quick usage
import asyncio
from async_adbutils import adb
from mobilerun_core_local import AndroidDriver
from mobilerun_core_local.driver.android import ensure_portal_ready
async def main():
# 1. Optional: make sure Portal is installed + accessibility is on for
# Portal-enhanced state/text paths. AndroidDriver still works over ADB
# without this step.
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())
HTTP-only Android:
import asyncio
from mobilerun_core_local import AndroidPortalHttpDriver
async def main():
driver = AndroidPortalHttpDriver(
url="http://127.0.0.1:18080",
token="...",
)
await driver.connect()
await driver.tap(540, 1200)
asyncio.run(main())
iOS Portal:
import asyncio
from mobilerun_core_local import IOSPortalDriver
async def main():
driver = IOSPortalDriver("http://127.0.0.1:6643")
await driver.connect()
await driver.start_app("com.apple.Preferences")
asyncio.run(main())
๐งฑ Layout
Platform-specific code is namespaced under driver/<platform>/ and
transport/<platform>/. Adding a new backend (e.g. iOS over USB, a new
Android transport) does not pollute the package root.
mobilerun_core_local/
โโโ __init__.py Re-exports the public driver surface
โโโ driver/
โ โโโ base.py DeviceDriver ABC, DeviceDisconnectedError
โ โโโ android/
โ โ โโโ adb.py AndroidDriver โ ADB-backed driver
โ โ โโโ http.py AndroidPortalHttpDriver โ HTTP-only driver
โ โ โโโ portal.py Portal APK lifecycle + content-provider helpers
โ โโโ ios/
โ โโโ http.py IOSPortalDriver โ ios-portal HTTP driver
โโโ transport/
โโโ android/
โโโ portal_client.py PortalClient โ TCP-with-content-provider fallback
๐ Public API
Re-exported from mobilerun_core_local:
| Symbol | What it is |
|---|---|
AndroidDriver |
ADB-first Android driver with optional Portal enhancement. Async methods: tap, swipe, input_text, press_button, start_app, install_app, screenshot, get_ui_tree, get_apps, list_packages, get_date. |
AndroidPortalHttpDriver |
HTTP-only Android Portal driver. Requires url and bearer token; does not use ADB at runtime. |
IOSPortalDriver / IOSDriver |
iOS Portal HTTP driver. Requires an already-running ios-portal URL. |
DeviceDriver |
Abstract base for drivers. supported: set[str] declares which verbs a subclass implements. |
DeviceDisconnectedError |
Raised when the device drops mid-call. |
validate_android_portal_url(url) / validate_ios_portal_url(url) |
Normalize + sanity-check portal URLs. |
discover_ios_portal(...) |
Scan localhost for a reachable ios-portal HTTP endpoint. |
Android Portal helpers live under mobilerun_core_local.driver.android (not at
the package root, since they're Android-specific):
| Symbol | What it is |
|---|---|
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. |
PortalClient (the TCP-with-content-provider transport) lives at
mobilerun_core_local.transport.android.PortalClient โ used internally by
AndroidDriver, exposed for low-level access.
AndroidDriver accepts:
serial: str | Noneโ ADB serial;Nonepicks the only connected device.use_tcp: bool = Falseโ whenTrue, the underlyingPortalClientport-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_local" logger. Configure it yourself; the package attaches no handlers.
import logging
logging.basicConfig(level=logging.INFO)
logging.getLogger("mobilerun_core_local").setLevel(logging.DEBUG)
๐ Relationship to upstream mobilerun
This package owns local execution drivers. The full framework imports these drivers for CLI/agent flows; mobilerun-core wraps them behind a sync, backend-neutral API.
Use mobilerun-core-local when you need async local drivers directly.
Use mobilerun when you want the full LLM-agent experience, CLI/TUI, and multi-platform support out of the box.
๐ License
MIT โ see LICENSE.
Project details
Release history Release notifications | RSS feed
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 mobilerun_core_local-0.3.1.tar.gz.
File metadata
- Download URL: mobilerun_core_local-0.3.1.tar.gz
- Upload date:
- Size: 49.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
9e23ca8c98de1651ffc1de2990ff6bf658379839d9309f6b5882f5eb345eb70d
|
|
| MD5 |
863338bf74abf408cfaaed59c3d94ac1
|
|
| BLAKE2b-256 |
e28b1a2d0585b3675dec10a15f84f37938c53ecceff984122baa54d7861e4606
|
Provenance
The following attestation bundles were made for mobilerun_core_local-0.3.1.tar.gz:
Publisher:
publish.yml on droidrun/mobilerun-core-local
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
mobilerun_core_local-0.3.1.tar.gz -
Subject digest:
9e23ca8c98de1651ffc1de2990ff6bf658379839d9309f6b5882f5eb345eb70d - Sigstore transparency entry: 1929033607
- Sigstore integration time:
-
Permalink:
droidrun/mobilerun-core-local@3ec73658d6913efda28d1386955918d877a8e4bd -
Branch / Tag:
refs/tags/v0.3.1 - Owner: https://github.com/droidrun
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@3ec73658d6913efda28d1386955918d877a8e4bd -
Trigger Event:
push
-
Statement type:
File details
Details for the file mobilerun_core_local-0.3.1-py3-none-any.whl.
File metadata
- Download URL: mobilerun_core_local-0.3.1-py3-none-any.whl
- Upload date:
- Size: 35.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
5be484a5d2ebd97bca782a8685d3e3515e151e556d29eeb71439b2af8c9b2a02
|
|
| MD5 |
fd4c37241cba15710a49ada6f5fa39df
|
|
| BLAKE2b-256 |
59c87844b86724598a44dc9f74d32236808b7c2f99e626ca0dbeaddd885506b4
|
Provenance
The following attestation bundles were made for mobilerun_core_local-0.3.1-py3-none-any.whl:
Publisher:
publish.yml on droidrun/mobilerun-core-local
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
mobilerun_core_local-0.3.1-py3-none-any.whl -
Subject digest:
5be484a5d2ebd97bca782a8685d3e3515e151e556d29eeb71439b2af8c9b2a02 - Sigstore transparency entry: 1929034071
- Sigstore integration time:
-
Permalink:
droidrun/mobilerun-core-local@3ec73658d6913efda28d1386955918d877a8e4bd -
Branch / Tag:
refs/tags/v0.3.1 - Owner: https://github.com/droidrun
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@3ec73658d6913efda28d1386955918d877a8e4bd -
Trigger Event:
push
-
Statement type: