Agent-readable docs index: /llms.txt. Full docs in one file: /llms-full.txt. Download /docs.zip to grep all markdown files locally.

ghosthand CLI reference

The ghosthand CLI controls an iPhone through the daemon on your Mac. Every command is also an MCP tool and an HTTP route, with the same help text.

Install

npx ghosthand --help

Agent loop

Take a lease, act, read the screen, release. Commands that use an iPhone need the lease with -l.
  1. ghosthand list (which iPhones, locked, leased by whom)
    ghosthand acquire -d <id> --label <session id> --reason "<task>" (prints e.g. studio:42 (42 below))
  2. ghosthand screentext -l 42 (read text and boxes (cheap, no image))
    ghosthand screenshot -l 42 -o s.png (or look at the screen (~500 tokens))
  3. ghosthand tap -l 42 --text "Label" --screenshot s.png --screentext
    ghosthand tap -l 42 <x> <y> --screenshot s.png --screentext (x,y read from s.png)
  4. read the printed text and s.png, decide the next action toward the task, repeat 3
  5. ghosthand release -l 42 (when the task is done)
The full rules are in the agent manual.

Global options

OptionDescription
-l, --lease [id]Lease id from ghosthand acquire (or GHOSTHAND_LEASE) with its Mac, e.g. studio:42 for an iPhone on Mac studio. Every command that uses an iPhone needs it and runs on its iPhone
-h, --helpDisplay this message
-v, --versionDisplay version number

Commands

Grouped commands take a subcommand: ghosthand file push. MCP tool names join the words with -.

Leases

CommandWhat it does
listList iPhones connected over USB, to this Mac and to the account's other Macs
acquireTake exclusive use of an iPhone for a task. Prints a short lease id; pass it explicitly with -l to every other command
waitWait until another lease on the iPhone ends, then acquire it. Use only after acquire said it is busy and you decided to wait
releaseEnd the lease from -l or GHOSTHAND_LEASE, so another client can acquire the iPhone

Screen

CommandWhat it does
screenshotSave the current iPhone screen as PNG (or JPG) over USB, in about 0.3s
screentextRead the text on the iPhone screen with on-device OCR. One line per text: x,y wxh text in screenshot coordinates (same space as tap)

Input

CommandWhat it does
tapTap at screenshot coordinates or on text found by OCR, via the AssistiveTouch mouse pointer
double-tapDouble tap at screenshot coordinates or on text found by OCR, via the AssistiveTouch mouse pointer
triple-tapTriple tap at screenshot coordinates or on text found by OCR, via the AssistiveTouch mouse pointer
holdPress and hold (long press) at screenshot coordinates or on text found by OCR, via the AssistiveTouch mouse pointer
swipeSwipe a finger like a person from (x1,y1) to (x2,y2) in screenshot coordinates: fast, lifted while moving. For TikTok, feeds, lists, carousels, Home Screen pages
hold-dragLong press at (x1,y1), then drag to (x2,y2) with the button still held: moves items that need a long press first, like Home Screen icons
scrollScroll with the Bluetooth mouse wheel over a point (default: screen center). Use this to scroll web pages and lists; one tick is about 100 points
keyPress a key on the Bluetooth keyboard: home (Home Screen), enter, backspace, esc, arrows, volumeup. cmd+space opens Spotlight to open apps
typeType text on the Bluetooth keyboard (US-ASCII)

Tasks

CommandWhat it does
taskDo a task in plain words: a fast agent on ghosthand.dev reads the screen with OCR and taps until it is done, then answers

iPhone

CommandWhat it does
wakeTurn the display on with a Bluetooth click at the status bar, then check that USB frames arrive
lockLock the iPhone over Bluetooth with Control-Command-Q; verify over USB
unlockUnlock with the Bluetooth keyboard: Enter, Enter, passcode, then check the lock state over USB (~3s). A wrong passcode is not retried
muteMute all iPhone sound (media in every app too) with the Bluetooth keyboard Mute key, confirmed from the iPhone log over USB
unmuteTurn iPhone sound back on after mute, confirmed from the iPhone log over USB
assistivetouchShow, or turn on or off, AssistiveTouch over USB (no touch on the phone, also while locked). acquire turns it on, release turns it off
renameSet the iPhone's name over USB (Settings > General > About > Name), no touch needed
forgetRemove this Mac's Bluetooth bond with the iPhone, to pair again from scratch
controlShow or switch how input reaches the iPhone: Bluetooth mouse and keyboard (default) or XCTest (WebDriverAgent). Switch only when the user asks
infoShow battery, storage, iOS build, serial number, language, time zone and SIM over USB (works while locked)
logsRead the iPhone system log over USB for a few seconds, filtered by process or text
restartRestart the iPhone over USB. Afterwards a person must type the passcode once
shutdownTurn the iPhone off over USB. Only a person can turn it on again

