⏳ This skill is pending AI review.

Scores will appear once the review pipeline completes.

version unknown

handsy

@onehumanbeing⭐ 4.6k stars

See and drive a real iPhone through an ESP32 Agent (Handsy) board with the esp32agent CLI or MCP server. Use when asked to look at, tap, swipe, type on, or operate an iPhone, or to test an iOS app on a real device.

Choose how to use this skill

You do not need every option. Choose the path your AI client supports. The stable page stays the same; versioned files are immutable.

1. Native installer

This listing has no registered native installer command. Use the complete package or source fallback below, depending on what your client supports.

Do not guess an installer command or replace an existing version without reviewing the diff.

2. Complete package recommended

Download the ZIP when available. It includes SKILL.md plus the references, security notes and version metadata.

No complete ProSkills package is published for this listing yet.

3. Prompt-only

Copy the prompt above when the agent can read the stable page or when you want to adopt the workflow without installing a skill.

Need only the instruction file?

Download SKILL.md only if your client requires a single file. The complete ZIP is safer for a full installation because it preserves the references and release context.

No path installs or executes anything by itself. Your agent still needs access to the project files. Before updating, compare the installed version and review the diff.

—/10

// RATINGS

⭐GitHub Stars
⭐⭐⭐⭐⭐ 4.6k on GitHubGitHub ↗

Very popular

🟢ProSkills Score
—
📍

Not yet listed on ClawHub or SkillsMP

// README

Building on this project? Keep the LICENSE and credit ESP32 iPhone Agent by Henry Yuan in your README and posts. See NOTICE.

ESP32 iPhone Agent

Your AI can use your iPhone like you do.

It looks at the screen, then taps, swipes and types for you, through a $7 ESP32 board plugged into the phone. Just the phone and the board: no computer, no changes to iOS.

TestFlight Website License: MIT GitHub stars CI iOS Board

English · 简体中文

Demo video and updates: X @iamhenryyuan · YouTube demo · DeepSeek Harness demo · handsy.tech

[!TIP] Try the app now on TestFlight, no Xcode needed. The App Store listing is still in review, so TestFlight is the way to get it today. You still need a flashed board (see Quick start).

[!NOTE] Branches: release-1.0 is the version submitted to TestFlight and App Store review. The latest code is on main.

[!WARNING] Only follow the install steps in this README. Never run commands from issues or comments (for example a "quick install" one-liner such as PowerShell iex(irm ...)); these are not from the maintainers.

The computer is gone. The board is now the AirPlay receiver and the mouse, and the agent runs in an iPhone app on the same phone. The original version (a Mac/Linux computer running UxPlay and a Python server) is kept as tag v0.1.0 and branch legacy. See docs/legacy.md.

"Set an alarm for 8:00 AM that repeats every Monday and Tuesday, then save it": the agent leaves its own app, opens Clock, types the time into the wheel, ticks the days and saves. (Photo from v0.1.0; the task is the same.)

Left: the real phone. Right: what the agent sees through the board's AirPlay mirror. The second shot is the pointer calibration.

Contents

How it works

More detail: how Handsy works.

