/v1/phonesGET/v1/devices it answers
at once, from USB lockdown, and also lists iPhones that screen capture does not show yet:
not trusted, or locked. Each iPhone has one step, the next thing a person must do
(ready when agents can use it), so a client needs no logic of its own. phones is
sorted by id, so the order is stable. macName is the name the iPhone lists under
Settings > Bluetooth.ghosthand tunnel url --new-token. The unix socket needs no tokensigned-out: no account on this Mac; every lease fails with login-required.
signing-in: a browser sign-in runs; open verificationUrl. signed-in: each
acquire checks the iPhone and this Mac against the plan.GET /v1/account. free: one iPhone, on any Mac. pro: every iPhone
on each paid Mac, plus the free iPhone anywhere. Acquire on another iPhone fails
with subscription-required.GET /v1/account. Macs the Pro subscription pays for; 0 on freeGET /v1/account. True when the account can read the daemon source on GitHubGET /v1/account, when ghosthand.dev could not be reachedauthorized, phones have no captureId. notDetermined: the user clicks Allow
Camera in setup. denied: the user opens Camera privacy settings from setup.
restricted: blocked by macOS policy. Commands and previews never ask by themselves.not-started: allowed, but no USB iPhone uses Bluetooth mode yet; starts on the first
Bluetooth command or when list or setup sees one. starting: waiting for
Bluetooth or HID publication. on: the HID service is published. Permission states
are checked before hardware state. Missing or denied permission tells the agent to
run setup and poll setup status until ready. Only the setup app's buttons request permissions
or open privacy settings. powered-off: turn Bluetooth on.
unsupported: authorized, but Classic is unavailable. error: service failure.photo delete, screenshot --native). The user clicks Allow Photos in setup.bluetooth (default): the Mac is a Bluetooth mouse and
keyboard; screenshots come from USB screen capture. xctest: WebDriverAgent, an XCUITest
runner, taps, types and takes screenshots (they show dialogs that USB capture hides).
Needs Xcode, Developer Mode and UI Automation. No passcode unlock, mute or keyboard shortcuts.92MF9DG2LRstopped: not started since the daemon started; the next command starts it (about
15 s). building: Xcode builds it (1-3 min the first time). starting: launched,
waiting for its HTTP server. running: input works. failed: see error./v1/devices; that is captureId.list prints and acquire -d takes. Absent until screen capture shows the iPhone and it is matched to its USB device.iPhone11,8iPhone XR. Absent for unknown product types+39 333 123 4567. Absent without a SIM, when the carrier did not write it, or when the iPhone is not trusted.trust: unlock the iPhone and tap Trust. unlock: trusted, needs its passcode.
usbUnreadable: trusted, but the lock state or Bluetooth address could not be read over USB.
Bluetooth mode: bluetoothUnavailable: Bluetooth is not ready on this Mac (see bluetooth).
pair: pair the Mac from iPhone Settings > Bluetooth. connecting: paired, the link
is down; the Mac reconnects.
XCTest mode: developerMode: turn on Developer Mode on the iPhone. xctestStarting:
WebDriverAgent builds or starts. xctestFailed: its start failed (xctest.error).
ready: agents can use it."A4:83:E7:12:34:56"Pattern: ^[0-9A-F]{2}(:[0-9A-F]{2}){5}$connected: input works. disconnected: paired, the Mac is reconnecting; Bluetooth is off
on the iPhone or it is out of range if this lasts. notPaired: pair from iPhone Settings > Bluetooth
(the next input command waits for it).absolute (iOS 17+) goes straight to the spot. relative (iOS 15, which ignores absolute positions) pushes the pointer into the top-left corner, then moves it in measured stepstap or screenshot. Absent before the firstghosthand wait for this iPhone, oldest firstremotePhones. Slug of the Mac the iPhone is plugged into, e.g. studioremotePhones. Name of that Mac, e.g. Tommy's Mac Studiomac and macName, for the control plane. Each Mac pushes its list through
ghosthand.dev when it changes, so the response makes no request. Lease times
(lastUsedAt, lastCommand, expiresAt) can be old. Absent when there are none.bluetooth (default): the Mac is a Bluetooth mouse and
keyboard; screenshots come from USB screen capture. xctest: WebDriverAgent, an XCUITest
runner, taps, types and takes screenshots (they show dialogs that USB capture hides).
Needs Xcode, Developer Mode and UI Automation. No passcode unlock, mute or keyboard shortcuts.92MF9DG2LRstopped: not started since the daemon started; the next command starts it (about
15 s). building: Xcode builds it (1-3 min the first time). starting: launched,
waiting for its HTTP server. running: input works. failed: see error./v1/devices; that is captureId.list prints and acquire -d takes. Absent until screen capture shows the iPhone and it is matched to its USB device.iPhone11,8iPhone XR. Absent for unknown product types+39 333 123 4567. Absent without a SIM, when the carrier did not write it, or when the iPhone is not trusted.trust: unlock the iPhone and tap Trust. unlock: trusted, needs its passcode.
usbUnreadable: trusted, but the lock state or Bluetooth address could not be read over USB.
Bluetooth mode: bluetoothUnavailable: Bluetooth is not ready on this Mac (see bluetooth).
pair: pair the Mac from iPhone Settings > Bluetooth. connecting: paired, the link
is down; the Mac reconnects.
XCTest mode: developerMode: turn on Developer Mode on the iPhone. xctestStarting:
WebDriverAgent builds or starts. xctestFailed: its start failed (xctest.error).
ready: agents can use it."A4:83:E7:12:34:56"Pattern: ^[0-9A-F]{2}(:[0-9A-F]{2}){5}$connected: input works. disconnected: paired, the Mac is reconnecting; Bluetooth is off
on the iPhone or it is out of range if this lasts. notPaired: pair from iPhone Settings > Bluetooth
(the next input command waits for it).absolute (iOS 17+) goes straight to the spot. relative (iOS 15, which ignores absolute positions) pushes the pointer into the top-left corner, then moves it in measured stepstap or screenshot. Absent before the firstghosthand wait for this iPhone, oldest firstremotePhones. Slug of the Mac the iPhone is plugged into, e.g. studioremotePhones. Name of that Mac, e.g. Tommy's Mac Studiotitle and detail are for people.curl -X GET "https://ghosthand.dev/macs/studio/v1/phones" \ -H "Authorization: Bearer <token>"
{ "macName": "Tommy's MacBook Pro", "camera": "authorized", "bluetooth": { "state": "on" }, "phones": [ { "id": "00008020-001A2B3C4D5E002E", "captureId": "7EF219AD-69B4-423E-B8C4-4F4A6140822F", "name": "Tommy's iPhone", "model": "iPhone11,8", "modelName": "iPhone XR", "iosVersion": "17.6.1", "step": "ready", "assistiveTouch": true, "bluetooth": { "address": "A4:83:E7:12:34:56", "state": "connected" }, "waiting": [] } ] }