Agents
Chat with the coding agents installed on your computer, answer their approvals and undo their changes from the phone.
The Agents tab works with the coding agents you already have on the computer. Link doesn't install them or hold their logins: it starts each one's own machine protocol inside the SSH connection, so API keys, transcripts and code stay where they are.
Supported agents
| Agent | Command Link runs | Notes |
|---|---|---|
| Claude Code | claude -p (stream-json) | Sessions from ~/.claude/projects; sessions open in a terminal show as live |
| Codex | codex app-server | Joins the computer's shared Codex server, so a thread is the same in the terminal and on the phone |
| OpenCode | opencode acp | Agent Client Protocol |
| Gemini CLI | gemini --experimental-acp | Agent Client Protocol |
| Pi | pi --mode rpc | One process per open session |
| Crush | crush server, through curl | Needs curl on the computer |
Link finds each CLI on your PATH, plus the usual places user installs go that SSH logins often miss: ~/.local/bin, ~/.bun/bin, ~/.opencode/bin, npm, pnpm, Volta, nvm, Homebrew and /usr/local/bin. If the app says an agent wasn't found, make sure its folder is on the PATH your login shell sets.
Sessions
Pick a computer in the header and the tab lists every agent's sessions together, newest first, with the ones running right now on top. Open one to read its history (newest first, older parts as you scroll up) and continue it, or start a New session in any project folder.
Sessions you started in a terminal show as In terminal. For Codex, the phone joins the very same thread. For Claude Code, sending from the phone continues the conversation in Link's own process, which the terminal doesn't see, unless the terminal session was started with Link's channel: then your message goes straight into it. See Claude in a terminal.
Agents that Link started stop when the phone's connection ends, so none is left waiting on an approval nobody can answer. Codex turns keep running on the shared server.
Approvals
When an agent asks before acting, the chat shows a card with the agent's own choices: Allow, Deny, and where the agent offers it, Always allow. Questions (Claude's AskUserQuestion, Codex's and Crush's question tools) become cards you answer in place, and Claude's plan mode shows the plan with Approve plan or Keep planning. A notification brings you back when an agent is waiting.
Link never approves anything by itself. Requests it can't show are refused, not allowed.
Permission modes
The chip in the composer sets how much an agent may do without asking. Modes that let it act without asking need a confirmation first.
| Agent | Modes |
|---|---|
| Claude Code | Ask, Accept edits, Auto (Claude approves what its classifier finds safe), Plan, Don't ask |
| Codex | Ask, Auto (no prompts inside the project, no network), Read only, Full access |
| OpenCode, Gemini CLI | The modes the agent itself lists: OpenCode's build and plan; Gemini's, including YOLO |
| Crush | Ask, Don't ask (Crush's own "skip permissions", which covers every Crush session in that folder) |
| Pi | None: Pi doesn't ask before using tools, unless an extension adds dialogs, which show as cards |
The mode you pick last is where new sessions start, until Link closes.
Undo a turn
Every message you send from Link is bracketed by two hidden git snapshots of the project, taken before and after the turn (under refs/link/checkpoints/, invisible to git log and your branches). The chat then shows what the turn changed, such as 3 files changed +40 −12. Open it to see each file's diff and choose Undo these changes, or redo them after an undo. This needs the project to be a git repository; snapshots never touch your index, branches or stash.
Steer or queue
While an agent works, Send adds your message to the running turn where the agent supports it (Claude Code, Codex, Pi). Elsewhere it waits in Link's queue and goes out when the turn ends.
Images
Attach images from the phone's photo picker; they're scaled down on the phone first. Agents and models that don't take images hide the button.