Companion for iPhone
Pair your iPhone with your Mac over an end-to-end-encrypted connection to watch agents, answer their questions, review diffs, merge PRs, and start tasks from anywhere.
Agents work for a long time and then stop, waiting on one word from you. Companion is the iPhone app that closes that loop: it pairs with your Mac, shows you every agent, and lets you answer without going back to your desk.
The phone talks to your Mac over an end-to-end-encrypted connection on your LAN or tailnet. When neither reaches it — a phone on cellular, a Mac behind NAT — an optional relay carries the connection without being able to read it. The feature is off until you turn it on, and the relay is a separate switch.
Turn it on and pair#
The iPhone app is in public beta on TestFlight and needs iOS 18 or later. On the Mac, open Settings → Mobile App: the iPhone App row has a Get It on TestFlight link, and the QR button beside it shows a code to scan with your iPhone's camera.
- In Settings → Mobile App, turn on Enable connections from your phone.
- Under Devices, click +, or Pair a Device… if nothing is paired yet. The Pair Your Phone sheet shows a QR code.
- In the iPhone app, open the Settings tab, tap Pair a Mac, and scan the code. Paste Link takes the link from the sheet's Copy Link instead.
The Mac appears in the app, and the device appears in the Mac's Devices list.
The QR code carries the Mac's name, its reachable addresses, and its public key — never an access token. A payload that tries to smuggle one is rejected outright. It also carries a single-use invite, so a phone without an Agentastic account can pair; the invite lasts ten minutes, and the sheet shows when it expires. When the Mac is signed in to an Agentastic account, the code offers that identity too, and the phone picks.
From a device's tile you can Revoke Access — it keeps the entry but cuts it off — or Remove it entirely, after which it has to pair again before it can connect.
What you can do from the phone#
The app has three tabs: Agents for the fleet, Inbox for what's waiting on you, and Settings, where you pair a Mac.
Watch the fleet#
Every agent across every workspace — terminal agents and Chat sessions alike — grouped by repository and worktree. The chips above the list filter by what an agent needs from you, each with its live count:
| Filter | Shows |
|---|---|
| All Agents | Everything the Mac is running |
| Needs You | Agents blocked on a question or a permission request |
| Working | Agents currently running |
| In Review | Agents finished with changes waiting |
Each worktree is one compact row: its name, then its branch, lines added and removed, and its pull request's number and CI result, with the most urgent agent inside shown at the right edge. Tap the row to open it and see its agents and terminals, plus shortcuts to its Changes, its Pull Request, a new Task, and a new Terminal; long-press it for the same actions without opening it. While you search or filter, the worktrees that match open by themselves, so the agent that matched is in view. Tap a repository's name to fold it away.
Rows are sorted by urgency — errors first, then agents waiting on you, then review-ready, then running — so the top of the list is always the thing to look at.
The menu at the top of Agents offers the same arrangements as the Mac's sidebar:
| Arrangement | Shows |
|---|---|
| Group by Repository | The default: a section per repository, ordered by urgency as above |
| Sort by Recent Activity | One list across repositories under Pinned, Today, Last 7 Days, Last 30 Days, and Backlog. Within each, agents waiting on you come first, then the most recent activity |
| Sort by Creation Date | The same headings by when the worktree was created, newest first. Activity never moves a row |
In the sorted arrangements, each row names its repository on the second line.
To open an agent straight from a folded row, tap its face at the right edge. When a row holds several agents, the face shows, and opens, the one that most needs you. Tapping anywhere else on the row unfolds it.
The list shows worktrees with something going on; Show → All Worktrees lists every one. Sessions started without a project are grouped under a single Sessions row, titled as they are in the Mac's sidebar. The list stays live: an agent started on the Mac, or from the phone, shows up within a couple of seconds.
Answer, steer, interrupt#
Open an agent to read its transcript. An agent that runs in a terminal opens on its terminal instead; a button in the toolbar switches between the terminal and the transcript. To archive or delete an agent, swipe its row left in Agents; a full swipe archives. You can send a message, answer a question, respond to a permission request, or interrupt the current turn, whether the agent runs in a terminal or in Chat. It is the same live session the Mac is driving; there's no separate phone copy to reconcile.
When an agent in Chat stops to ask before running a command, changing files, or anything else it needs your OK for, a card above the composer shows what it asked, with the same choices the Mac shows, in the agent's own words: Allow once, Allow for this session, and Deny for Codex, for instance, or Always Allow, Allow, and Reject for some other agents. Every way to allow is green and every way to refuse is red. The card is there even if your phone was locked when the agent asked and you opened the app from the notification. A question shows the answers the agent suggested and a field for your own; several questions come one at a time. If the agent opened on its terminal, a bar above the terminal says what it's waiting on, and Answer takes you to the card.
Follow-ups go in a roomy card at the bottom of the transcript, with the send button inside it. Drag the handle on top of the card up for more room to write, and back down when you're done. To say a follow-up instead of typing it, tap the microphone beside the send button, talk, and tap the red stop button. It works the way it does in New Task: what you said goes where the cursor is, a level meter shows the phone is listening, and the send button waits until you stop. For an agent in Chat, the button in the card's corner shows the model and thinking level the next turn runs on. Tap it to pick another, from the same list the Mac's Chat composer offers. The pick goes out with your next message and sticks for the turns after it, exactly as if you had changed it on the Mac. An agent the Mac shows as a terminal keeps the model its terminal picked.
Beside the model, a second button sets how the agent's actions are approved, with the presets the Mac's Chat composer offers for it: for Claude, Plan, Ask every time, Auto, and Full access. Unlike a model, a preset applies the moment you pick it, and switching to Full access also approves a request the agent is already waiting on, as it does on the Mac.
A message you send gets there even if you leave the app right after, or the phone is between connections: it shows as Sending… until the Mac takes it, goes out again when the phone reconnects, and reaches the agent once.
An agent you've opened before, or one that posted while the app was connected, opens straight away with what the phone already has and catches up from the Mac in the background. Any other agent shows a spinner until its messages arrive, labeled Connecting… while the phone is still reaching your Mac. If they can't be loaded, the transcript says so, with a Retry button. If the connection drops, an open transcript or terminal picks up again on its own once the phone reconnects. A single very large tool result is shortened on the phone; the full output stays on the Mac.
Replies are formatted as they are on the Mac — headings, lists, tables, and code blocks with syntax highlighting and a copy button. Long-press a reply to copy it. An image in a reply shows as its file name rather than loading, since an agent's image paths point at files on your Mac.
The Inbox#
Approvals, questions, and finished runs collect in the Inbox tab, and its badge counts what's waiting. Swipe a row to Dismiss it, or tap Clear to empty the Inbox.
A real terminal, not a screenshot of one#
Terminal output is rendered through an actual VT parser on the phone — cursor positioning, colors, redraws. A TUI agent that repaints its screen looks right, instead of degrading into thousands of lines of escape-code soup the way a plain text tail does.
Type into the field under the terminal and press Return to send the line; the keyboard stays up for the next one, and Return in an empty field sends a bare Return. Tap ••• for a tray of keys the keyboard lacks: show or hide the keyboard, esc, tab, ^C, ^D, ^Z, the arrow keys, and ⏎. With the tray, you can answer an agent's menu with the keyboard hidden — ↓ ↓ ⏎. The tray stays open until you tap ••• again, and the phone remembers how you left it.
To work in a shell of your own, open a worktree and tap Terminal, or long-press it and choose New Terminal Here. The Mac adds a terminal tab to that worktree in the background, running the Startup Command from Settings → Terminal if you set one, and the phone opens it ready for typing. The phone chooses only where the terminal opens, never what it starts with. If the Mac can't open one, Couldn't Open Terminal says why.
Review the diff#
See what a worktree changed, so "In Review" is something you can actually act on from a phone rather than a status you note for later. Files changed is one scrolling page: every file under a header that stays pinned while you read it, with line numbers, syntax highlighting, and a marker where unchanged lines are skipped.
All Changes shows everything the branch did against its base — committed work included, matching the counts on the worktree's row — and Uncommitted narrows it to what isn't committed yet. Remote worktrees show their uncommitted changes. Tick a file's circle to mark it viewed and fold it away; the mark sticks until the file changes again. The list button jumps straight to a file, and the ⋯ menu wraps long lines, folds or unfolds every file, and refreshes.
Check a pull request#
When a worktree's branch has a pull request, its row shows the PR's number and CI result. Open it for the PR page: its state, title, and size; whether it is approved, waiting for review, or has changes requested; its checks, with each failing one listed; who is reviewing; merge conflicts; and the description, rendered. Files changed opens the PR's own diff, and the link button opens it in the browser.
Full detail comes from GitHub, through the account connected on the Mac. For other hosts the page shows the state and check results the Mac already tracks.
While the page is on screen it keeps itself current: every 15 seconds while checks run, every few seconds while GitHub works out whether the branch can merge after a push, and once a minute after that. The status card says when it last reached GitHub, and each refresh also updates the worktree's row and the Mac's sidebar badge. Tap a check to open its page on GitHub, logs included.
Merge a pull request#
An open GitHub pull request shows Slide to merge whenever GitHub would accept the merge, colored by CI: green when every check passed, orange while checks run, red when some failed, and blue when none are reported. The line under it says which, so you know what you're agreeing to. Drag the arrow to the right and release to merge; a drag you don't finish springs back, and VoiceOver offers a Merge or Cancel confirmation that names the CI state too. When the repository allows more than one merge method, choose one from the menu above the slider.
When GitHub or the Mac would refuse — merge conflicts, a branch that is behind, branch rules, a draft, requested changes, or no push access — the slider locks and says why. Checking mergeability… means GitHub is still testing the merge after a push; the page checks again within seconds.
Before it merges, the Mac reads the pull request again. If new commits have landed, or CI got worse since the page showed it — a check that failed after you slid on orange, say — the Mac refuses, and the page refreshes so you can look again. Merging needs Agentastic.dev 0.13.2 or later on the Mac; with an older Mac the slider doesn't appear.
Start a task#
Tap + in the toolbar, or the Plan, ask, build… bar at the bottom of the list, to open New Task; the + beside a repository's name opens it with that repository chosen. Describe the task, optionally name it, and pick the repository, the agent, and a Mode: Agent, Agent (Auto-Approve), or Plan.
The sheet opens on the choices the Mac last sent for that repository, so the agent list is there at once, and checks the Mac for changes while you type — a small spinner beside Agent shows the check running. Anything you pick in the meantime is kept.
The sheet remembers what you started your last task with, so a routine task is a description and Start. Opened from the bottom bar, it picks the repository you last started a task in. The agent defaults to the one already working in the worktree, then to the one you last started from the phone in that repository, with the model, thinking level, mode, placement, base branch, and label you used. In a repository you haven't started a task in yet, it uses the agent, model, thinking level, mode, and placement from your last task on that Mac. Base branches and labels belong to one repository, so they don't carry over. Otherwise it uses the Mac's own choice. A remembered choice the Mac no longer offers falls back to the Mac's default, and nothing is remembered until you tap Start. Start doesn't wait for the check: the Mac checks every choice when the task starts and says if one is no longer available.
To show the agent a screenshot or photo, tap + at the bottom left of the task description and choose Attach an Image. A task takes up to eight images. Each one is shrunk on the phone to fit, uploads while you finish the sheet, and reaches the agent the same way as an image pasted into a task on the Mac. A failed upload stays on its thumbnail; tap it to try again. Start waits until every image has uploaded. The + appears only when the Mac supports attachments.
To say the task instead of typing it, tap the microphone at the bottom right of the task description, talk, and tap the red stop button. What you said goes where the cursor is, ready to edit — or delete — before Start; nothing is written while you talk, and a level meter between + and the stop button shows the phone is listening. A spinner takes its place while dictation starts and while it transcribes. Start waits until you stop. The phone does the transcribing, in the keyboard's language, and on iOS 26 the audio never leaves it. The first time, iOS asks for the microphone — and, before iOS 26, for speech recognition — and may download its speech model once, showing the progress in the same place.
The name also names the new workspace and its branch, so spaces and other characters a branch can't contain become dashes: Fix login bug! becomes Fix-login-bug. Without a name, or with nothing usable in it, the Mac picks one.
After choosing an agent, tap Model to search the choices available on the Mac. Mac Default uses the model that agent would choose there. Agentastic also shows each model's provider, so models with the same name remain distinct.
Run In chooses a new Workspace with its own branch, This Workspace, or a container or cloud machine where the repository offers one. A new workspace also takes a Base Branch, which defaults to the one you last used in that repository and otherwise to its main branch, and an optional Label. Whether the branch starts from origin follows the Mac's Start from origin setting under Settings → Worktrees, and the sheet's footer says which way it points.
The branch picker honors the repository and global default branch preferences configured on the Mac. If the Mac doesn't provide an available default, including when connected to an older host, Companion prefers main, then master, before the current branch. You can choose another branch before starting.
To put another agent to work in a worktree you already have, open the worktree and tap Task, or long-press it and choose New Task Here. The agent runs there, and no new branch is created.
Starting a task is the one action gated behind an explicit confirmation step: nothing runs until you tap Start. The sheet then closes at once, and the task waits under Starting at the top of the list until the Mac confirms it. You don't have to wait with it. Switch apps or lock the phone and it keeps the connection open in the background until the Mac answers; if the connection drops first, or iOS closes the app, the task goes out again as soon as the phone reconnects, and the Mac starts it only once. If it can't start, Couldn't Start Task says why, and if the agent is waiting at a login or trust screen on the Mac, Task May Need Attention says so. A task the phone can't get to the Mac for a day is given up on, with a notice to check the list.
With an older version of Agentastic.dev on the Mac, a launch whose answer was lost isn't sent again, because that Mac would start a second agent. Task May Need Attention says so instead: check the list before starting the task again, because the agent may already be running.
What the phone deliberately cannot do#
Every method a paired device may call is listed in a single authorization table, grouped into four tiers — read, steer, run, and merge. The Mac's request router denies anything not in that table, so a method nobody classified is refused by default rather than allowed by accident.
Destructive and exec-shaped operations are absent on purpose: removing a worktree, driving the browser, mutating scheduled tasks, packing a repository, importing a workspace. A stolen phone cannot delete your work. The only change the phone can make to a pull request is merging it, after the slide confirmation and the Mac's own checks; it can't comment on, close, or edit one.
Notifications that don't leak#
When an agent needs a permission, asks a question, finishes, errors, or posts a notification, the Mac forwards an encrypted push.
The payload is sealed with a per-device key derived at pairing time, and decrypted by the app's notification extension on arrival. The push relay and Apple's servers see only an opaque envelope addressed to a device id — never the agent's question, the repository name, or anything else.
Forwarding is strictly best-effort: a relay outage never blocks or slows an agent interaction on the Mac.
Catching up after being away#
The Mac keeps a durable journal of everything that happened, with monotonic sequence numbers from its database rather than an in-memory counter. When your phone wakes up, it asks for what it missed since its last cursor and gets exactly that — not a full resync.
The journal is scoped to the Mac's current launch, so if the app restarted, the phone can tell its cursor is meaningless and start clean rather than silently skipping or replaying events. Events are retained for seven days.
Reach your Mac from anywhere#
On the same network or a shared tailnet, the phone connects to your Mac directly. For everywhere else, turn on Reach this Mac from anywhere in Settings → Mobile App — it appears once connections are enabled. The Mac keeps an outbound connection parked at Agentastic's relay, and the phone falls back to it when nothing direct answers, so neither end ever accepts an inbound connection.
- The relay cannot read a session. Traffic passes through sealed to the key the phone pinned at pairing. The relay routes by the Mac's id and learns only that this Mac and this phone are talking.
- Direct still wins. The relay is last in the phone's dial order, so on a shared network you never pay for the round trip.
- It needs an Agentastic account. The Mac has to be signed in. Without an account, the phone reaches the Mac on your network and tailnet only.
- Phones you already paired pick it up the next time they connect on your network or tailnet. New pairing codes include the relay once it is connected.
- Reset Relay Access… revokes the relay credential in every pairing code this Mac has shown. Phones on your network or tailnet pick up the new one the next time they connect; a phone that only reaches this Mac through the relay has to pair again.
Connecting and reconnecting#
The app finds the paired Mac's current address on its own — LAN first, then a tailnet address if you run Tailscale, then the relay if you turned it on — and copes with DHCP changes and Mac restarts. Of the direct addresses, it tries the one that answered last time first. The connection pins the Mac's public key at pairing, so a device that answers on the right address but presents the wrong key is rejected.
Each connection negotiates fresh session keys; there is nothing long-lived on the wire to steal. Authentication must complete within ten seconds of connecting or the socket closes.
Related#
- Notifications — how the Mac decides an agent needs you
- Slack — the other way to answer an agent from your phone
- Remote Machines — agents that run somewhere other than your Mac