Approvals
An approval is a request an agent is waiting on, such as permission to run a command. Togo shows it on your phone as "needs you" and lets you answer without opening a terminal.
Where requests appear#
- In the app, in the session's chat, with the agent's own choices.
- On the Lock Screen, as a notification with Approve and Deny.
- In the session's Live Activity on the Lock Screen and in the Dynamic Island, with Approve and Deny when the request can be answered in place.
- On Apple Watch, with Approve and Deny.
While a session's Live Activity is running on your phone, its update takes the place of the notification for the same event. The update lights the screen and plays the alert sound, and you answer on the Live Activity card. When no Live Activity is running, the phone gets the notification. When a Live Activity has just started, the helper waits up to 10 seconds for it to register, and sends the notification if it hasn't.
Approve on the Lock Screen, in a notification or on the Live Activity card, needs the phone unlocked. To change that, turn on Approve without unlocking in the app's notification settings. Deny never needs the phone unlocked.
Notifications are sealed, so only your devices can open them. A Live Activity update also carries a few plain status fields, such as the session number and the agent's name, which the relay and Apple can read. Its alert text is fixed wording chosen from that status. The request and the command travel sealed. See Security model.
Phone and desk race#
The agent's own prompt stays live in its terminal the whole time. Whoever answers first wins.
When you answer on the phone, the helper captures the pane again and checks that the same prompt is still on screen before it types anything. If you already answered at the desk, nothing is typed and the phone is told so.
The helper replies with error -32006 (conflict) when an approval can no longer be answered. Its data gives the reason:
answered, withbyset todeskorphone.prompt_gone, when the prompt left the screen.expired, when the request is older than ten minutes.
How answers are typed#
A phone answer is one of approve, deny, or option:<n> for a numbered choice the agent shows. approve picks the agent's approve option and never an "always allow" option, so one tap cannot grant a lasting permission. deny picks the deny option, or sends Escape when there is none.
In the app, over SSH, an answer can also be text, for prompts that accept it.
From the Lock Screen and the Watch#
Answers from a notification, a Live Activity or the Watch travel through the relay. The device seals the answer and signs it with its approval key. The helper opens it and accepts it only when all of these hold:
- the signature matches a paired device that has not been revoked;
- the timestamp is within ten minutes;
- the request is still pending and has not been answered through the relay before;
- the decision is
approve,denyoroption:<n>, and the option is not "always allow".
Text and "always allow" are refused on this path. Use the app for those.
Which agents report requests#
Claude Code, Codex, Auggie, Droid, Copilot CLI, Amp and Cursor CLI report permission requests through hooks. For Amp, Togo installs a plugin. Install them with the helper:
$ togo hooks installAdd --agent with one of claude, codex, auggie, droid, copilot, amp or cursor to set up one agent. togo hooks status shows what is installed, and togo hooks uninstall removes it. --block also hooks the approval event, so the request waits for your answer from the phone before the agent shows its own prompt. Without it, the prompt stays at the desk and the phone races it.
Other agents report through their own server or files and need no setup. OpenCode, for example, reports through the HTTP API it serves for its session.
The screen watcher covers every agent. The helper reads the bottom of the tmux pane and recognises a prompt only when it has a clear structure, such as a numbered menu with a cursor or a yes/no token on the last line. It would rather miss a prompt than invent one.
Your own scripts can ask too:
$ togo ask "Deploy now?" --options yes,no