esp32-iphone-agent README

The project's README from github.com/onehumanbeing/esp32-iphone-agent. As one markdown file: README.md.

ESP32 iPhone Agent

Let an AI model use a real iPhone — with a $7 ESP32. No Mac, no developer account, no jailbreak.

English · 简体中文

Demo video and updates: X @iamhenryyuan · YouTube demo

CI License: MIT Python Board

Example 1: the web UI after drawing a smiley face in Whiteboard, with the live screen, live log, plan and step screenshots

Example 1 — draw on a canvas. "Open Whiteboard and draw a smiley face": the agent searches for the app, opens it and draws the face with continuous strokes. Every step's screenshot, with its tap or stroke drawn on top, stays on the step wall.

Example 2: an iPhone with a XIAO ESP32S3 plugged in, setting an alarm that repeats every day, next to the web UI

Example 2 — set an alarm. "Set an alarm for 7:00 AM that repeats every day, then save it": the agent opens Clock, types 0700 into the time wheel, ticks the days under Repeat several taps at a time, and saves. Left: the real iPhone with the ESP32 plugged in; right: the web UI.

The agent sees the phone through AirPlay screen mirroring and touches it through a tiny ESP32-S3 board that plugs into the phone's USB port as a mouse and keyboard. Any OpenAI-compatible vision model can be the brain — a cloud API, or a model you run yourself.

Why

