Phone Harness connects coding agents to real iPhone or Android devices so they can see screens, tap, type, and read results. It is for automating tasks on phones through iPhone Mirroring or Android’s adb connection. The catalogue skill provides the agent’s day-to-day instructions for using the harness.
Getting it into your agent
One page per mod, every tool's command on it. A separate URL per tool would split the same page into five that compete with each other.
npx skills add ShawnPana/phone-harness --skill phone-harnessgit clone --depth 1 https://github.com/ShawnPana/phone-harnessWrote this? Show the measurements
A badge with what this costs and how it scanned, read live from this page, so it follows the numbers instead of freezing them. Markdown for a README, HTML for a documentation site or a project page.
[](https://agentmods.dev/skills/shawnpana/phone-harness/phone-harness)<a href="https://agentmods.dev/skills/shawnpana/phone-harness/phone-harness"><img src="https://agentmods.dev/badge/skills/shawnpana/phone-harness/phone-harness/github.svg" alt="Measured on agentmods" height="20"></a>Or the 80×15 button, for a site that already has a row of RSS and ATOM ones. Only the verdict fits; the numbers stay here.
<a href="https://agentmods.dev/skills/shawnpana/phone-harness/phone-harness"><img src="https://agentmods.dev/badge/skills/shawnpana/phone-harness/phone-harness.svg" alt="Reviewed on agentmods" width="80" height="20"></a>What it costs to keep this loaded
Counted locally with the o200k_base tokenizer, which is exact for GPT models; Claude uses its own tokenizer and its counts differ. Treat this as one consistent yardstick across the catalogue rather than a bill. Prices are per million input tokens.
| Model | Per session | Once invoked |
|---|---|---|
| Fable 5.1 | $0.00053 | $0.09069 |
| Opus 5.5 | $0.00021 | $0.03628 |
| Sonnet 5.5 | $0.00011 | $0.01814 |
| Haiku 4.5 | $0.00005 | $0.00907 |
Grade A, and why
phone-harness scanned grade A with 0 findings against 26 rules in 11 categories — prompt injection, anti-refusal, data exfiltration, privilege escalation, supply chain, agent snooping, system-prompt leakage, SSRF and excessive agency — measured 10d ago.
A static scan of the body, not an audit. Every finding is printed with the line that produced it so you can judge whether it matters here. A mod is markdown that instructs an agent; that is exactly why what it instructs is worth reading.
Nothing flagged
None of the 26 patterns this scan looks for appear in this file: no shell pipes, no recursive deletes, no credential paths, no hidden text, no instruction-override or anti-refusal phrasing, no agent-config snooping. That is not a guarantee, it is the absence of the things that are checkable.
How it starts
The opening of the file, as written. The whole thing — 547 lines — stays where its author put it; the contents beside it link to each section on GitHub.
phone-harness
The main helpers are listed in Helpers.
Direct control of a phone from Python scripts. The same helpers drive every kind of phone below; what differs is how each one sees and touches the screen, and that is what the per-phone sections below are for. Read Which phone, the shared Working method, and then only the section for the phone in front of you.
Setup
Check what this machine can do (OS, shell, install rights, network,
attached phones; phone-harness doctor does the phone part), tell the user
in a sentence or two which phone you can drive with what is here, and use
the best one that actually runs. A phone on the desk wins; the cloud needs
no hardware and is always the fallback.
| Mode | Needs |
|---|---|
| Personal iPhone | macOS 15+, iPhone Mirroring paired to an iOS 18+ iPhone, Accessibility + Screen Recording for the app that runs Python |
| Android on the desk | macOS, Linux or Windows; adb; USB debugging (or Wireless debugging, Android 11+) |
| Cloud iPhone | HTTPS to phone-harness.com hosts; a signed-in account. No adb, any OS |
| Cloud Android | the cloud iPhone list, plus adb and outbound TCP to the phone's adb port |
| No install possible | HTTPS and an HTTP client: the API directly |
- If something is missing, name it and the one step the user can take.
- Ask the user only to approve sign-in and to pick a phone.
- Detail: iPhone, Android, Cloud, API.
Helpers
ensure_device()- Screen bounds once the device is usable, or raises with what the user has to do.screen(min_confidence=0.3)- Visible text as{text, confidence, source, x, y, w, h}boxes. On Android the boxes come from the accessibility tree; on iPhone Mirroring they come from recognizing text.screenshot(path=None)- Capture the screen to a PNG, print its path, and return it.find_text(query, exact=False)- Visible text boxes matchingquery.tap_text(query, index=0, exact=False)- Tap the center of visible text matchingquery.tap(x, y)- Tap one point.long_press(x, y, duration=0.8)- Press and hold a point.type_text(text, delay=0.03, keystrokes=False)- Type into the focused field.press(combo)- Press a key, such aspress("enter").open_app(name)- Launch an app and return the app id that launched.open_url(url)- Open an https link in the phone's browser, whole. Cloud phones only for now.push_file(path)- Send a file to the phone; it opens in the phone's browser under its own name. Cloud phones only for now.swipe(direction, distance=0.4, at=None)- Flick.directionis finger motion:"up","down","left", or"right".scroll(direction="down", amount=0.3, at=None)- Scroll.directionis the content to reveal:"down","up","left", or"right".scroll_screen(direction="down", amount=0.6, settle=2.5, moved_thresh=None, at=None)- One scroll, then the text on screen before and after.scroll_until(done, direction="down", amount=0.6, max_scrolls=60, settle=2.5, at=None)- Scroll untildone(boxes)is truthy or the screen stops changing.scroll_collect(extract=None, key=None, direction="down", amount=0.6, max_scrolls=400, end_after=3, settle=2.5, on_progress=None, at=None)- Scroll a list and return{items, stop, scrolls}.home()- Go to the Home Screen.back()- System Back, where the phone has one.app_switcher()- Open the app switcher.wait_stable(timeout=6.0, interval=0.5, settle=2)- Wait until the screen stops changing.wait_for_text(query, timeout=10.0, exact=False, interval=0.5)- Poll untilqueryis visible; return its box, or None.wait_for_app(app_id, timeout=10.0, interval=0.3)- Poll untilapp_idis the foreground app.ui()- The accessibility tree, where the device has one.tap_ui(query, index=0, exact=False, clickable_only=False)- Tap an element in the accessibility tree.current_app()- Foreground app id, where the device exposes one.list_apps(include_system=False)- Installed app ids.screen_info()-{window, frontmost, img_px}: bounds, focus, and capture size.find_window()- Screen bounds{x, y, w, h, id}, or None if there is no device.image_point(x, y, image_size=None)- Convert a screenshot pixel to a screen point.tap_image_point(x, y, image_size=None)- Tap a point taken from a screenshot.connection_state()- Backend state string;"ready"means usable.shell(cmd, binary=False, timeout=60)- Run a shell command on the phone, where the device has a shell.
What ships with it
2 files beside SKILL.md in the same directory: the scripts, references and assets a skill reads on demand. Not counted in the per-session cost; read them before you install if any of them is executable.
What this file has done since we first saw it
Hashed on every crawl. A supply-chain change to an agent config is a question of when, not whether, so the history is kept rather than the latest state alone.
- 10d ago Changed · -14 lines b7c77fefd6da
- 11d ago Changed · +23 lines 0838c6b1a29c
- 15d ago Changed · +42 lines 45f52b2fbeeb
- 16d ago Changed · +97 lines e8d9b3533c0e
- 17d ago Changed · +127 lines · +7 tokens per session 7e1bf99b3e0d
- 1mo ago Changed · +30 lines · +6 tokens per session a7e6ead0348a
- 1mo ago Changed · +9 lines 174272f6b524
- 1mo ago First seen · 233 lines · 40 tokens per session scan A 3670a6cc5a6a
phone-harness is a skill published in the GitHub repository ShawnPana/phone-harness (3,974 stars, last pushed today), licensed MIT. It adds 53 tokens to every session and 9,069 once invoked, about $0.0002 per session on Opus 5.5. A static security scan graded it A with 0 findings. No closer match exists in the catalogue, so it is treated as the original; first seen 2026-08-30.
Other skills, from other repositories
agent-browser
Browser automation via Chrome/Chromium CDP — open, snapshot, click, screenshot. For testing web apps, mobile layouts, and automated interactions without Playwright/Puppeteer.
serve-sim
Control and stream a running iOS, iPad, or Apple Watch Simulator with npx serve-sim. Use for simulator preview, taps, gestures, hardware buttons, rotation, camera injection, permissions, accessibility, and CoreAnimation debug.
mobile-automation
Control Android and iOS devices, emulators and simulators — launch apps, tap, swipe, type, take screenshots, read the accessibility tree. Use when a task involves a mobile device or app, mobile UI testing, or reproducing a bug on a phone.
baguette
Drive and inspect iOS simulators with the baguette CLI: taps, swipes, buttons, typing, screenshots, the accessibility tree, logs, and the conditions an app runs under (location, network, appearance, push, UserDefaults), without opening Xcode. Use when an agent must act on or verify a running simulator — a UI flow…
omh-apple-design
This is an OMH apple-design workflow skill, projected for Agent Skills hosts (Claude Code, Codex, Cursor, opencode, OpenClaw, pi).
omh-mobile-release
This is an OMH mobile-release workflow skill, projected for Agent Skills hosts (Claude Code, Codex, Cursor, opencode, OpenClaw, pi).