# Double tap Source: https://docs.tapkit.ai/api-reference/double-tap POST /phones/{phone_id}/double-tap Double tap a point on the screen Tap twice quickly at a point. Double tapping zooms in many apps and selects a word in a text field. The phone's ID, from [List phones](/api-reference/list-phones). Return `{"job_id": ...}` immediately instead of waiting for the action. See [Jobs](/api-reference/introduction#jobs). ## Body Horizontal position in pixels from the left edge. Vertical position in pixels from the top edge. ```bash cURL theme={null} curl -X POST https://api.tapkit.ai/v1/phones/$PHONE_ID/double-tap \ -H "X-API-Key: $TAPKIT_API_KEY" \ -H "Content-Type: application/json" \ -d '{"x": 585, "y": 1266}' ``` ```json 200 theme={null} { "id": "5d2c9a0e-7f7b-4c1e-9d1a-2f4b8e0c3a61", "status": "completed", "result": {}, "created_at": "2026-09-23T18:30:00Z", "completed_at": "2026-09-23T18:30:01Z" } ``` # Download screenshot Source: https://docs.tapkit.ai/api-reference/download-screenshot GET /jobs/{job_id}/download Fetch the image from an async screenshot Returns the PNG captured by a [screenshot](/api-reference/screenshot) requested with `?async=true`. Returns `404 DATA_NOT_FOUND` if the image isn't available yet. The `job_id` returned by the screenshot request. ```bash cURL theme={null} curl https://api.tapkit.ai/v1/jobs/$JOB_ID/download \ -H "X-API-Key: $TAPKIT_API_KEY" \ -o screen.png ``` # Drag Source: https://docs.tapkit.ai/api-reference/drag POST /phones/{phone_id}/drag Press, move, and release Press at one point, move to another, and release. Use a drag to move a slider, scroll an exact distance, or pull to refresh. The phone's ID, from [List phones](/api-reference/list-phones). Return `{"job_id": ...}` immediately instead of waiting for the action. See [Jobs](/api-reference/introduction#jobs). ## Body Start position, pixels from the left edge. Start position, pixels from the top edge. End position, pixels from the left edge. End position, pixels from the top edge. How fast to move: `slow`, `medium`, or `fast`. ```bash cURL theme={null} curl -X POST https://api.tapkit.ai/v1/phones/$PHONE_ID/drag \ -H "X-API-Key: $TAPKIT_API_KEY" \ -H "Content-Type: application/json" \ -d '{"from_x": 585, "from_y": 600, "to_x": 585, "to_y": 1400, "speed": "medium"}' ``` ```json 200 theme={null} { "id": "5d2c9a0e-7f7b-4c1e-9d1a-2f4b8e0c3a61", "status": "completed", "result": {}, "created_at": "2026-09-23T18:30:00Z", "completed_at": "2026-09-23T18:30:01Z" } ``` # Flick Source: https://docs.tapkit.ai/api-reference/flick POST /phones/{phone_id}/flick Quick swipe from a point Swipe quickly from a point in one direction. Flicks scroll lists, turn pages, and dismiss sheets. To move further down a list, flick `up`. The phone's ID, from [List phones](/api-reference/list-phones). Return `{"job_id": ...}` immediately instead of waiting for the action. See [Jobs](/api-reference/introduction#jobs). ## Body Horizontal position in pixels from the left edge. Vertical position in pixels from the top edge. `up`, `down`, `left`, or `right`. ```bash cURL theme={null} curl -X POST https://api.tapkit.ai/v1/phones/$PHONE_ID/flick \ -H "X-API-Key: $TAPKIT_API_KEY" \ -H "Content-Type: application/json" \ -d '{"x": 585, "y": 1500, "direction": "up"}' ``` ```json 200 theme={null} { "id": "5d2c9a0e-7f7b-4c1e-9d1a-2f4b8e0c3a61", "status": "completed", "result": {}, "created_at": "2026-09-23T18:30:00Z", "completed_at": "2026-09-23T18:30:01Z" } ``` # Get apps Source: https://docs.tapkit.ai/api-reference/get-apps GET /phones/{phone_id}/apps List the apps installed on a phone Returns the phone's installed apps and Apple's built-in apps. TapKit saves the list the first time you request it. Call [Refresh apps](/api-reference/refresh-apps) after you install or remove apps. The phone's ID, from [List phones](/api-reference/list-phones). ## Response Each app's `name` and `bundle_id`. Number of apps. When the list was last fetched from the phone. Absent if it was fetched for this request. ```bash cURL theme={null} curl https://api.tapkit.ai/v1/phones/$PHONE_ID/apps \ -H "X-API-Key: $TAPKIT_API_KEY" ``` ```json 200 theme={null} { "apps": [ { "name": "Safari", "bundle_id": "com.apple.mobilesafari" }, { "name": "Settings", "bundle_id": "com.apple.Preferences" } ], "app_count": 2, "updated_at": "2026-09-23T18:30:00Z", "source": "database" } ``` # Get job Source: https://docs.tapkit.ai/api-reference/get-job GET /jobs/{job_id} Check the status of an action Poll a job started with `?async=true`. See [Jobs](/api-reference/introduction#jobs). The `job_id` returned by the action. ## Response The job's ID. `pending`, `running`, `completed`, or `failed`. On failure, `error` describes what went wrong. When the job was created. When the job finished. ```bash cURL theme={null} curl https://api.tapkit.ai/v1/jobs/$JOB_ID \ -H "X-API-Key: $TAPKIT_API_KEY" ``` ```json 200 theme={null} { "id": "5d2c9a0e-7f7b-4c1e-9d1a-2f4b8e0c3a61", "status": "failed", "result": { "error": "TIMEOUT" }, "created_at": "2026-09-23T18:30:00Z", "completed_at": "2026-09-23T18:31:00Z" } ``` # Get phone status Source: https://docs.tapkit.ai/api-reference/get-status GET /phones/{phone_id}/status Check whether a phone is connected The phone's ID, from [List phones](/api-reference/list-phones). ## Response The phone's ID. The phone's TapKit name, or the name it reports if you haven't renamed it. `online`, `available`, or `offline`. See [List phones](/api-reference/list-phones). Screen width in pixels. Screen height in pixels. The response has other fields that aren't part of the API. Don't rely on them. ```bash cURL theme={null} curl https://api.tapkit.ai/v1/phones/$PHONE_ID/status \ -H "X-API-Key: $TAPKIT_API_KEY" ``` ```json 200 theme={null} { "phone_id": "d9fb00a7-1c7a-44dc-88f6-d06ba5061fdd", "phone_name": "Test phone", "connection_status": "online", "width": 1170, "height": 2532 } ``` # Hold and drag Source: https://docs.tapkit.ai/api-reference/hold-and-drag POST /phones/{phone_id}/hold-and-drag Long press, then drag Press and hold at one point, then drag to another and release. Use it to move app icons, reorder lists, and drag and drop. The phone's ID, from [List phones](/api-reference/list-phones). Return `{"job_id": ...}` immediately instead of waiting for the action. See [Jobs](/api-reference/introduction#jobs). ## Body Start position, pixels from the left edge. Start position, pixels from the top edge. End position, pixels from the left edge. End position, pixels from the top edge. How long to hold before moving, in milliseconds. How fast to move: `slow`, `medium`, or `fast`. ```bash cURL theme={null} curl -X POST https://api.tapkit.ai/v1/phones/$PHONE_ID/hold-and-drag \ -H "X-API-Key: $TAPKIT_API_KEY" \ -H "Content-Type: application/json" \ -d '{"from_x": 300, "from_y": 800, "to_x": 900, "to_y": 800, "hold_duration_ms": 500, "speed": "medium"}' ``` ```json 200 theme={null} { "id": "5d2c9a0e-7f7b-4c1e-9d1a-2f4b8e0c3a61", "status": "completed", "result": {}, "created_at": "2026-09-23T18:30:00Z", "completed_at": "2026-09-23T18:30:01Z" } ``` # Home Source: https://docs.tapkit.ai/api-reference/home POST /phones/{phone_id}/home Go to the Home Screen Go to the Home Screen from any app. The phone's ID, from [List phones](/api-reference/list-phones). Return `{"job_id": ...}` immediately instead of waiting for the action. See [Jobs](/api-reference/introduction#jobs). ```bash cURL theme={null} curl -X POST https://api.tapkit.ai/v1/phones/$PHONE_ID/home \ -H "X-API-Key: $TAPKIT_API_KEY" ``` ```json 200 theme={null} { "id": "5d2c9a0e-7f7b-4c1e-9d1a-2f4b8e0c3a61", "status": "completed", "result": {}, "created_at": "2026-09-23T18:30:00Z", "completed_at": "2026-09-23T18:30:01Z" } ``` # API overview Source: https://docs.tapkit.ai/api-reference/introduction Control connected iPhones over HTTP The REST API sends touch and keyboard input to your iPhones and takes screenshots. It has the same actions that agents get through [MCP](/integrations/mcp), for code that doesn't use an agent framework. ## Base URL ``` https://api.tapkit.ai/v1 ``` ## Authentication Send an API key in the `X-API-Key` header. Create keys in the [web app](/web-app#api-keys). Keys start with `tk_`. ```bash theme={null} curl https://api.tapkit.ai/v1/phones \ -H "X-API-Key: $TAPKIT_API_KEY" ``` A key has access to every phone in your organization. Keep it out of source control and client-side code. ## Before you call an action A phone accepts actions when its Mac app is open and signed in, the phone is connected, unlocked, and set up in the Mac app, and the phone is active on your subscription. [List phones](/api-reference/list-phones) returns each phone's ID and `connection_status`. ## Coordinates Coordinates are integer pixels on the phone's screen, measured from the top-left corner. They match the pixels of a [screenshot](/api-reference/screenshot). [List phones](/api-reference/list-phones) reports each screen's `width` and `height`. ## Jobs Every action runs as a job on the phone's Mac. By default, a request waits up to 60 seconds for the job to finish and then returns it: ```json theme={null} { "id": "5d2c9a0e-7f7b-4c1e-9d1a-2f4b8e0c3a61", "status": "completed", "result": {}, "created_at": "2026-09-23T18:30:00Z", "completed_at": "2026-09-23T18:30:01Z" } ``` `status` is `pending`, `running`, `completed`, or `failed`. A failed action still returns HTTP 200, with the reason in `result.error`. If an action doesn't finish in 60 seconds, its job fails with `"error": "TIMEOUT"`. Add `?async=true` to get the job ID back immediately, then poll [Get job](/api-reference/get-job): ```json theme={null} { "job_id": "5d2c9a0e-7f7b-4c1e-9d1a-2f4b8e0c3a61" } ``` ## Errors Other errors return an HTTP error status, with details under `detail`: ```json theme={null} { "detail": { "error": "PHONE_NOT_FOUND", "message": "Phone not found", "context": { "phone_id": "..." } } } ``` | Status | `error` | Meaning | | ------ | ----------------------- | ------------------------------------------------------------------------------------------- | | 401 | `AUTH_REQUIRED` | No `X-API-Key` header | | 401 | `INVALID_API_KEY` | The key is wrong or revoked | | 402 | `SUBSCRIPTION_REQUIRED` | Your organization has no active subscription | | 404 | `PHONE_NOT_FOUND` | No phone with that ID in your organization | | 409 | `PHONE_INACTIVE` | The phone isn't active on your subscription. Activate it in the [web app](/web-app#phones). | | 400 | `MAC_APP_NOT_RUNNING` | The phone's Mac app isn't connected | | 408 | `TIMEOUT` | A screenshot didn't arrive in time | # Press key Source: https://docs.tapkit.ai/api-reference/keypress POST /phones/{phone_id}/keypress Press a keyboard key Press a keyboard key on the phone, optionally holding modifier keys. Use it to delete text, submit a field, dismiss the keyboard, or move the cursor. The phone's ID, from [List phones](/api-reference/list-phones). Return `{"job_id": ...}` immediately instead of waiting for the action. See [Jobs](/api-reference/introduction#jobs). ## Body `enter`, `escape`, `backspace`, `arrow_up`, `arrow_down`, `arrow_left`, or `arrow_right`. Modifier keys to hold: any of `control`, `shift`, `alternate`, `command`. How many times to press the key. At least 1. ```bash cURL theme={null} curl -X POST https://api.tapkit.ai/v1/phones/$PHONE_ID/keypress \ -H "X-API-Key: $TAPKIT_API_KEY" \ -H "Content-Type: application/json" \ -d '{"key": "backspace", "repeat": 5}' ``` ```json 200 theme={null} { "id": "5d2c9a0e-7f7b-4c1e-9d1a-2f4b8e0c3a61", "status": "completed", "result": {}, "created_at": "2026-09-23T18:30:00Z", "completed_at": "2026-09-23T18:30:01Z" } ``` # List phones Source: https://docs.tapkit.ai/api-reference/list-phones GET /phones List every phone in your organization Returns every phone your organization has connected, including offline ones. ## Response The phone's ID. Pass it as `phone_id` to every other endpoint. The name the phone reports, such as "Tom's iPhone". The name you gave the phone in TapKit, if any. See [Rename phone](/api-reference/rename-phone). `online` if the phone is connected and selected on its Mac, `available` if it's connected to a Mac but not selected, or `offline`. `active` or `inactive`. Only active phones accept actions. The Mac the phone is connected to. Screen width in pixels. Screen height in pixels. When the phone was first connected. The response has other fields that aren't part of the API. Don't rely on them. ```bash cURL theme={null} curl https://api.tapkit.ai/v1/phones \ -H "X-API-Key: $TAPKIT_API_KEY" ``` ```json 200 theme={null} [ { "id": "d9fb00a7-1c7a-44dc-88f6-d06ba5061fdd", "name": "iPhone", "display_name": "Test phone", "connection_status": "online", "activation_state": "active", "connected_mac_id": "3f1e8c52-6a0b-4d8e-9b7a-1c2d3e4f5a6b", "width": 1170, "height": 2532, "created_at": "2026-09-11T17:02:44Z" } ] ``` # Refresh apps Source: https://docs.tapkit.ai/api-reference/refresh-apps POST /phones/{phone_id}/apps/refresh Fetch a phone's app list again Fetches the app list from the phone and saves it. Returns the same `apps` and `app_count` as [Get apps](/api-reference/get-apps). The phone's ID, from [List phones](/api-reference/list-phones). ```bash cURL theme={null} curl -X POST https://api.tapkit.ai/v1/phones/$PHONE_ID/apps/refresh \ -H "X-API-Key: $TAPKIT_API_KEY" ``` # Rename phone Source: https://docs.tapkit.ai/api-reference/rename-phone PATCH /phones/{phone_id}/settings Change the name TapKit and agents use for a phone The phone's ID, from [List phones](/api-reference/list-phones). ## Body The new name. ## Response The updated phone, in the same shape as [List phones](/api-reference/list-phones). ```bash cURL theme={null} curl -X PATCH https://api.tapkit.ai/v1/phones/$PHONE_ID/settings \ -H "X-API-Key: $TAPKIT_API_KEY" \ -H "Content-Type: application/json" \ -d '{"display_name": "Test phone"}' ``` # Screenshot Source: https://docs.tapkit.ai/api-reference/screenshot GET /phones/{phone_id}/screenshot Capture a phone's screen Returns a PNG of the phone's screen at full resolution. Pixel positions in the image are the coordinates gesture endpoints expect. The phone's ID, from [List phones](/api-reference/list-phones). Return `{"job_id": ...}` immediately. Fetch the image with [Download screenshot](/api-reference/download-screenshot) once the [job](/api-reference/get-job) completes. ## Response `image/png` bytes. If the screenshot doesn't arrive within 60 seconds, the request fails with `408 TIMEOUT`. ```bash cURL theme={null} curl https://api.tapkit.ai/v1/phones/$PHONE_ID/screenshot \ -H "X-API-Key: $TAPKIT_API_KEY" \ -o screen.png ``` # Tap Source: https://docs.tapkit.ai/api-reference/tap POST /phones/{phone_id}/tap Tap a point on the screen Tap once at a point. The phone's ID, from [List phones](/api-reference/list-phones). Return `{"job_id": ...}` immediately instead of waiting for the action. See [Jobs](/api-reference/introduction#jobs). ## Body Horizontal position in pixels from the left edge. Vertical position in pixels from the top edge. ```bash cURL theme={null} curl -X POST https://api.tapkit.ai/v1/phones/$PHONE_ID/tap \ -H "X-API-Key: $TAPKIT_API_KEY" \ -H "Content-Type: application/json" \ -d '{"x": 585, "y": 1266}' ``` ```json 200 theme={null} { "id": "5d2c9a0e-7f7b-4c1e-9d1a-2f4b8e0c3a61", "status": "completed", "result": {}, "created_at": "2026-09-23T18:30:00Z", "completed_at": "2026-09-23T18:30:01Z" } ``` # Tap and hold Source: https://docs.tapkit.ai/api-reference/tap-and-hold POST /phones/{phone_id}/tap-and-hold Long press a point on the screen Press and hold at a point. A long press opens context menus and previews, and puts the Home Screen into edit mode. The phone's ID, from [List phones](/api-reference/list-phones). Return `{"job_id": ...}` immediately instead of waiting for the action. See [Jobs](/api-reference/introduction#jobs). ## Body Horizontal position in pixels from the left edge. Vertical position in pixels from the top edge. How long to hold, in milliseconds. ```bash cURL theme={null} curl -X POST https://api.tapkit.ai/v1/phones/$PHONE_ID/tap-and-hold \ -H "X-API-Key: $TAPKIT_API_KEY" \ -H "Content-Type: application/json" \ -d '{"x": 585, "y": 1266, "duration_ms": 1000}' ``` ```json 200 theme={null} { "id": "5d2c9a0e-7f7b-4c1e-9d1a-2f4b8e0c3a61", "status": "completed", "result": {}, "created_at": "2026-09-23T18:30:00Z", "completed_at": "2026-09-23T18:30:01Z" } ``` # Triple tap Source: https://docs.tapkit.ai/api-reference/triple-tap POST /phones/{phone_id}/triple-tap Triple tap a point on the screen Tap three times quickly at a point. Triple tapping selects a line or paragraph of text. The phone's ID, from [List phones](/api-reference/list-phones). Return `{"job_id": ...}` immediately instead of waiting for the action. See [Jobs](/api-reference/introduction#jobs). ## Body Horizontal position in pixels from the left edge. Vertical position in pixels from the top edge. ```bash cURL theme={null} curl -X POST https://api.tapkit.ai/v1/phones/$PHONE_ID/triple-tap \ -H "X-API-Key: $TAPKIT_API_KEY" \ -H "Content-Type: application/json" \ -d '{"x": 585, "y": 1266}' ``` ```json 200 theme={null} { "id": "5d2c9a0e-7f7b-4c1e-9d1a-2f4b8e0c3a61", "status": "completed", "result": {}, "created_at": "2026-09-23T18:30:00Z", "completed_at": "2026-09-23T18:30:01Z" } ``` # Type Source: https://docs.tapkit.ai/api-reference/type POST /phones/{phone_id}/type Type text into the focused field Type text into the focused field. Tap the field first so the keyboard is showing. The phone's ID, from [List phones](/api-reference/list-phones). Return `{"job_id": ...}` immediately instead of waiting for the action. See [Jobs](/api-reference/introduction#jobs). ## Body The text to type. US-ASCII only, up to 100 characters. Emoji, accented letters, and other characters outside US-ASCII can't be typed. Split text longer than 100 characters across several requests. ```bash cURL theme={null} curl -X POST https://api.tapkit.ai/v1/phones/$PHONE_ID/type \ -H "X-API-Key: $TAPKIT_API_KEY" \ -H "Content-Type: application/json" \ -d '{"text": "hello world"}' ``` ```json 200 theme={null} { "id": "5d2c9a0e-7f7b-4c1e-9d1a-2f4b8e0c3a61", "status": "completed", "result": {}, "created_at": "2026-09-23T18:30:00Z", "completed_at": "2026-09-23T18:30:01Z" } ``` # Examples Source: https://docs.tapkit.ai/examples Prompts to try with TapKit Paste any of these into the Mac app's agent chat, or into Claude or Codex with the TapKit plugin installed. Sign in to the apps you want the agent to use first. Agents can't get past Face ID or CAPTCHAs, and won't type a password you haven't given them. ## Book a flight The agent searches for flights, fills in the dates and airports, and compares the results. Give it the airports, dates, and number of passengers, and say whether to stop at the results or go on to book. > In Safari, go to Google Flights and search for round-trip flights from Orlando to Denver, leaving next Friday and returning Sunday. Find the cheapest option and show me the results. ## Book a haircut Salon booking apps such as Booksy, Vagaro, and Fresha all follow the same steps: pick a service, a place, a stylist, and a time. Name the service and time you want, and tell the agent how to pick a stylist so it doesn't stop to ask. > Open Booksy and book a men's haircut for Saturday at 2pm. Pick the closest barbershop with availability and book with whoever is free. ## Order dinner The agent finds a restaurant in a delivery app, adds items to the cart, and checks out. List exactly what to order, and include a tip amount if you care about it. The app needs a saved address and payment method before the agent can place the order. > Open Uber Eats and order a pepperoni pizza and a Caesar salad from the highest-rated Italian restaurant nearby. Use my saved address and payment method. ## Dating apps The agent reads each profile, likes or passes based on what you tell it to look for, and can write opening messages to matches. Set a limit on how many profiles to review so it doesn't run indefinitely. > Open Hinge and look at 10 profiles. Like people who seem active and outdoorsy, and pass on profiles without a bio. If we match with someone, send a friendly opening message that mentions something from their profile. ## QA testing The agent can run a test script on a real iPhone, against your own app or anyone else's, without test IDs or XCUITest. Write the test as a series of steps, each with what should be on screen afterwards, and ask for a pass or fail on each step. > Open Safari and go to example.com. Check that the page shows the heading "Example Domain". Tap "More information...". Check that a new page loads, and report whether each step passed. ## Writing prompts Name the app, and give specific dates, names, and amounts rather than "a cheap one". Say whether the agent may send, post, or pay, or should check with you first. Agents can't type emoji or accented letters. # How it works Source: https://docs.tapkit.ai/how-it-works How the Mac, the iPhone, and your agent connect TapKit has three parts: your iPhone, the TapKit Mac app, and the TapKit cloud. ## The Mac hosts the iPhone The iPhone stays plugged into a Mac running the TapKit app. The Mac app is the only part of TapKit that talks to the phone. It sees the phone's screen and carries out taps, flicks, typing, and key presses on it. To disconnect a phone, unplug it or quit the Mac app. ## Agents reach the Mac through the cloud While you're signed in, the Mac app keeps a connection open to the TapKit cloud. Claude, Codex, and your own code send commands to the cloud through [MCP](/integrations/mcp) or the [REST API](/api-reference/introduction). The cloud forwards each command to the Mac that the target phone is plugged into, and sends the result back. The built-in agent in the Mac app works with the phone directly and only uses the network to call a hosted language model. ## Why this architecture? * **No jailbreak, no sideloading, no developer mode.** Nothing is installed on the iPhone. * **Works with any app.** TapKit interacts with the phone through the same visible interface a person uses, rather than relying on app-specific integrations. * **Remote by default.** The API layer means your agent can be anywhere. The Mac and phone can be in a closet, a data center, or on your desk. ## What happens when you run a task ```mermaid theme={null} sequenceDiagram participant Agent as Your AI Agent participant Server as TapKit Server participant Mac as Mac App participant Phone as iPhone Agent->>Server: Send command (API / MCP) Server->>Mac: Route to host Mac Mac->>Phone: Execute action Phone-->>Mac: Updated screen Mac-->>Server: Screenshot Server-->>Agent: Result Note over Agent: Decide next action Agent->>Server: Next command... ``` Every TapKit agent works in a loop. It takes a screenshot, decides what to do, then taps, flicks, types, or presses a key. Then it takes another screenshot to check the result, and repeats until the task is done. ## When a phone is ready A phone works with TapKit when the Mac app is open and signed in, the iPhone is plugged in and unlocked, and you've finished [setup](/setup) for it in the Mac app. The phone also has to be active on your TapKit subscription. If a phone isn't ready, it shows as offline. See [Setup](/setup#troubleshooting). # Introduction Source: https://docs.tapkit.ai/index Give your agent an iPhone TapKit lets AI agents use real iPhones. Plug an iPhone into a Mac running the TapKit app, and an agent can take screenshots of it, tap, and type. The agent can be TapKit's built-in agent, Claude, Codex, or your own code. Nothing is installed on the iPhone. You don't need to jailbreak it, turn on developer mode, or use a simulator. ## What you can do with it Tell the TapKit Mac app what to do on a phone and watch it work. Install the TapKit plugin and ask your assistant to use your iPhone. Point Cursor or your own agent at `https://mcp.tapkit.ai/mcp`. Send taps, keystrokes, and screenshot requests from your own code. ## Get started Install the Mac app, connect an iPhone, and run your first task. How the Mac, the iPhone, and your agent connect. # Claude app Source: https://docs.tapkit.ai/integrations/claude-app Control iPhones from Claude Chat and Cowork The TapKit plugin adds the TapKit connector and TapKit's [skills](/integrations/skills) to Claude Chat and Cowork. You install it from Cowork in the Claude app. To use TapKit in the terminal, see [Claude Code](/integrations/claude-code). ## 1. Add the TapKit marketplace 1. Open **Cowork** in the Claude app. 2. In the left sidebar, click **Customize**. 3. Go to **Personal Plugins** and click the **+** button. 4. In the popup, hover over **Create Plugin**. 5. Click **Add Marketplace**. 6. Paste this and confirm: ``` jootsing-research/tapkit-plugins-claude ```
Customize sidebar showing Personal Plugins, Create Plugin, and Add Marketplace Add marketplace popup with URL field for owner/repo
## 2. Install the plugin Still under **Customize** in Cowork, click **Browse Plugins**. Find **TapKit** in the list, click **Install**, then click **Manage**. TapKit now appears under **Personal Plugins** in the Customize sidebar.
Customize sidebar with Browse Plugins button Directory showing Anthropic and Partners plugins
Personal tab showing tapkit-plugins-claude marketplace with Tapkit plugin Tapkit plugin page with Install button, skills, and connectors
## 3. Allow the tools In the Customize sidebar, click the **TapKit** plugin, click **Connectors**, and select the **TapKit** connector. Set its tool permission to **Always allow**.
TapKit plugin in Customize sidebar showing Skills and Connectors TapKit connector with Tool permissions set to Always allow
## 4. Sign in The first time Claude uses TapKit, it opens TapKit in your browser. Sign in and click **Allow access**. ## Example prompts * "Open Settings and take a screenshot" * "Go to Safari and search for flights to Denver" * "Open DoorDash and order from the first restaurant" * "Take a screenshot and tell me what apps are on the home screen" ## Troubleshooting Open the TapKit connector under **Customize** and reconnect it. Check that the Mac app is open and signed in, and isn't showing a setup message for the phone. Ask Claude to "list my phones" to see what TapKit sees. Unlock the phone and check that it's still plugged in. If the Mac app shows a problem with the phone, fix that first. # Claude Code Source: https://docs.tapkit.ai/integrations/claude-code Control iPhones from Claude Code The TapKit plugin for Claude Code adds the TapKit MCP server and TapKit's [skills](/integrations/skills). ## Install Run these in Claude Code: ``` /plugin marketplace add jootsing-research/tapkit-plugins-claude /plugin install tapkit@tapkit-plugins-claude /reload-plugins ``` ## Sign in Run `/mcp`, select the TapKit server, and choose **Authenticate**. Sign in to TapKit in your browser and click **Allow access**. If the browser doesn't open, open the URL that Claude Code prints. If the redirect back to Claude Code fails, copy the full URL from the browser's address bar and paste it into Claude Code. ## Try it ``` What's on my phone right now? ``` Claude asks for permission the first time it uses each TapKit tool. Choose the "don't ask again" option to allow the tool for the rest of the project, or approve each action as it comes. ## Update ``` /plugin marketplace update tapkit-plugins-claude ``` ## Troubleshooting Run `/mcp` and check the TapKit server's status. If it needs authentication, authenticate again. Check that the Mac app is open and signed in, and isn't showing a setup message for the phone. Ask Claude to "list my phones" to see what TapKit sees. Unlock the phone and check that it's still plugged in. If the Mac app shows a problem with the phone, fix that first. # Codex app Source: https://docs.tapkit.ai/integrations/codex-app Control iPhones from the Codex desktop app The TapKit plugin for Codex adds the TapKit MCP server and TapKit's [skills](/integrations/skills) to the Codex desktop app. The plugin's source is [on GitHub](https://github.com/jootsing-research/tapkit-plugins-codex). For more on Codex plugins, see [OpenAI's docs](https://developers.openai.com/codex/plugins). Adding the marketplace uses the [Codex CLI](https://developers.openai.com/codex/cli), so install it first. ## 1. Add the TapKit marketplace Run this command in your terminal: ```bash theme={null} codex plugin marketplace add jootsing-research/tapkit-plugins-codex ``` If the Codex app is open, restart it to load the new marketplace. ## 2. Open Plugins In the Codex app, click **Plugins** in the left sidebar.
Codex app sidebar with Plugins selected
## 3. Select the TapKit marketplace On the Plugins page, open the marketplace dropdown and select **Tap Kit Plugins**.
Codex plugins page marketplace dropdown showing Tap Kit Plugins
## 4. Install the plugin Find **Tap Kit** under **Productivity**, click the **+** button, then click **Install Tap Kit** in the popup. Tap Kit gets a checkmark in the plugin list when it's installed.
Codex plugins page showing Tap Kit with plus button Install Tap Kit popup with Install Tap Kit button
## 5. Sign in Sign in to TapKit in your browser when Codex asks, and click **Allow access**. ## Try it ``` What phones can you see with TapKit right now? ``` ## Update ```bash theme={null} codex plugin marketplace upgrade tapkit-plugins ``` Restart the Codex app afterwards. # Codex CLI Source: https://docs.tapkit.ai/integrations/codex-cli Control iPhones from the Codex CLI The TapKit plugin for Codex adds the TapKit MCP server and TapKit's [skills](/integrations/skills). The plugin's source is [on GitHub](https://github.com/jootsing-research/tapkit-plugins-codex). For more on Codex plugins, see [OpenAI's docs](https://developers.openai.com/codex/plugins). You need the [Codex CLI](https://developers.openai.com/codex/cli) installed. ## Install 1. Add the TapKit marketplace: ```bash theme={null} codex plugin marketplace add jootsing-research/tapkit-plugins-codex ``` 2. Start Codex and open the plugin directory: ```bash theme={null} codex ``` ``` /plugins ``` 3. Switch to the **Tap Kit Plugins** marketplace, open **Tap Kit**, and select **Install plugin**. 4. Sign in to TapKit in your browser when Codex asks, and click **Allow access**. ## Try it ``` What phones can you see with TapKit right now? ``` ## Update ```bash theme={null} codex plugin marketplace upgrade tapkit-plugins ``` # MCP Source: https://docs.tapkit.ai/integrations/mcp Connect any MCP client to TapKit TapKit runs a hosted MCP server. Any client that supports remote MCP servers with OAuth can connect to it. The only thing you run locally is the [Mac app](/setup). ``` https://mcp.tapkit.ai/mcp ``` The server uses the Streamable HTTP transport. ## Connect Most clients accept a config like this: ```json theme={null} { "mcpServers": { "tapkit": { "type": "http", "url": "https://mcp.tapkit.ai/mcp" } } } ``` Point your MCP client at the URL. The client must support OAuth 2.1 with PKCE and dynamic client registration. The server publishes its OAuth metadata at `/.well-known/oauth-protected-resource/mcp`. ## Sign in The first time your client connects, it opens TapKit in your browser. Sign in with Google, then click **Allow access** to let the client view and interact with your connected iPhones. The MCP server only accepts OAuth. [API keys](/web-app#api-keys) are for the [REST API](/api-reference/introduction). ## Tools Start with `list_phones`. Every other tool takes the `phone_id` it returns. | Tool | Parameters | Description | | ------------------ | ----------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------- | | `list_phones` | None | List phones with their IDs, status, and screen size | | `get_phone_status` | `phone_id` | Connection status and screen size of one phone | | `screenshot` | `phone_id` | Capture the screen as an image | | `tap` | `phone_id`, `x`, `y` | Tap a point | | `double_tap` | `phone_id`, `x`, `y` | Double tap, for zooming or selecting a word | | `triple_tap` | `phone_id`, `x`, `y` | Triple tap, for selecting a line or paragraph | | `long_press` | `phone_id`, `x`, `y`, `duration`? | Press and hold, for context menus. `duration` is in ms, default 1000 | | `flick` | `phone_id`, `x`, `y`, `direction` | Quick swipe `up`, `down`, `left`, or `right` from a point | | `drag` | `phone_id`, `from_x`, `from_y`, `to_x`, `to_y`, `speed`? | Press, move, and release. `speed` is `slow`, `medium`, or `fast`, default `medium` | | `hold_and_drag` | `phone_id`, `from_x`, `from_y`, `to_x`, `to_y`, `hold_duration_ms`?, `speed`? | Long press, then drag, for moving items. Hold defaults to 500 ms | | `type_text` | `phone_id`, `text` | Type into the focused field. US-ASCII only, up to 100 characters | | `press_key` | `phone_id`, `key`, `modifiers`?, `repeat`? | Press `enter`, `escape`, `backspace`, or an arrow key, optionally holding `control`, `shift`, `alternate`, or `command` | | `press_home` | `phone_id` | Go to the Home Screen | ## Coordinates Screenshots are JPEGs scaled so the long edge is at most 1344 pixels. Tool coordinates are pixels in that image, measured from the top-left corner. The server converts them to the phone's native resolution. Action tools don't return a screenshot. Call `screenshot` after an action to see the result. ## Limits Each connection can make 300 requests per minute. Agents can only control phones that are online and active on your subscription. # Integrations Source: https://docs.tapkit.ai/integrations/overview Use TapKit from Claude, Codex, and any MCP client Every integration connects to the same hosted MCP server, `https://mcp.tapkit.ai/mcp`, and signs in with your TapKit account in the browser. The plugins for Claude and Codex also install [skills](/integrations/skills) that teach the agent how to navigate iOS. All integrations need the [TapKit Mac app](/setup) running with at least one connected, active iPhone. Plugin for Claude in the terminal. Plugin for Claude Chat and Cowork. Plugin for Codex in the terminal. Plugin for the Codex desktop app. Cursor, your own agent, or anything else that speaks MCP. iOS navigation know-how for agents without a TapKit plugin. To control phones from your own code without an agent framework, use the [REST API](/api-reference/introduction). # Skills Source: https://docs.tapkit.ai/integrations/skills Teach agents how to use TapKit and navigate iOS Skills are Markdown instructions that an agent loads when it needs them. They follow the open [Agent Skills](https://agentskills.io) standard. TapKit's skills teach an agent how to control an iPhone through TapKit and where to find things in iOS and Apple's apps. The skills' source is [on GitHub](https://github.com/jootsing-research/skills). The [Claude](/integrations/claude-code) and [Codex](/integrations/codex-cli) plugins include these skills. Install them separately only for other agents. ## Install ```bash theme={null} npx skills add jootsing-research/skills ``` Choose your agent when prompted. Skills don't give an agent access to your phone, so connect the agent to the [MCP server](/integrations/mcp) too. ## Available skills The core `tapkit` skill teaches an agent how to use TapKit's tools. The rest include a few skills for getting around iOS, such as finding apps and editing text, and several skills for specific Apple apps. # Mac app Source: https://docs.tapkit.ai/mac-app The app that connects your phones to TapKit The TapKit Mac app connects your iPhones to your TapKit account. Once a phone is connected, the built-in agent, Claude, Codex, the API, and any other MCP client can use it. TapKit can only see or control a phone while the app is open and signed in. TapKit Mac app with a connected iPhone on the left and the agent chat on the right ## Connected phones The main window shows the live screen of every iPhone connected to this Mac. To add a phone, plug it in. It goes through the same trust, screen, and Bluetooth checks as the first one. See [Setup](/setup#adding-more-phones). Each phone has to stay plugged in, unlocked, and paired with the Mac over Bluetooth. If a phone isn't ready, the app tells you why and what to do. ## Gestures and device controls You can control a phone by hand from the Mac app. Pick a gesture and click on the phone's screen. The gestures are tap, double tap, triple tap, tap and hold, flick, drag, and hold and drag. **Live** lets you click and drag on the screen like a finger. **Home** goes to the Home Screen. Use manual control to test the connection, set up a phone before a task, or take over while an agent is working. Your Mac's keyboard doesn't type on the phone. ## Agent chat The built-in agent lets you try TapKit without setting up another tool. Open a phone's chat and type a task: > Add eggs to my Groceries list in Reminders The agent looks at the screen, acts, and repeats until the task is done or it needs your input. Each step shows on the phone and in the chat, and you can stop the agent at any time. The agent can use any connected phone, and asks which one if your task doesn't say. TapKit doesn't save chats when you quit. ## Connection status When a phone isn't ready, first check that TapKit is open and signed in and that the iPhone is plugged in and unlocked. The Mac app shows a message for the phone saying what's wrong, such as asking you to tap **Trust** on the iPhone or reconnect Bluetooth. If agents still can't use the phone, check that it's active on your subscription in the [web app](/web-app#phones). [Setup troubleshooting](/setup#troubleshooting) covers specific problems. ## Settings Most settings are behind the **Account** button in the toolbar. There you can rename a phone, which changes the name agents see. You can also fix Camera or Bluetooth access, copy the MCP server URL to [connect another AI tool](/integrations/overview), manage your subscription, add phones to it, and sign out. If a phone gets stuck in a state you can't fix, choose **TapKit > Settings...** (⌘,) and click **Run Setup Again** to go through setup from the start. TapKit updates itself. Choose **TapKit > Check for Updates...** to check now. # Quickstart Source: https://docs.tapkit.ai/quickstart Connect an iPhone and run your first task ## What you need You need a Mac running macOS 14.6 or later, an iPhone, and a USB data cable. ## 1. Install TapKit and connect your iPhone Download TapKit, drag it into **Applications**, and open it. The app walks you through signing in, allowing Camera and Bluetooth access, trusting the Mac on your iPhone, and pairing over Bluetooth. Each setup step, and what to do if one fails. ## 2. Run a task in the Mac app Open the chat for your phone in the Mac app and type a task in the **Do anything** box: > Open the Clock app and start a 2 minute timer The agent takes screenshots, taps, and types on the phone while you watch. For more tasks to try, see [Examples](/examples). ## 3. Connect your own AI tools Install the TapKit plugin for Claude or Codex, or add the TapKit MCP server to any MCP client. Claude Code, the Claude app, Codex, and other MCP clients. Control phones from your own code. # Security and privacy Source: https://docs.tapkit.ai/security What TapKit can access and where your data goes ## What's on the iPhone TapKit installs nothing on the iPhone and doesn't need a jailbreak or developer mode. The Mac app can only reach a phone that is plugged into the Mac, trusts it, and is paired with it over Bluetooth. TapKit can't get past the passcode, Face ID, or anything else that would stop a person holding the phone. To cut off TapKit, unplug the phone, quit the Mac app, or forget the Mac in **Settings > Bluetooth**. ## Mac permissions | Permission | Used for | Not used for | | ---------- | ---------------------------------------------- | -------------------------- | | Camera | Seeing the iPhone's screen | Your Mac's webcam | | Bluetooth | Pairing with the iPhone and sending it actions | Any other Bluetooth device | ## Where screenshots and actions go **Built-in agent.** The Mac app captures screenshots and sends them through TapKit's servers to a hosted language model, which picks the next action. The Mac app sends actions straight to the phone. **MCP and REST API.** Your agent's commands go through TapKit's servers to your Mac. Screenshots come back the same way, and TapKit stores them. Your agent's provider, such as Anthropic or OpenAI, receives every screenshot your agent requests. **Live streaming.** When you watch a phone in the web app, Agora streams its screen to your browser. The Mac app shows each phone's screen on the Mac. It only sends the screen elsewhere when an agent takes a screenshot or someone opens a live stream. ## Access control The Mac app signs in through tapkit.ai and keeps its session in the macOS Keychain. MCP clients sign in with OAuth, and you approve each one on a consent screen. Access tokens expire after an hour, and clients refresh them automatically. The REST API uses API keys from the [web app](/web-app#api-keys). TapKit stores only a hash of each key, and a revoked key stops working immediately. Everyone in your organization can use its phones. ## Agent safety TapKit's skills tell agents to check typed text and stop before submitting it unless you've asked them to. They also tell agents not to type passwords you haven't given them. These rules reduce risk but don't remove it, because an agent with your phone can do anything you can. Use a phone and accounts you're comfortable handing to an agent. ## Legal Read the [Privacy Policy](https://tapkit.ai/privacy), [Terms of Service](https://tapkit.ai/terms), and [list of subprocessors](https://tapkit.ai/subprocessors). Report security issues to [security@tapkit.ai](mailto:security@tapkit.ai). # Setup Source: https://docs.tapkit.ai/setup Install the Mac app and connect an iPhone The TapKit Mac app walks you through setup. This page covers the same steps and what to do when one fails. ## Requirements You need a Mac running macOS 14.6 or later, an iPhone, and a USB data cable. The iPhone stays plugged into the Mac while TapKit uses it. ## 1. Install Download TapKit.dmg, open it, and drag **TapKit** into **Applications**. Then open TapKit from Applications. TapKit updates itself. To check for an update now, choose **TapKit > Check for Updates...**. ## 2. Sign in Click **Log in with browser**. TapKit opens tapkit.ai in your browser. Sign in with Google, then click **Open the desktop app**. The Mac app continues once you're signed in. ## 3. Allow Camera and Bluetooth TapKit needs two macOS permissions. [Security and privacy](/security#mac-permissions) explains how it uses them. | Permission | Button | Why | | ---------- | ------------------- | ------------------------------------------------------------------------- | | Camera | **Enable Camera** | Lets TapKit see the iPhone's screen. TapKit never uses your Mac's webcam. | | Bluetooth | **Allow Bluetooth** | Lets TapKit pair with the iPhone and control it. | Click each button and choose **Allow** when macOS asks. If you denied a permission earlier, the button opens System Settings instead. Turn on TapKit under **Privacy & Security > Camera** or **Privacy & Security > Bluetooth**. ## 4. Connect your iPhone Plug the iPhone into the Mac and unlock it. Select it under **Connected iPhones** and click **Continue**. If the iPhone asks whether to trust this computer, tap **Trust** and enter your passcode. TapKit then checks that it can see the phone's screen. Keep the phone plugged in and unlocked during this step. TapKit may put the phone to sleep for a moment and ask you to unlock it again. If TapKit still can't see the screen, it asks to restart the phone. Click **Restart iPhone**, then unlock the phone when it comes back on. ## 5. Pair over Bluetooth TapKit turns on AssistiveTouch on the iPhone for you. Then, on the iPhone, open **Settings**, tap **Bluetooth**, and tap your Mac's name. The Mac app moves on as soon as the phone connects. If your Mac's name doesn't appear, go back to Settings and tap **Bluetooth** again. ## 6. Subscribe Click **Start subscription** to check out in your browser, or **Explore TapKit first** to skip this step. Agents can only control phones that are active on a subscription. You can subscribe or add phones later from **Account > Billing** in the Mac app or from the [web app](/web-app#billing). When you see **Your agents have an iPhone now.**, click **Start using TapKit**. ## Adding more phones Plug in another iPhone. It appears next to your other phones in the Mac app and goes through the same trust, screen, and Bluetooth steps. Each phone takes one phone slot on your subscription. To run the whole setup again, choose **TapKit > Settings...** (⌘,) and click **Run Setup Again** on the **General** tab. ## Troubleshooting Unlock the iPhone and try a different cable or USB port. Some cables only charge. Unplug and reconnect, and tap **Trust** if the iPhone asks. TapKit can't unlock a phone, so the phone has to stay unlocked. Set **Settings > Display & Brightness > Auto-Lock** to **Never** to stop it from locking between tasks. Keep the phone plugged in and unlocked. If TapKit offers to restart the phone, let it. If that doesn't work, click **Try Again**, or unplug the phone, restart it yourself, and plug it back in. Check that Bluetooth is on for both devices and that the Mac app is still on the pairing step. Leave **Settings > Bluetooth** and open it again to refresh the list. Check that AssistiveTouch is on in **Settings > Accessibility > Touch > AssistiveTouch**. If it's on and taps still fail, open the phone's **More** menu in the Mac app and choose **Reset AssistiveTouch**. Open **System Settings > Privacy & Security**, choose **Camera** or **Bluetooth**, and turn on TapKit. Then quit and reopen TapKit. Still stuck? Email [support@tapkit.ai](mailto:support@tapkit.ai). # Web app Source: https://docs.tapkit.ai/web-app Manage phones, API keys, your team, and billing at tapkit.ai Use the [TapKit web app](https://tapkit.ai/dashboard) to manage your organization. Sign in with the same account you use in the Mac app. TapKit web app showing a phone's live stream ## Phones The Phones page lists every phone your organization has connected. For each phone it shows the status, the Mac it's connected to, and whether it's active. A phone's status is **Online** when it's connected and selected on its Mac, **Available** when it's connected to a Mac but not selected, and **Offline** otherwise. Agents can only control active phones. Your plan sets how many phones can be active at once. Click **Activate** or **Deactivate** to choose which ones. To rename a phone, click the pencil next to its name. Agents see this name. To remove a phone you no longer use, click **Edit**. ### Live stream Click **View Stream** to watch a phone's screen in real time and tap, flick, and drag on it from your browser. The phone's Mac must be online, and each Mac can stream one phone at a time. ## API keys API keys authenticate requests to the [REST API](/api-reference/introduction). To create a key, click **Create API Key** and give it a name. Copy the key right away. It starts with `tk_`, and you can't view it again after you close the dialog. The list shows each key's prefix, when it was created, and when it was last used. Click **Revoke** to disable a key immediately. ## Sessions The Sessions page shows how much streaming and viewing time your organization has used this billing period. Its history lists each live stream with its phone, start time, length, and viewers. ## Team Invite people to your organization by email as a **Member** or **Admin**. Admins can remove members and revoke pending invitations. Everyone in the organization shares its phones and API keys. ## Settings Set your display name, which other people see when you watch a stream, and your organization's name. ## Billing You pay for your subscription per phone. Subscribe or change how many phones you pay for on the Billing page. Added phones are available immediately, and you pay a prorated amount for the rest of the billing period. Removed phones stay active until the period ends. You can choose which phones to deactivate then, or TapKit deactivates the oldest ones. Click **Manage Payment & Invoices** to update your card, download invoices, or cancel in Stripe.