Recording

CommandWhat it does
record startStart recording the iPhone screen and sound to a new .mov or .mp4 file. Stops by itself after 5 minutes; stop earlier with record stop
record stopStop the screen recording and wait until the file is complete. Prints path, duration, size, resolution and fps

Files, photos and apps

CommandWhat it does
file listList a folder on the iPhone over USB (AFC): /DCIM, /Downloads, or an app's /Documents with --app
file pullCopy a file or folder from the iPhone to this Mac over USB
file pushCopy a file from this Mac to the iPhone over USB, replacing it and making missing folders
file removeRemove a file, or a folder with everything in it, on the iPhone over USB
photo listList the newest Camera Roll files (photos, videos, screenshots) on the iPhone, newest first
photo pullCopy the newest Camera Roll files (photos, videos, screenshots) from the iPhone to this Mac
photo deleteDelete photos from the iPhone's Photos library by file name (from photo list), over USB
uploadUpload a photo or video to a 1-day link that Safari on the iPhone saves to Photos (Save Video, Save Image)
app listList installed apps over USB, with where each icon is on the Home Screen
app installInstall an .ipa signed for this iPhone over USB (ad hoc, enterprise or development signing)
app uninstallUninstall an app and its data over USB, like Remove App > Delete App

Setup and account

CommandWhat it does
setupOpen the setup window: connect a new iPhone over USB and Bluetooth, step by step
setup statusRead setup readiness as JSON, including missing permissions and disconnected phones; no lease needed
accountShow this Mac's ghosthand.dev account: who is signed in, the plan, and the subscribe link
account loginSign this Mac in to ghosthand.dev in the browser. For people; agents run ghosthand setup instead
account logoutSign this Mac out of ghosthand.dev; leases fail until it signs in again
dashboardOpen the control plane window: every iPhone, which agent uses it and why, and its live screen

Tunnel and scripts

CommandWhat it does
tunnel urlPrint this Mac's tunnel URL, to call the HTTP API from a script (curl, Linux). --new-token also creates the API token
tunnel revokeRevoke an API token made with tunnel url --new-token; scripts that use it get 401

Daemon

CommandWhat it does
daemon startStart the background daemon. Other commands start it on demand
daemon stopStop the daemon
daemon restartRestart the daemon
daemon statusShow daemon state, listeners, Bluetooth state and the log path
daemon runRun the daemon in the foreground (for launchd or debugging)

Random values

CommandWhat it does
randomMake a random name, lastname, username, birthdate (18+) or password for a new account, saved with the lease. random list shows every saved value

Agent manual

