| 1 | # Remote access |
| 2 | |
| 3 | Connect a phone, browser, or another desktop app to T3 Code running on a different |
| 4 | machine. That machine must stay running and reachable while you work. |
| 5 | |
| 6 | ## T3 Connect |
| 7 | |
| 8 | T3 Connect makes an environment available to your other devices without setting |
| 9 | up router forwarding. In the desktop app on the host, open **Settings → |
| 10 | Connections**, sign in, and enable **T3 Connect** for that environment. |
| 11 | |
| 12 | For a command-line host, run: |
| 13 | |
| 14 | ```bash |
| 15 | t3 connect |
| 16 | ``` |
| 17 | |
| 18 | Follow the sign-in instructions. Setup offers a |
| 19 | [background service](./background-service.md); if you decline it, start the |
| 20 | server with `t3 serve`. Saving your sign-in alone does not make the machine |
| 21 | reachable. |
| 22 | |
| 23 | On your other device, sign in to the same T3 Connect account and choose the |
| 24 | environment. Over SSH, the CLI prints a browser link and a short code. Open the |
| 25 | link on any device, confirm the code matches, and approve. The CLI continues on |
| 26 | its own, so you do not need to forward an OAuth callback port. |
| 27 | |
| 28 | T3 Connect renews access credentials when needed without disconnecting a healthy |
| 29 | connection. Pull request diffs and provider settings keep working after the |
| 30 | previous credential expires. A failed renewal affects that request; it does not |
| 31 | disconnect an otherwise healthy conversation. |
| 32 | |
| 33 | ## Pair over a LAN or private network |
| 34 | |
| 35 | Use direct pairing when the other device can reach the host's network address. |
| 36 | |
| 37 | On a desktop host, open **Settings → Connections**, enable **Network access**, |
| 38 | then create a pairing link using an address the other device can reach. Changing |
| 39 | network access restarts the desktop app. You can turn it off in the same place. |
| 40 | |
| 41 | For a command-line host, replace `<private-ip>` with the host's LAN or tailnet |
| 42 | address: |
| 43 | |
| 44 | ```bash |
| 45 | t3 serve --host <private-ip> |
| 46 | ``` |
| 47 | |
| 48 | If a server is already running, generate a fresh link without restarting it: |
| 49 | |
| 50 | ```bash |
| 51 | t3 pair |
| 52 | ``` |
| 53 | |
| 54 | Scan the QR code on your phone or paste the pairing URL into **Add environment** |
| 55 | in the receiving app. Connection settings are under **Settings → Connections** |
| 56 | on web and desktop and **Settings → Environments** on mobile. A loopback address |
| 57 | such as `127.0.0.1` reaches only the device opening the link. |
| 58 | |
| 59 | Pairing authorizes that device for future connections. Use a fresh one-time link |
| 60 | for each new device; you do not need the original token to reconnect. Links |
| 61 | created in Settings can only be copied from the client that created them while |
| 62 | its Connections page stays open. If you leave or reload that page, create |
| 63 | another link to share. |
| 64 | |
| 65 | ### Reach one machine several ways |
| 66 | |
| 67 | A machine can have more than one route: LAN, Tailscale, another VPN, a public |
| 68 | URL, SSH, or T3 Connect. Tailscale shares its `100.64.0.0/10` address range with |
| 69 | other VPNs such as Cloudflare WARP, so an address in that range shows as VPN |
| 70 | unless the machine confirms it is on Tailscale. To add a route, choose **Add |
| 71 | route** in the machine's route list, or next to it in the T3 Connect list. |
| 72 | Pairing the same machine again over another address also adds a route instead |
| 73 | of a second machine. A new route is placed by speed, in that order, and you can |
| 74 | reorder routes at any time. |
| 75 | |
| 76 | While connected through T3 Connect or a paired address, T3 Code also learns the |
| 77 | machine's current LAN and Tailscale addresses and adds them as routes, so |
| 78 | pairing once through T3 Connect is enough to use the LAN at home. When the |
| 79 | machine's LAN address changes, for example after it joins another Wi-Fi network, |
| 80 | the learned route follows it. The machine must allow network access for its LAN |
| 81 | address to be learned. You can reorder a learned route, but not remove it; it |
| 82 | goes away with the route it was learned through, or when the machine stops |
| 83 | reporting that address. |
| 84 | |
| 85 | T3 Code connects over the first route that answers. Away from home, a LAN |
| 86 | address that does not answer is checked briefly and skipped. It is only tried |
| 87 | again, after the other routes, if none of them connect. While connected over a |
| 88 | later route, T3 Code checks the earlier ones when your network changes, when you |
| 89 | return to the app, and every minute, and moves back as soon as one works. |
| 90 | |
| 91 | On web and desktop, select the route count under the machine's name in |
| 92 | **Settings → Connections** to see its routes. Drag a route to change the order, |
| 93 | or remove it. On mobile, open the machine under **Settings → Environments** and |
| 94 | choose **Edit**. Signing out of T3 Connect removes only that route; a machine |
| 95 | you can still reach another way stays saved. |
| 96 | |
| 97 | Open **Permissions** next to **Routes** in web or desktop, or **Your permissions** |
| 98 | in the mobile route details, to see what your current connection can do on that |
| 99 | environment. For a remote environment, this is in its route details. Permissions |
| 100 | shown there apply only to the route marked **In use**; other routes are not |
| 101 | checked. Direct pairing and T3 Connect have separate sessions and may grant |
| 102 | different permissions. |
| 103 | |
| 104 | ### Balance new threads across machines |
| 105 | |
| 106 | Auto balance is off by default. On web and desktop, enable it in |
| 107 | **Settings → Connections → Load balancing** to automatically choose a machine for |
| 108 | new threads in projects grouped across connected environments. The section |
| 109 | appears once two or more machines are switched on. |
| 110 | Each machine starts at **Normal**. Choose **Prefer** to favor it when it has CPU and |
| 111 | memory available, **Less often** to reduce its share, or **Manual only** to exclude |
| 112 | it from automatic selection. These are preferences, not fixed traffic percentages. |
| 113 | Preferences are saved separately in each client. |
| 114 | |
| 115 | The composer checks eligible machines when choosing a draft's environment, then keeps |
| 116 | that choice stable. Choose **Auto balance** again to check current resources, or choose |
| 117 | a specific machine to override it. Choosing a branch or worktree also keeps the draft |
| 118 | on that machine. Existing threads stay where they started. If resource checks are |
| 119 | unavailable or all eligible machines are full, choose a machine manually to continue. |
| 120 | Mobile keeps its manual environment selection. |
| 121 | |
| 122 | ### Tailscale HTTPS |
| 123 | |
| 124 | Join both devices to the same tailnet. In the desktop app, enable **Tailscale |
| 125 | HTTPS** in **Settings → Connections**. Turn it off there to remove that route. |
| 126 | |
| 127 | To start a command-line server with Tailscale HTTPS: |
| 128 | |
| 129 | ```bash |
| 130 | t3 serve --tailscale-serve |
| 131 | ``` |
| 132 | |
| 133 | For an already-running server: |
| 134 | |
| 135 | ```bash |
| 136 | t3 pair --tailscale |
| 137 | ``` |
| 138 | |
| 139 | The pairing link uses an address such as `https://machine.tailnet.ts.net/`. |
| 140 | The mapping created by `pair --tailscale` persists across restarts. Remove its |
| 141 | default-port mapping with: |
| 142 | |
| 143 | ```bash |
| 144 | tailscale serve --https=443 off |
| 145 | ``` |
| 146 | |
| 147 | If that port is already in use, choose another with |
| 148 | `--tailscale-serve-port`. See `t3 pair --help` for other pairing options. |
| 149 | |
| 150 | ### Hosted web app |
| 151 | |
| 152 | [app.t3.codes](https://app.t3.codes) needs an HTTPS endpoint. It connects directly |
| 153 | to your server; a hosted pairing link does not make an unreachable backend |
| 154 | reachable or convert HTTP to HTTPS. |
| 155 | |
| 156 | For a plain HTTP LAN endpoint, use the direct pairing URL in a browser that can |
| 157 | open it, or pair from the desktop app. On mobile, an IP address entered without a |
| 158 | scheme uses HTTP, so include `https://` when your server uses HTTPS. |
| 159 | |
| 160 | ## Desktop-managed SSH |
| 161 | |
| 162 | In the desktop app, open **Settings → Connections → Add environment**, choose |
| 163 | **SSH**, and enter a host or SSH alias such as `user@example.com`. T3 Code starts |
| 164 | or reuses a server there and opens the port forward for you. Projects, provider |
| 165 | credentials, and agent work stay on the remote machine. |
| 166 | |
| 167 | The remote host must be Linux or an Apple Silicon Mac with `curl` or `wget`, |
| 168 | `tar`, `sha256sum` or `shasum`, and [provider setup](./install.md#providers). |
| 169 | The first launch downloads T3 Code's server to `~/.t3/runtime` on the host, so |
| 170 | it takes longer than later ones. |
| 171 | Provider CLIs must be on the `PATH` of a non-interactive login shell there; |
| 172 | check with: |
| 173 | |
| 174 | ```bash |
| 175 | ssh user@example.com 'sh -lc "command -v claude codex"' |
| 176 | ``` |
| 177 | |
| 178 | If SSH reconnecting fails after an app update, retry the launch once. Removing |
| 179 | the connection stops a server that T3 Code launched; a server that was already |
| 180 | running is left alone. |
| 181 | |
| 182 | For Antigravity's Google callback on a remote host, see |
| 183 | [remote sign-in](./providers-antigravity.md#sign-in-from-a-remote-device). |
| 184 | |
| 185 | ## Browser on a remote environment |
| 186 | |
| 187 | Browser tabs belong to the environment, so you and your agents see the same |
| 188 | tabs from any device. The desktop app shows its own environment's tabs |
| 189 | directly. Every other device, and the desktop app for other environments, |
| 190 | streams them from the host. Agents keep using them while no device is |
| 191 | connected, and `localhost` addresses reach servers on the host. |
| 192 | |
| 193 | The first tab downloads a headless Chrome, about 120 MB, into the T3 home. It |
| 194 | is the same browser [HTML renders](html-renders.md) use, so a host downloads it |
| 195 | only once. Some Linux hosts need [setup](#browser-host-setup) before it can |
| 196 | start. |
| 197 | |
| 198 | Agent tabs have separate storage and share a Chromium process. Take control before |
| 199 | typing into an agent's tab, then release control when you want the agent to |
| 200 | continue. Read-only connections can watch without changing the page. |
| 201 | |
| 202 | While you have control, the tab works with your device: text the page copies or |
| 203 | cuts goes to your clipboard, a file picker on the page opens your device's |
| 204 | picker, and a finished download is offered for you to save. Popups such as |
| 205 | sign-in windows open as their own tabs. Downloads stay on the host until the |
| 206 | tab closes. Audio does not play on your device. |
| 207 | |
| 208 | On a phone, tap the floating preview's corner dot to show its controls, then |
| 209 | **Pop into separate window** to keep watching in picture-in-picture over other |
| 210 | apps. |
| 211 | |
| 212 | ### Browser host setup |
| 213 | |
| 214 | macOS, Windows, and Linux desktops run the browser as is. Some Linux hosts need |
| 215 | one-time setup: Ubuntu 23.10 and later block the sandbox the browser runs in, |
| 216 | and minimal images and containers lack libraries it loads. When that happens, |
| 217 | the server says so at startup, and browser tabs and HTML previews show the |
| 218 | command to run on the host: |
| 219 | |
| 220 | ```sh |
| 221 | sudo t3 browser setup |
| 222 | ``` |
| 223 | |
| 224 | The server shows the exact line for how you started it, such as |
| 225 | `sudo npx t3 browser setup`, and keeps your `PATH` when Node is installed only |
| 226 | for your user. Where `t3` is not on your `PATH`, such as with only the |
| 227 | desktop app installed, it names the full path of the app's own `t3` instead. It allows Chrome's sandbox with an AppArmor profile and installs |
| 228 | any missing libraries with apt. It is safe to run again. Without `sudo`, it |
| 229 | only reports what it would change. |
| 230 | |
| 231 | The browser always runs in Chrome's sandbox. Where you cannot change the host, |
| 232 | set `T3CODE_SERVER_BROWSER_SANDBOX=0` for the environment to run without it. |
| 233 | |
| 234 | ## Connect an outside agent |
| 235 | |
| 236 | Claude Code, Codex, ChatGPT and other agents T3 Code did not start can drive |
| 237 | threads on an environment through its MCP server. See |
| 238 | [outside agents](./outside-agents.md) for setup. |
| 239 | |
| 240 | ## Manage or revoke access |
| 241 | |
| 242 | On the host, **Settings → Connections** lets authorized administrators create |
| 243 | pairing links and revoke client sessions. Revoking an unused link prevents new |
| 244 | pairings; revoke a device's session to remove its existing access. Command-line |
| 245 | management is available through `t3 auth --help`. |
| 246 | |
| 247 | A session with an open connection stays listed after its access credential |
| 248 | expires. |
| 249 | |
| 250 | To choose a token's permissions, pass `--scope` once for each scope you want: |
| 251 | |
| 252 | ```sh |
| 253 | npx t3 pair --scope orchestration:read --scope relay:read |
| 254 | ``` |
| 255 | |
| 256 | The selected scopes replace the default permissions. The same option works with |
| 257 | `npx t3 auth pairing create` and `npx t3 auth session issue`; each command's |
| 258 | `--help` lists the available scopes. Without `--scope`, pairing tokens retain |
| 259 | standard client permissions and issued bearer sessions retain administrative |
| 260 | permissions. |
| 261 | |
| 262 | To change an existing client's permissions, create a fresh pairing link with the |
| 263 | scopes it needs. In a browser opened directly on the environment, open that link |
| 264 | to replace the browser's current grant. For mobile or a saved remote environment |
| 265 | in web or desktop, use **Add Environment** with the fresh link or code; pairing |
| 266 | the same environment replaces its saved grant. Reconnecting alone does not change |
| 267 | permissions. |
| 268 | |
| 269 | Grouping checkouts does not combine their permissions. Shared project settings |
| 270 | require `orchestration:operate` on every member environment; actions on one |
| 271 | checkout use that checkout's permissions. |
| 272 | |
| 273 | `source-control:write` covers direct Git and pull request changes made from the |
| 274 | client: pushing, switching or creating branches, cloning, and removing |
| 275 | worktrees. It does not restrict what a task does. Starting a task in a new |
| 276 | worktree still creates that branch and worktree with `orchestration:operate`, |
| 277 | and the agent it runs can use Git however the environment allows. |
| 278 | |
| 279 | Settings changes, provider management, and environment maintenance can be granted |
| 280 | separately from access administration. New standard pairings include these |
| 281 | permissions. Existing clients can stay connected after an update, but newly separated |
| 282 | features may require pairing again with the permissions they need. Older clients |
| 283 | may show controls that the server denies. Create a fresh pairing link to change |
| 284 | a client's permissions. |
| 285 | |
| 286 | `filesystem:read` allows browsing host files, opening workspace files, and viewing |
| 287 | local changes. Add `filesystem:write` to allow editing files or saving plans to |
| 288 | the workspace. These scopes control direct file access from the client. |
| 289 | |
| 290 | To remove an environment from T3 Connect, open your account menu's **T3 Connect** |
| 291 | page, or **Settings → T3 Connect** on mobile, and choose **Deregister**. This |
| 292 | revokes its cloud access and frees its host space even when the environment is |
| 293 | offline or has been wiped. When T3 Connect rejects a host's link, the host |
| 294 | shows that it was removed from T3 Connect. To link it again, turn on |
| 295 | **T3 Connect** in **Settings → Connections** on a desktop host, or run |
| 296 | `t3 connect link` on a command-line host and then restart T3 Code there. A |
| 297 | command-line host that released its tunnel when it last stopped may link itself |
| 298 | again on its next start; run `t3 connect unlink` on that host to keep it off. |
| 299 | Removing an environment from a device's connection settings only forgets it on |
| 300 | that device; it stays registered to your account. |
| 301 | |
| 302 | When idle tunnel cleanup is enabled, T3 Connect removes a linked environment's |
| 303 | tunnel after it stays offline for several minutes. The environment stays linked |
| 304 | and keeps the same address. When the host starts again or wakes, T3 Connect |
| 305 | creates a replacement tunnel on its own. You do not need to pair again. Cleanup |
| 306 | usually runs five to ten minutes after the tunnel goes down. |
| 307 | |
| 308 | T3 Connect also removes the tunnel of an environment running an older version of |
| 309 | T3 Code once it has been offline for seven days. That environment shows a message |
| 310 | asking you to update. Start T3 Code on that computer and update it to the latest |
| 311 | version; it reconnects at the same address without pairing again. |
| 312 | |
| 313 | On a command-line host, `t3 connect unlink` disables exposure while retaining |
| 314 | your login; `t3 connect logout` also clears that login. Background-service |
| 315 | [removal](./background-service.md#manage-the-service) is separate. |
| 316 | |
| 317 | Treat pairing URLs and authorization codes as passwords. Do not include them in |
| 318 | screenshots, logs, or bug reports. |
| 319 | |
| 320 | ## T3 Connect troubleshooting |
| 321 | |
| 322 | Run `t3 connect status` on the host to inspect saved authorization and link |
| 323 | configuration. It is not a live reachability check. If the environment appears |
| 324 | offline, run `t3 service status` and read the displayed log. If it disappears |
| 325 | when SSH closes, see [background-service troubleshooting](./background-service.md#troubleshooting). |
| 326 | |
| 327 | | Error | Recovery | |
| 328 | | --------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------- | |
| 329 | | `environment_link_limit_exceeded` or managed tunnel limit | Deregister an unused environment, then restart T3 Code on the host. | |
| 330 | | `auth_invalid` or `invalid_bearer` | Run `t3 connect login`. If credentials were revoked, run `t3 connect logout`, then `t3 connect` again. Restart the server after signing in. | |
| 331 | | Expired or invalid link proof | Check the host's date and time, update T3 Code, then restart it. | |
| 332 | | HTTP 403 without a recognized error | Check relay access, proxies, and firewall rules. Keep any Cloudflare Ray ID for a bug report. | |
| 333 | | HTTP 408, 429, or 5xx | Check network and relay availability. Startup retries temporary failures for up to ten minutes. | |
| 334 | |
| 335 | After fixing a permanent rejection, restart the host's server. On Linux, use |
| 336 | `systemctl --user restart t3code.service` for the background service. For a |
| 337 | foreground server, stop it and run `t3 serve` again with your usual options. |
| 338 | Include the diagnostic message and trace ID when reporting a persistent failure. |
| 339 | |
| 340 | For a connection that still fails after linking, check the date and time on both |
| 341 | devices. For server version warnings, follow [Updating T3 Code](./updating.md). |
| 342 | |
| 343 | ## Using the Desktop App as a Remote Only |
| 344 | |
| 345 | If a computer should only drive work running elsewhere, turn off its local environment. In the |
| 346 | desktop app, open **Settings → Connections** and switch off **Local |
| 347 | environment**. T3 Code restarts without a local server: no local agents or terminals run, WSL |
| 348 | backends stay off, and other devices can no longer connect to this computer. Your projects, |
| 349 | history, and saved connections are kept, and you keep working through pairing, T3 Connect, or SSH. |
| 350 | |
| 351 | Switch **Local environment** back on in the same place to restart with your previous local |
| 352 | settings. |