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

Request a macOS permission

/v1/setup/permissionsPOST
Called by the setup app only after a user clicks an Allow button. Normal commands never request permissions. Agents run ghosthand setup once, then poll setup status until ready while the user follows the app. Already allowed or denied permissions do not show another prompt; denied permissions need the setup app's Open Settings button.
Authorizationoptional
bearerAuth?Bearer <token>
Required on the tunnel. An API token of the account, from ghosthand tunnel url --new-token. The unix socket needs no token
Request Bodyapplication/jsonrequired
Type: "camera" | "bluetooth" | "photos"
Response
202 · Permission request started; read GET /v1/phones for its result
message *string
What the daemon did, for people and logs
Default · Error (RFC 9457 problem details). `code` is stable; switch on it, not on `title` or `detail`.
code *"invalid-request" | "unauthorized" | "not-found" | "device-not-found" | "no-device" | "multiple-devices" | "permission-denied" | "bluetooth-unavailable" | "bluetooth-disconnected" | "no-frame" | "device-locked" | "lock-failed" | "pairing-timeout" | "pointer-not-found" | "lock-state-unavailable" | "lockdown-unavailable" | "unlock-failed" | "mute-unconfirmed" | "text-not-found" | "wait-text-timeout" | "cancelled" | "lease-invalid" | "device-leased" | "recording-active" | "no-recording" | "recording-failed" | "daemon-busy" | "tunnel-offline" | "login-required" | "subscription-required" | "unsupported-in-mode" | "xctest-unavailable" | "task-failed" | "internal-error"
Stable error code. Switch on it; title and detail are for people.
title *string
Short summary of the code, the same for every error with this code
status *integer
HTTP status of the error. In stream mode the response status stays 200.
detail *string
What happened and what to do next. Agents should read it.
Request example
curl -X POST "https://ghosthand.dev/macs/studio/v1/setup/permissions" \ -H "Authorization: Bearer <token>" \ -H "Content-Type: application/json" \ -d '"camera"'
Response example
{ "code": "device-leased", "title": "iPhone leased by another client", "status": 409, "detail": "Tommy's iPhone is in use by another lease:\n ses_456 (book a table on OpenTable), acquired 2 min ago, last used 10 s ago (tap)\nDecide first: if that task is still active, give up or tell the user the iPhone is busy." }