Most iPhone automation drives the phone through XCTest / WebDriverAgent. That needs a Mac, Xcode, a signed helper app and an Apple developer account (a free account's signature expires every 7 days). This project uses the same paths a person uses — the screen and a pointer — so the phone needs nothing installed.

ESP32 iPhone Agent XCTest / WebDriverAgent tools
Apple developer account Not needed Needed (to sign the runner)
Xcode Not needed Needed
Computer Mac or Linux Mac
App installed on the phone None Test runner app
Jailbreak Not needed Not needed
Extra hardware ESP32-S3 board (~$7) USB cable
Works in any app, incl. games Yes (it only sees pixels) Mostly (depends on the accessibility tree)

How it works

Hardware

Part Notes
ESP32-S3 board Tested with a Seeed Studio XIAO ESP32S3, plain version without pre-soldered headers (not the Sense camera version, not the Plus). About $7 from Seeed, or about ¥40-50 on Taobao in China (search "XIAO ESP32S3"). Any ESP32-S3 board whose USB-C port is wired to the S3's native USB works.
iPhone USB-C models plug in directly. Lightning models need a Lightning to USB Camera Adapter. The phone powers the board.
Computer macOS or Linux, on the same network as the phone; runs UxPlay and the server.
Vision model Any OpenAI-compatible chat API that accepts images. Running a model locally is optional.

A XIAO ESP32S3 plugged into an iPhone, next to the web UI

Use a USB-C hub with power pass-through if the phone should keep charging while the board is plugged in.

Quick start

Set up with an AI coding agent. Paste this into Claude Code, Codex or a similar agent on the computer the board will connect to:

Clone https://github.com/onehumanbeing/esp32-iphone-agent and follow its README to set it up on this machine:
flash the ESP32-S3 plugged in over USB, install UxPlay and the server, write server/.env for my model API, start
the server and give me the web UI address. Ask me for the Wi-Fi name/password and the model API key.

1. Flash the board

Install arduino-cli and the ESP32 core (3.x), then:

cp hardware/hid_bridge/secrets.example.h hardware/hid_bridge/secrets.h
# edit secrets.h: 2.4 GHz Wi-Fi name/password and the IP address of the computer running the server
hardware/flash.sh            # optional arguments: [serial port] [--debug]

2. Install and start the server

# UxPlay — macOS:
brew install uxplay
# UxPlay — Debian / Ubuntu:
sudo apt install uxplay gstreamer1.0-plugins-good gstreamer1.0-plugins-bad gstreamer1.0-libav

cd server
python3 -m venv .venv && .venv/bin/pip install -e .
cp .env.example .env         # set LLM_BASE_URL / LLM_MODEL / LLM_API_KEY
set -a && . ./.env && set +a && .venv/bin/python -m hidagent

Open http://<computer-ip>:8890 in a browser.

3. Set up the phone (once)

  1. Settings → Accessibility → Touch → AssistiveTouch: turn it on.
  2. Plug the board into the phone. A round pointer appears; the web page shows controller connected.
  3. Control Center → Screen Mirroring → iPhone Agent. The live screen appears in the web page.
  4. In the web page, open Manual controls → Calibrate. The server moves the pointer, finds it on the live screen and calibrates itself in a few seconds; if it cannot see the pointer, it asks you to click exactly on it.

4. Give it a task

Type a goal (for example "Open Settings and go to Wi-Fi") and press Start, or click one of the examples.

Web UI

Configuration

Set in server/.env (see .env.example):

Variable Default Meaning
LLM_BASE_URL http://localhost:8000/v1 OpenAI-compatible endpoint
LLM_MODEL / LLM_API_KEY — Model name and API key
LLM_EXTRA_BODY {} JSON merged into every request (e.g. to turn off a model's thinking mode)
LLM_TOKEN_PARAM auto Token-limit field: max_tokens, max_completion_tokens (newer OpenAI models), or auto to detect
ACTOR_* / PLANNER_* — Per-role overrides of any LLM_* variable
AIRPLAY_NAME iPhone Agent Receiver name in the phone's Screen Mirroring list
PORT / DEVICE_PORT 8890 / 7300 Web UI port / port the board connects to
HIDAGENT_DATA ~/.hidagent Calibration and debug traces
HIDAGENT_DEBUG 0 Debug mode, see below

Local model (optional)

A cloud API is enough. If you want everything on your own hardware, this is the setup the project was developed and timed with:

LLM_BASE_URL=http://<dgx-spark-ip>:8888/v1
LLM_MODEL=Qwen3.8-Flash-Next
LLM_EXTRA_BODY='{"chat_template_kwargs": {"enable_thinking": false}}'

Any other OpenAI-compatible server (vLLM, SGLang, llama.cpp, Ollama, …) with a vision model works the same way.

Debug mode

Set HIDAGENT_DEBUG=1 to log every board command with its latency and to save one folder per agent run:

~/.hidagent/traces/20261012-005207/
├── steps.jsonl   # every model call (prompt, raw reply, latency) and every action
├── 002.jpg       # the screenshot each model call saw
└── ...

hardware/flash.sh --debug builds firmware that echoes each command and its duration over USB serial.

Board protocol

The board holds no logic. On connecting it sends hello <last reset reason> <uptime ms>; then the server sends one command per line over TCP and the board answers ok or err <reason>.

Command Effect
ping Health check
home Push the pointer into the top-left corner (a known position)
move <dx> <dy> Relative pointer move, at a constant pace so iOS pointer acceleration stays predictable
press / release / click Left button down / up / both
scroll <v> <h> Scroll wheel
type <text> Type ASCII text
key <combo> Press keys, e.g. enter, cmd+h, cmd+space

If the Wi-Fi link drops, the board releases all buttons and reconnects on its own. While the phone is locked, its USB port sleeps: the board then tries to wake it and otherwise answers err phone usb asleep instead of waiting. A watchdog restarts the board if it ever stops responding.

Project layout

hardware/   ESP32-S3 firmware (Arduino) and flash script
server/     agent, web UI, screen capture and board link (Python, FastAPI)
            serve/: optional minimal server to host a Hugging Face vision model yourself

Roadmap

Limitations

Responsible use

Only automate devices and accounts you own or are allowed to use, and respect the terms of the apps involved. The agent acts with your hands: watch it, and keep the emergency stop within reach.

Contributing

Issues and pull requests are welcome. Run the checks before sending a change:

cd server && pip install -e ".[dev]" && ruff check . && pytest

Other ways people drive an iPhone with code or AI, and how this project differs. Corrections welcome.

Project Approach Needs on the phone / host Difference from this project
VersaiOS UxPlay mirroring + ESP32-S3 Bluetooth mouse + vision model ESP32 tethered to a computer over USB serial; desktop GUI, mainly Windows Closest in spirit. One tap per instruction, no planning step or before/after screen check
ja1chen/actell Agent app on the iPhone, screenshots and taps via Apple's CoreDevice debug channel Developer Mode, pairing + Developer Disk Image, Xcode self-signing This project needs no Developer Mode, no app on the phone and no signing
AidenAI-IO/aiden-firmware Dedicated board: HDMI capture + USB keyboard/mouse + multimodal model HDMI capture chip and dock; mainly Android Uses AirPlay instead of HDMI capture, so no capture hardware
yoyicue/glassbox PicoKVM HDMI capture + USB HID, observe/decide/act/verify loop macOS controller and PicoKVM Runs on Linux with a single ESP32
boboabw/phone-agent ESP32-S3 Bluetooth HID + AssistiveTouch, agent runs as an iPhone app Mac + Xcode to build and sign the app Nothing to install on the phone
dovydaskel/Iphone-control-for-social-media ESP32 Bluetooth mouse with OpenCV pointer correction, scripted posting Mac Similar closed-loop pointer idea; this project adds a vision-model planner/executor
VKCOM/devicehub ESP32 Bluetooth mouse for iOS device farms Farm infrastructure Device-farm tooling, no AI agent
NolanCotter/AirBridge / gbulog/pcairplay UxPlay on Linux + the PC's own Bluetooth as keyboard/mouse Linux PC with Bluetooth Manual remote control, no AI

Other routes: WebDriverAgent/XCUITest-based tools such as mobile-mcp and Midscene need a Mac and code signing; tools built on macOS iPhone Mirroring need a Mac.

Acknowledgements

UxPlay (AirPlay receiver) · Arduino ESP32 core and TinyUSB (USB HID) · FastAPI

License

MIT

esp32-iphone-agent (onehumanbeing/esp32-iphone-agent)

Searching Database…

这是什么?这个项目能让 AI 视觉模型控制一台真实的 iPhone:用 AirPlay 屏幕镜像当它的“眼睛”,用一块价值 7 美元的 ESP32-S3 开发板充当 USB 鼠标和键盘,作为它的“手”。整个过程不需要 Mac、Apple 开发者账号,也不需要越狱。
这是一个现成的应用,还是需要我自己组装硬件、自己跑服务器?这是一个需要自己动手的方案:先把固件烧录到 ESP32-S3 开发板上,再在电脑上运行一个 Python/FastAPI 服务器,然后通过网页界面来操控一切;手机上不需要安装任何东西。
我怎么把它跑起来?用 arduino-cli 和 ESP32 核心给 ESP32-S3 烧录固件,启动 Python 服务器,然后在 iPhone 上开启 AssistiveTouch,插上开发板,通过屏幕镜像把画面投到“iPhone Agent”,在网页界面里校准指针,最后输入一个目标就能启动 agent。
我需要哪些硬件和模型权限?你需要一块 Seeed Studio XIAO ESP32S3 开发板(约 7 美元)、一台 iPhone(USB-C 接口,或带转接器的 Lightning 接口)、一台和手机在同一网络下的 macOS 或 Linux 电脑,以及任意一个 OpenAI 兼容的视觉模型——云端或自托管的都行。
哪些情况会不好用?因为 iOS 不会镜像这些画面,agent 看不到密码输入、Apple Pay 和受 DRM 保护的视频;手机锁屏后镜像会中断;键盘输入只支持 ASCII 字符;另外由于坐标是按竖屏计算的,横屏应用目前还不支持。
服务器能在 Windows 上跑吗,还是只支持 Mac 和 Linux?控制端电脑只支持 macOS 或 Linux,Windows 没有被列为受支持的主机。
哪些视觉模型可以充当它的大脑?任何能接收图片的 OpenAI 兼容聊天 API 都可以充当规划和执行的模型,无论是云端模型,还是 vLLM、SGLang、llama.cpp、Ollama 这类自托管模型。
和基于 XCTest/WebDriverAgent 的自动化工具相比,它怎么样?与基于 XCTest 的工具不同,这个项目不需要 Mac、Xcode、签名过的测试运行器应用,也不需要 Apple 开发者账号——它只用屏幕和一个 USB 指针设备,也就是人自己在用的那套接口。
agent 怎么知道一次点击有没有真的生效?每次操作后,服务器会检查屏幕画面有没有变化;漏掉的点击会被发现并重试,如果反复失败,就会让规划模型重新制定计划,而不是一味往下执行。
网页界面里的 Step 墙显示什么?它会把每一步的截图都展示出来,并在上面画出对应的点击或滑动轨迹,还附带模型的推理过程以及思考和执行的耗时,让你能清楚地审查 agent 到底做了什么。
Size
9.3 MB
Stars
3K
Age
6d
Commits · 90 Days