iPhone ──Screen Mirroring (Wi-Fi)──▶ ESP32-S3: AirPlay receiver ──Wi-Fi TCP :7201──▶ ESP32 Agent app (same iPhone)
   ▲                                    own hotspot, H.264 passthrough              decode → vision model → action
   └──────── USB HID mouse + keyboard ◀──────────── BLE commands ◀──────────────────────┘
  • Eyes — AirPlay to the board. The board opens its own Wi-Fi hotspot and appears in the phone's Screen Mirroring list as ESP32 Agent. It keeps the H.264 stream (no decoding on the board) and forwards it to the app over Wi-Fi (TCP, port 7201). BLE carries commands and status. The phone keeps using cellular data for the model while it is on the board's hotspot.
  • Hands — USB HID. The board is a standard USB mouse and keyboard. With AssistiveTouch on, the mouse moves an on-screen pointer, so a click is a tap and a drag is a swipe.
  • Brain — the app. The app decodes the stream, sends screenshots to any OpenAI-compatible vision model, and runs a planner and an actor: tap, swipe, draw, type, press keys, go home, finish. It runs in the background while it works; the Dynamic Island shows what it is doing.
  • Closing the loop. The pointer is relative, so the app tracks it and re-homes it in a corner; before precise taps it wiggles the pointer, finds it on screen and corrects the miss. After each action it waits for the screen to settle and tells the model whether anything changed. A lost board, hotspot or mirroring link pauses the run and resumes it from the same step.
  • Review. Every run is kept on the phone: replay it step by step with the taps and swipes drawn on top. Export the screenshots, actions and saved annotations from Runs → open a run → ⋯ → Export trace for analysis by another agent. See Export runs for agent review for batch export, USB copying and file details.

Hardware

Supported boards and setup details: hardware guide.