The rules every agent gets with ghosthand --help, and as the MCP server instructions.
  • Ghosthand app windows are user-only. Never interact with them for the user.
  • Missing macOS Camera or Bluetooth permission: run ghosthand setup once and tell the user to complete setup in the small Ghosthand window. Poll setup status every 2 seconds until ready is true, then continue automatically. Do not request permissions yourself. No normal command or preview shows permission dialogs.
  • Leases: every command that uses an iPhone needs one (list does not). Always pass --reason with your task. An iPhone leased by someone else fails at once and shows the label, reason, and how long ago it was acquired and last used. Decide: give up or tell the user, or run ghosthand wait. Never --force unless its holder is gone. A lease ends after 10 min without a command. Pass -l explicitly: tool-call environments may not persist. --label is display only.
  • --wait-text checks a known expected text after input, with --timeout-ms 1...60000 (default 5000). A timeout says input was sent; never repeat input automatically. Already-present matching text does not prove the action caused a transition.
  • Non-English phone: export GHOSTHAND_LANGUAGE=it-IT (or pass --language) once, so screentext and tap --text read accents and local words right.
  • Coordinates are screen points by default: the numbers you read in a screenshot or in screentext are the numbers you send to tap/swipe. Never rescale them yourself.
  • Add --screenshot and/or --screentext to every action: they wait until the screen is still, then save the image / print the text. No separate screenshot call.
  • Before type, read a screenshot: the cursor must be in the field you want. Keys go to the focused field (in Messages, Enter in To: keeps focus there).
  • Leave the iPhone unlocked when done. Locked phones give no screenshots. The daemon keeps every unlocked USB- and Bluetooth-connected iPhone awake (a Control key press after 10 s idle). Locked or unplugged iPhones get no key, so Auto-Lock works normally.
  • A wrong unlock passcode is never retried (failed attempts count toward lockout).
  • Account: acquire needs this Mac signed in to ghosthand.dev. The free plan covers one iPhone. login-required: run ghosthand setup, tell the user to sign in there, poll setup status. subscription-required: show the user the links in the error, acquire again after they change the plan; never retry in a loop. Do not run account login yourself.
  • New account and the user gave no details: get each from ghosthand random <kind> (name, lastname, username, birthdate, password). Never invent a password. Every value is saved: ghosthand random list finds one you forgot.
  • ghosthand drives the iPhone as a Bluetooth keyboard and mouse, so iOS keyboard shortcuts work with key: cmd+a then backspace clears a field, alt+backspace, cmd+shift+left, cmd+c, cmd+z, fn+h (Home), fn+up (App Switcher), fn+c (Control Center), fn+n (notifications). Full list: ghosthand key --help.
  • Go Home with key home, not the AssistiveTouch menu.
  • Screen shrunk to the bottom half (iOS Reachability), sheets look stale: tap the empty top area (tap 207 100) to restore it. Check this before anything else.
  • Screen dimmed but no dialog in the screenshot: the dialog is hidden from USB capture. screenshot --native takes a real iOS screenshot (cmd+shift+3) that shows it, at the same coordinates tap takes. A button that ignores tap: press it once more (tap or hold x y --duration 400); a just-opened alert can ignore the first press.
  • Long press (context menus, Home Screen icon menu, previews): hold x y. Move an item that needs a long press first (Home Screen icons): hold-drag --hold 2500.
  • Files, photos, apps, battery and logs go over USB without the screen: file list, file pull, file push, photo list, photo pull, app list, info, logs (see each --help). To add a photo or video to Photos: ghosthand upload <file>, then Safari (upload --help).
  • Dialog not responding or invisible to capture: try lock, then unlock once to dismiss it without accepting an option (tested on an XR, iOS 18.7). First obtain a user-confirmed passcode and pipe it to unlock --stdin. Without one, ask the user before locking. Check the screen afterward; this may not dismiss every dialog. Never retry a failed passcode or guess hidden taps.
  • Scroll far with scroll down <ticks> (mouse wheel, ~100 pt per tick). swipe moves content by the drag length (no momentum): use it for pages and short moves.
  • Swipe Home Screen pages from empty space or an icon, not from a widget, the dock or the AssistiveTouch button.
  • Open an app: key cmd+space, type <app name>, key enter (works from any app; tested on an SE2, iOS 18.6). Faster than swiping Home Screen pages.
  • An iPhone in XCTest mode (list shows xctest) takes the same commands through Apple's UI testing instead of Bluetooth. No lock, unlock, mute or shortcuts there; see control --help. Switch modes only when the user asks.
  • On errors, read the whole message: it says what failed and what to do.
  • No iPhone in list, or errors about USB, Trust, a never-paired iPhone, or Bluetooth that never connects: the user must connect or fix the phone. Run ghosthand setup once (MCP: use the setup tool). Tell the user to complete setup in the small Ghosthand window. All actions in the Ghosthand app window are user-only. Agents must not interact with the window or complete setup for the user. Poll ghosthand setup status (MCP: setup-status) every 2 seconds until ready is true. Pass --device (MCP: device) for the intended iPhone if known or if several are connected; use the returned device id on later polls. When ready, acquire that phone using its captureId from overview. Wait while the user completes setup, then continue automatically when ready. Do not reopen setup, request permissions, or retry input while waiting. If setup is still incomplete after 10 minutes, report the current status instead of retrying forever. Do not tap Trust or pair for them. A locked iPhone that is trusted and paired is not a setup problem: use unlock only with a passcode the user confirmed, otherwise ask the user to unlock it. ghosthand dashboard is a window to watch every iPhone and its agent; open it only if the user asks to see it.
  • No clever loops that wait for a text you guess ("Open", "Done"): the next screen is hard to predict (App Store "Install" confirm, "requires a newer iOS", alerts). Loop only when a skill or document you follow says so. Otherwise: one action, read the whole screen, decide the next action.