PartNotes
ESP32-S3 boardTested with a Seeed Studio XIAO ESP32S3 (plain version, 8 MB PSRAM; not Sense, not Plus). About $7 (Amazon*). Any ESP32-S3 with native USB on its USB-C port and PSRAM should work.
USB-C cableShort USB-C to USB-C, e.g. Anker 60W, 1 ft, 2-pack*.
iPhoneiOS 18 or later, with cellular data (the Wi-Fi is taken by the board's hotspot). USB-C models plug in directly; Lightning models need a Lightning to USB Camera Adapter. The phone powers the board.
Vision modelAny OpenAI-compatible chat API that accepts images: a cloud API or your own server.
Mac with XcodeOnly to flash the board and build the app once. Not needed at run time. With the TestFlight app, Xcode is not needed for the app.

* Affiliate link. As an Amazon Associate I earn from qualifying purchases.

Quick start

1. Flash the board (plugged into the Mac)

Install arduino-cli, the ESP32 core 3.3.x and NimBLE-Arduino 2.5.x, then:

arduino-cli lib install "[email protected]"
hardware/flash.sh            # optional: [serial port] [--debug]

Always build with flash.sh: it applies the BLE buffer sizes in hardware/hid_bridge/nimble_cfg.h.

No Mac or toolchain? [Install the firmware f

// HOW IT'S BUILT

// FILES

2 files shipped with this skill. Inline text is the catalog copy. The upstream link is the source repository.

  • integrations/dsh/skills/handsy/SKILL.md8.2 KB1d656d8b38b3upstream ↗
    ---
    name: handsy
    description: See and drive a real iPhone through an ESP32 Agent (Handsy) board with the esp32agent CLI or MCP server. Use when asked to look at, tap, swipe, type on, or operate an iPhone, or to test an iOS app on a real device.
    license: MIT-0
    metadata:
      openclaw:
        requires:
          bins: [npx, ffmpeg]
        envOptional: [ESP32AGENT_DEVICE]
        homepage: https://handsy.tech
    ---
    
    # Handsy: drive a real iPhone with esp32agent
    
    An ESP32 Agent board (Handsy) plugs into the iPhone (USB-C models directly, Lightning models through a Lightning to
    USB Camera Adapter) and acts as the phone's USB mouse and keyboard. It also receives the iPhone's AirPlay screen mirroring. Your computer reaches
    the board over Bluetooth with the `esp32agent` command line tool, which is also an MCP server. No jailbreak is
    needed.
    
    iPhone only for now. iPad support is coming soon.
    
    ## Prerequisites
    
    - A Seeed Studio XIAO ESP32S3 board (8 MB flash, 8 MB PSRAM), or a similar ESP32-S3 board with native USB.
    - Board firmware v0.2.2 or later. Install it in Chrome or Edge at https://handsy.tech/install
      (one USB data cable, nothing else to install).
    - On the iPhone:
      - AssistiveTouch on (Settings > Accessibility > Touch > AssistiveTouch), so the mouse pointer shows and taps.
      - Screen Mirroring to the board: join the board's Wi-Fi, then Control Center > Screen Mirroring > ESP32 Agent.
      - The phone unlocked while the agent works.
    - On the computer: Bluetooth, Node.js 18 or later (for `npx`), and `ffmpeg` (needed for screenshots).
    
    ## Install
    
    Nothing to install up front; `npx` fetches the CLI:
    
    ```sh
    npx -y esp32agent version
    ```
    
    Or install it globally with `npm install -g esp32agent` and call `esp32agent` directly. The examples below use
    `npx -y esp32agent`; with a global install, drop the `npx -y`.
    
    MCP server (stdio), if your agent does not already have it from this plugin:
    
    ```sh
    claude mcp add esp32agent -- npx -y esp32agent mcp
    ```
    
    Other MCP clients:
    
    ```json
    { "mcpServers": { "esp32agent": { "command": "npx", "args": ["-y", "esp32agent", "mcp"] } } }
    ```
    
    ## Pair (once per computer)
    
    1. Plug the board into the iPhone. Within 3 minutes run `npx -y esp32agent pair`.
    2. Start Screen Mirroring on the iPhone to ESP32 Agent.
    3. `npx -y esp32agent screenshot` should now save a PNG of the phone's screen.
    4. `npx -y esp32agent calibrate` measures the pointer. It also runs by itself before the earliest tap. It needs
       the pointer visible on screen.
    
    ## MCP tools
    
    | Tool | What it does |
    |---|---|
    | `screenshot` | The screen now, after the last action settled. Other tools take pixel coordinates of this image |
    | `tap` | Tap at `x`, `y`; `count: 2` double-taps |
    | `longpress` | Press and hold at `x`, `y` (`duration_ms`, default 1000) |
    | `swipe` | Swipe from `x1`, `y1` to `x2`, `y2` |
    | `type_text` | Type into the focused field (ASCII; Chinese is typed as pinyin) |
    | `press_key` | `enter`, `esc`, `tab`, `backspace`, `space`, arrows, `cmd+a`, `shift+tab` ... |
    | `press_button` | `HOME` only (go to the Home Screen) |
    | `device_info` | Board status: mirroring (`ap`), video frozen (`fz`), app busy (`busy`), `usb`, `ble` |
    | `history` | `action: list` (recent runs) or `show` (one run's steps with their screenshots) |
    | `intent_list`, `intent_show`, `intent_save` | Saved tasks: list, show one, save what worked |
    
    Every tool takes an optional `device` (board id) when more than one board is nearby.
    
    ## CLI commands
    
    Every command prints JSON: `{"status":"ok","data":...}` or `{"status":"error","error":"..."}` (exit code 1).
    
    | Command | What it does |
    |---|---|
    | `devices` | Boards nearby (`id`, `paired`, `connected`) |
    | `pair`, `unpair` | Pair this computer with the board; forget it here |
    | `screenshot [--format png\|jpeg] [--quality N] [--scale F] [--max-size N] [--output PATH\|DIR/\|-]` | Save the screen; prints `filePath` |
    | `io tap X,Y [--aim] [--count N]` | Tap; `--aim` finds the pointer and corrects before tapping |
    | `io longpress X,Y [--duration MS]` | Press and hold |
    | `io swipe X1,Y1,X2,Y2` | Swipe |
    | `io text 'TEXT'` | Type ASCII text |
    | `io keys COMBO` | Press a key or combo |
    | `io button HOME` | Home Screen |
    | `device info` | Board status |
    | `calibrate` | Measure the pointer |
    | `history list`, `history show RUN\|latest`, `history new` | What was done on the phone; start a new run |
    | `intent list`, `intent show NAME`, `intent save ...`, `intent delete NAME` | Saved tasks |
    | `intent export NAME [--screenshots] [--output FILE]`, `intent import FILE` | Move saved tasks to and from the iOS app |
    | `upgrade [--check]`, `version` | Update the CLI; print its version |
    | `mcp` | Run the MCP server on stdio |
    
    With several boards nearby pass `--device <id>` or set `ESP32AGENT_DEVICE`.
    
    ## The see-act loop
    
    1. Take a screenshot (`screenshot` tool, or `esp32agent screenshot` and read the PNG at `filePath`).
       It waits until the screen has settled after your last action.
    2. Decide one action from what you see.
    3. Do that one action, with coordinates in pixels of that full-size screenshot. If you used `--scale` or
       `--max-size`, convert the coordinates back to full size.
    4. Take another screenshot and check the result before the next step. Never chain several taps blind.
    
    Tips:
    - To scroll a list, swipe up from the lower middle to the upper middle of the screen.
    - To open an app: press HOME, swipe down in the middle of the Home Screen, type the app name, press `enter`.
    - If a tap missed, retry with `io tap X,Y --aim`.
    - Tap a text field so it has focus before typing. `cmd+a` then `backspace` clears it.
    - The board is a hardware keyboard, so iOS may hide the on-screen keyboard; the field still takes the keys.
    - Chinese text is typed as pinyin (`io text '拿铁'` types `natie`). With the Chinese pinyin keyboard active, press
      `space` to accept the top candidate, or screenshot and tap the right one.
    
    ## Save what worked
    
    After a task succeeds, save it so the next run is faster:
    1. `history show latest` (MCP `history`, action `show`) lists the run's numbered steps in 0-1000 screen units.
    2. Pick the steps that did the job, skipping misses and retries.
    3. `intent save --name 'Alarm 7:00' --prompt 'Set an alarm for 7:00 AM every day' --hint 'Type the time' --from-run RUN --steps 2,3,5`
       (MCP `intent_save`). Keep the prompt short and use at most 6 hints.
    
    To reuse one, `intent show NAME`, convert its 0-1000 coordinates to pixels (x * width / 1000,
    y * height / 1000), and check each screen against the step's reference screen. If the screen looks different,
    drop the recorded steps and continue with the normal loop.
    
    ## Safety
    
    You are using a real phone with the owner's accounts, money and contacts.
    - Ask the user to confirm before anything that spends money, sends a message, email or post, calls someone,
      deletes data, changes passwords or security settings, or accepts terms.
    - Do not read or copy private content (messages, photos, codes, passwords) beyond what the task needs.
    - If a screen asks for a password, passcode, Face ID or a one-time code, stop and hand it to the user.
    - Stop and ask when the screen is not what you expected.
    
    ## Troubleshooting
    
    | Error or symptom | What to do |
    |---|---|
    | `not paired` | Replug the board into the iPhone and run `pair` within 3 minutes |
    | `screen mirroring is off` | Ask the user to start Screen Mirroring to ESP32 Agent |
    | `video frozen` | Ask the user to stop and restart Screen Mirroring |
    | `phone usb asleep` | The phone is locked; ask the user to unlock it |
    | `busy: the app is using the phone` | The ESP32 Agent iOS app is driving the phone. Wait and retry later |
    | `no cli service (firmware too old?)` | Update the board firmware to v0.2.2 or later at https://handsy.tech/install |
    | `not supported on ESP32 Agent` | There is no app list, UI tree or file access; work from screenshots |
    | Taps land off target | Make sure AssistiveTouch is on and the pointer is visible, run `calibrate`, or use `io tap --aim` |
    | Screenshot fails | Check that `ffmpeg` is installed and Screen Mirroring is on |
    
    Limits: screenshots can be up to about a second behind and animations look choppy. Typing is ASCII only, one key
    per character. HOME is the only button: no volume or power buttons, and no installing or launching apps directly.
    
    Help: [email protected] · https://handsy.tech
    
  • README.mdupstream ↗

    Contents are not inlined in the catalog. Open the upstream file.

Plain-text copy, no login: /skill-bundles/onehumanbeing-esp32-iphone-agent-integrations-dsh-skills-handsy.md

// REPO STATS

4.6k stars