1# Remote access
2
3Connect a phone, browser, or another desktop app to T3 Code running on a different
4machine. That machine must stay running and reachable while you work.
5
6## T3 Connect
7
8T3 Connect makes an environment available to your other devices without setting
9up router forwarding. In the desktop app on the host, open **Settings →
10Sharing & access**, sign in, and enable **T3 Connect** for that environment.
11
12For a command-line host, run:
13
14```bash
15t3 up
16```
17
18It asks how your other devices reach the machine: T3 Connect, the local network,
19or both. Choose T3 Connect and follow the sign-in instructions. It then runs
20T3 Code as a [background service](./background-service.md).
21`t3 connect` is the same as `t3 up --connect`. Run `t3 up` again to change your
22choice, and `t3 status` to see it.
23
24Instead of the background service, you can keep the desktop app running with
25its local environment enabled. Closing the desktop app's last window stops its
26local server. Saving your sign-in alone does not start a server or make the
27machine reachable.
28
29On your other device, sign in to the same T3 Connect account and choose the
30environment. On the app.t3.codes home page with no computer added yet, signing
31in adds compatible computers linked to your account. Over SSH, the CLI prints a
32browser link and a short code. Open the link on any device, confirm the code
33matches, and approve. The CLI continues on its own, so you do not need to forward
34an OAuth callback port.
35
36T3 Connect renews access credentials when needed without disconnecting a healthy
37connection. Pull request diffs and provider settings keep working after the
38previous credential expires. A failed renewal affects that request; it does not
39disconnect an otherwise healthy conversation.
40
41### Scripts and agents
42
43`t3 up` asks nothing when you name a choice: `--connect`, `--lan`, or their
44`--no-` forms. Choices you do not name keep their settings, and `--yes` takes
45the defaults. Without a terminal:
46
47- T3 Connect sign-in prints a URL and a code. Approve it on any device.
48- A needed restart runs without asking, and stops running agent turns.
49- With nothing set up and no choice named, `t3 up` stops and names the flags.
50
51`t3 status --json` prints the settings. `t3 up --help` lists every flag with
52examples.
53
54### More machines with T3 Chat
55
56Each T3 Connect account can link up to 3 machines. Phones and browsers do not
57count. A paid T3 Chat plan raises the limit to 10 machines with Pro, or 100 with
58Premier.
59
60To link T3 Chat, open your account menu on the web or desktop app, go to
61**T3 Chat**, and select **Link T3 Chat**. Sign in to T3 Chat in the window that
62opens and approve. The new limit applies the next time you add a machine. If you
63cancel or downgrade T3 Chat, machines you already linked stay linked, but you
64cannot add more until you are under the limit again.
65
66## Pair over a LAN or private network
67
68Use direct pairing when the other device can reach the host's network address.
69
70On a desktop host, open **Settings → Sharing & access**, enable **Network access**,
71then create a pairing link using an address the other device can reach. Changing
72network access restarts the desktop app. You can turn it off in the same place.
73
74For a command-line host, choose the local network in `t3 up`, or run:
75
76```bash
77t3 up --lan
78```
79
80For a server in a terminal, run `t3 serve --lan`. Either way, T3 Code then
81accepts connections from your local network and tailnet, so a pairing code is
82all that keeps other devices on them out.
83
84If a server is already running, generate a fresh link without restarting it:
85
86```bash
87t3 pair
88```
89
90Scan the QR code on your phone or paste the pairing URL into **Add environment**
91in the receiving app. Connection settings are under **Settings → Environments**
92on web and desktop and **Settings → Environments** on mobile. A loopback address
93such as `127.0.0.1` reaches only the device opening the link.
94
95On a computer with the desktop app, you can open the printed `t3code://pair`
96app link instead. The desktop app asks you to confirm the server address, then
97adds it.
98
99If your HTTPS endpoint uses a certificate from your own certificate authority,
100install that CA on Android as a **CA certificate** in its security settings; the
101Android app then trusts it.
102
103Pairing authorizes that device for future connections. Use a fresh one-time link
104for each new device; you do not need the original token to reconnect. Links
105created in Settings can only be copied from the client that created them while
106its Sharing & access page stays open. If you leave or reload that page, create
107another link to share.
108
109### Reach one machine several ways
110
111A machine can have more than one route: LAN, Tailscale, another VPN, a public
112URL, SSH, or T3 Connect. Tailscale shares its `100.64.0.0/10` address range with
113other VPNs such as Cloudflare WARP, so an address in that range shows as VPN
114unless the machine confirms it is on Tailscale. To add a route, choose **Add
115route** in the machine's route list, or next to it in the T3 Connect list.
116A pairing link for a saved machine is refused when it comes from an address
117that machine does not have yet; add that address with **Add route** instead.
118Pairing again over an address the machine already has still works. A new route
119is placed by speed, in that order, and you can reorder routes at any time.
120
121While connected through T3 Connect or a paired address, T3 Code also learns the
122machine's current LAN and Tailscale addresses and adds them as routes, so
123pairing once through T3 Connect is enough to use the LAN at home. When the
124machine's LAN address changes, for example after it joins another Wi-Fi network,
125the learned route follows it. The machine must allow network access for its LAN
126address to be learned: **Network access** in the desktop app, or the
127[local network](./background-service.md#local-network-access) choice in `t3 up`.
128You can reorder a learned route, but not remove it; it
129goes away with the route it was learned through, or when the machine stops
130reporting that address.
131
132T3 Code connects over the first route that answers. Away from home, a LAN
133address that does not answer is checked briefly and skipped. It is only tried
134again, after the other routes, if none of them connect. While connected over a
135later route, T3 Code checks the earlier ones when your network changes, when you
136return to the app, and every minute, and moves back as soon as one works.
137
138On web and desktop, select the route count under the machine's name in
139**Settings → Environments** to see its routes. Drag a route to change the order,
140or remove it. On mobile, open the machine under **Settings → Environments** and
141choose **Edit**. Signing out of T3 Connect removes only that route; a machine
142you can still reach another way stays saved.
143
144Open **Permissions** next to **Routes** in web or desktop, or **Your permissions**
145in the mobile route details, to see what your current connection can do on that
146environment. For a remote environment, this is in its route details. Permissions
147shown there apply only to the route marked **In use**; other routes are not
148checked. Direct pairing and T3 Connect have separate sessions and may grant
149different permissions.
150
151### Balance new threads across machines
152
153Auto balance is off by default. On web and desktop, enable it in
154**Settings → Environments → Load balancing** to automatically choose a machine for
155new threads in projects grouped across connected environments. The section
156appears once two or more machines are switched on.
157Each machine starts at **Normal**. Choose **Prefer** to favor it when it has CPU and
158memory available, **Less often** to reduce its share, or **Manual only** to exclude
159it from automatic selection. These are preferences, not fixed traffic percentages.
160Preferences are saved separately in each client.
161
162The composer checks eligible machines when choosing a draft's environment, then keeps
163that choice stable. Choose **Auto balance** again to check current resources, or choose
164a specific machine to override it. Choosing a branch or worktree also keeps the draft
165on that machine. Existing threads stay where they started. If resource checks are
166unavailable or all eligible machines are full, choose a machine manually to continue.
167Mobile keeps its manual environment selection.
168
169### Tailscale HTTPS
170
171Join both devices to the same tailnet. In the desktop app, enable **Tailscale
172HTTPS** in **Settings → Sharing & access**. Turn it off there to remove that route.
173
174To start a command-line server with Tailscale HTTPS:
175
176```bash
177t3 serve --tailscale-serve
178```
179
180For an already-running server:
181
182```bash
183t3 pair --tailscale
184```
185
186The pairing link uses an address such as `https://machine.tailnet.ts.net/`.
187The mapping created by `pair --tailscale` persists across restarts. Remove its
188default-port mapping with:
189
190```bash
191tailscale serve --https=443 --set-path=/ off
192```
193
194If that port is already in use, choose another with
195`--tailscale-serve-port`. See `t3 pair --help` for other pairing options.
196
197### Hosted web app
198
199[app.t3.codes](https://app.t3.codes) needs an HTTPS endpoint. It connects directly
200to your server; a hosted pairing link does not make an unreachable backend
201reachable or convert HTTP to HTTPS.
202
203For a plain HTTP LAN endpoint, use the direct pairing URL in a browser that can
204open it, or pair from the desktop app. On mobile, an IP address entered without a
205scheme uses HTTP, so include `https://` when your server uses HTTPS.
206
207## Desktop-managed SSH
208
209In the desktop app, open **Settings → Environments → Add environment**, choose
210**SSH**, and enter a host or SSH alias such as `user@example.com`. T3 Code starts
211or reuses a server there and opens the port forward for you. Projects, provider
212credentials, and agent work stay on the remote machine.
213
214The remote host must be Linux or an Apple Silicon Mac with `curl` or `wget`,
215`tar`, `sha256sum` or `shasum`, and [provider setup](./install.md#providers).
216The first launch downloads T3 Code's server to `~/.t3/runtime` on the host, so
217it takes longer than later ones.
218Provider CLIs must be on the `PATH` of a non-interactive login shell there;
219check with:
220
221```bash
222ssh user@example.com 'sh -lc "command -v claude codex"'
223```
224
225If SSH reconnecting fails after an app update, retry the launch once. Removing
226the connection stops a server that T3 Code launched; a server that was already
227running is left alone.
228
229Each desktop app keeps one session on the host for its SSH connection and reuses
230it when it reconnects. Revoke sessions you no longer use in **Settings →
231Sharing & access** on the host, or on a headless host with `t3 auth session list` and
232`t3 auth session revoke <id>`. A desktop that can still sign in over SSH pairs
233again on its next connect.
234
235For Antigravity's Google callback on a remote host, see
236[remote sign-in](./providers-antigravity.md#sign-in-from-a-remote-device).
237
238## Browser on a remote environment
239
240Browser tabs belong to the environment, so you and your agents see the same
241tabs from any device. The desktop app shows its own environment's tabs
242directly. Every other device, and the desktop app for other environments,
243streams them from the host. Agents keep using them while no device is
244connected, and `localhost` addresses reach servers on the host.
245
246The first tab downloads a headless Chrome, about 120 MB, into the T3 home. It
247is the same browser [HTML renders](html-renders.md) use, so a host downloads it
248only once. Some Linux hosts need [setup](#browser-host-setup) before it can
249start.
250
251Agent tabs have separate storage and share a Chromium process. Take control before
252typing into an agent's tab, then release control when you want the agent to
253continue. Read-only connections can watch without changing the page.
254
255While you have control, the tab works with your device: text the page copies or
256cuts goes to your clipboard, a file picker on the page opens your device's
257picker, and a finished download is offered for you to save. Popups such as
258sign-in windows open as their own tabs. Downloads stay on the host until the
259tab closes. Audio does not play on your device.
260
261On a phone, tap the floating preview's corner dot to show its controls, then
262**Pop into separate window** to keep watching in picture-in-picture over other
263apps.
264
265### Local servers
266
267The browser lists ports held by processes your terminals and agents started.
268T3 Code reads which process holds each port and never connects to it, so a
269listed port opens as `http://localhost:<port>` and might not be a web page. For
270an HTTPS server or a specific path, set the **Preview URL** on the project
271script that starts it; T3 Code checks that address and opens it as written.
272
273To stop listing ports, set `T3CODE_PORT_DISCOVERY=0` in the environment that
274starts the T3 Code server, such as
275[`service.env`](./background-service.md#configure-the-service-environment) for
276the background service, and restart it. Script preview URLs still appear.
277
278### Browser host setup
279
280macOS, Windows, and Linux desktops run the browser as is. Some Linux hosts need
281one-time setup: Ubuntu 23.10 and later block the sandbox the browser runs in,
282and minimal images and containers lack libraries it loads. When that happens,
283the server says so at startup, and browser tabs and HTML previews show the
284command to run on the host:
285
286```sh
287sudo t3 browser setup
288```
289
290The server shows the exact line for how you started it, and keeps your `PATH`
291when you started it with `npx` and Node is installed only for your user. Where `t3` is not on your `PATH`, such as with only the
292desktop 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
293any missing libraries and system fonts with apt; pages that load without text
294can mean the host has no fonts. It is safe to run again. Without `sudo`, it only
295reports what it would change.
296
297The browser runs in Chrome's sandbox by default. Chrome cannot start that sandbox
298as root. If your T3 server runs as root, run it as a nonroot user to keep
299sandboxing enabled. `t3 browser setup` does not fix this root restriction.
300
301If you need to run as root, or cannot enable the sandbox on your host, set
302`T3CODE_SERVER_BROWSER_SANDBOX=0` in the **T3 server's environment** and restart
303the server. This disables Chrome's sandbox. For a manual launch:
304
305```sh
306T3CODE_SERVER_BROWSER_SANDBOX=0 t3 serve
307```
308
309For a systemd service, add `Environment=T3CODE_SERVER_BROWSER_SANDBOX=0` under
310`[Service]` in its configuration, run `sudo systemctl daemon-reload`, then restart
311your T3 service. Setting the variable in an agent's terminal does not change the
312environment of an already running T3 server.
313
314## Connect an outside agent
315
316Claude Code, Codex, ChatGPT and other agents T3 Code did not start can drive
317threads on an environment through its MCP server. See
318[outside agents](./outside-agents.md) for setup.
319
320## Link another environment
321
322Link two machines, such as your laptop and a VPS, and agents on one can work on
323the other: launch, message, wait on and stop its threads, answer their
324questions, and manage its queues, projects and scheduled tasks.
325
326Linked environments is a beta. Turn it on for both machines in **Settings →
327Labs**; on mobile, **Settings → Labs** lists each connected machine. While it is
328off on either machine, agents start nothing over a link between them. A task
329already running on the other machine still finishes, and if that machine has it
330off, its result arrives once it is back on.
331
332On the machine you will work from, open **Settings → Environments → Linked environments**,
333choose **Link**, and pick the other machine or enter its address. The list
334holds the machines this app knows and those on your T3 Connect account. If this
335app has an address for that machine and is connected to it with a session that
336manages access there, it makes the pairing code itself; otherwise paste one
337from that machine's **Settings → Sharing & access**. An address you type always
338needs a pasted code. From a terminal, use
339`t3 environment link <address> --pairing-code <code> --access <mode>`.
340
341You can also ask an agent to link a machine by name, such as "delegate this to
342my vps". It shows a card in the thread where you pick the machine the same way
343and the access, then approve. An address the agent gives that this app does
344not know for one of your machines also needs a pasted code. Paste one only for
345an address you trust: the code is sent there.
346
347- The access you pick is the most agents from this machine may do there. An
348 agent also never gets more there than its own mode here.
349- Threads a link starts are marked **From** and this machine's name there.
350- A full-access link works there like that machine's own agents. Below full
351 access, the link's agents can change only threads it started, not that
352 machine's own threads, projects or settings, and they skip its project setup
353 scripts.
354- The link shows up in that machine's **Settings → Sharing & access** like any
355 outside agent. Revoke it there to end it. **Forget** on this machine only
356 removes it here.
357- Links last 30 days. Link again with a new pairing code to renew one.
358
359An agent can also hand a task to a linked machine with `delegate_task`: it runs
360there as an ordinary thread, in the project with the same repository (or the
361one `target.projectId` names), and this thread wakes with its result when it
362ends, as for any delegated task. It keeps following the task across restarts.
363If the other machine revokes the link, or the link is removed here, the task
364fails with that reason.
365
366## Manage or revoke access
367
368On the host, **Settings → Sharing & access** lets authorized administrators create
369pairing links and revoke client sessions. Revoking an unused link prevents new
370pairings; revoke a device's session to remove its existing access. Command-line
371management is available through `t3 auth --help`.
372
373When the app connects to more than one environment, choose one at the top of the
374page. A desktop app with **Local environment** off can manage a background
375service on the same machine this way, including its T3 Connect link.
376
377A session with an open connection stays listed after its access credential
378expires.
379
380To choose a token's permissions, pass `--scope` once for each scope you want:
381
382```sh
383t3 pair --scope orchestration:read --scope relay:read
384```
385
386The selected scopes replace the default permissions. The same option works with
387`t3 auth pairing create` and `t3 auth session issue`; each command's
388`--help` lists the available scopes. Without `--scope`, pairing tokens and issued
389bearer sessions get every permission, including managing access and T3 Connect.
390A terminal or a full-access agent on the host can reach those as well, so a
391client that should not manage access also needs to go without `terminal:operate`
392and `orchestration:operate`.
393
394To change an existing client's permissions, create a fresh pairing link with the
395scopes it needs. In a browser opened directly on the environment, open that link
396to replace the browser's current grant. For mobile or a saved remote environment
397in web or desktop, use **Add Environment** with the fresh link or code; pairing
398the same environment replaces its saved grant. Reconnecting alone does not change
399permissions.
400
401Grouping checkouts does not combine their permissions. Shared project settings
402require `orchestration:operate` on every member environment; actions on one
403checkout use that checkout's permissions.
404
405`source-control:write` covers direct Git and pull request changes made from the
406client: pushing, switching or creating branches, cloning, and removing
407worktrees. It does not restrict what a task does. Starting a task in a new
408worktree still creates that branch and worktree with `orchestration:operate`,
409and the agent it runs can use Git however the environment allows.
410
411Settings changes, provider management, environment maintenance, access
412management, and T3 Connect management can each be granted separately. New
413pairings without `--scope` include all of them. Existing clients keep the
414permissions they paired with and can stay connected after an update, but newly
415separated features may require pairing again with the permissions they need.
416Older clients may show controls that the server denies. Create a fresh pairing
417link to change a client's permissions.
418
419`filesystem:read` allows browsing host files, opening workspace files, and viewing
420local changes. Add `filesystem:write` to allow editing files or saving plans to
421the workspace. These scopes control direct file access from the client.
422
423To remove an environment from T3 Connect, open your account menu's **T3 Connect**
424page, or **Settings → T3 Connect** on mobile, and choose **Deregister**. This
425revokes its cloud access and frees its host space even when the environment is
426offline or has been wiped. When T3 Connect rejects a host's link, the host
427shows that it was removed from T3 Connect. To link it again, turn on
428**T3 Connect** in **Settings → Sharing & access** on a desktop host, or run
429`t3 connect link` on a command-line host and then restart T3 Code there. A
430command-line host that released its tunnel when it last stopped may link itself
431again on its next start; run `t3 connect unlink` on that host to keep it off.
432Removing an environment from a device's connection settings only forgets it on
433that device and doesn't change your T3 Connect account. A device keeps a saved
434environment after it's deregistered until you remove it from that device.
435
436When idle tunnel cleanup is enabled, T3 Connect removes a linked environment's
437tunnel after it stays offline for several minutes. The environment stays linked
438and keeps the same address. When the host starts again or wakes, T3 Connect
439creates a replacement tunnel on its own. You do not need to pair again. Cleanup
440usually runs five to ten minutes after the tunnel goes down.
441
442T3 Connect also removes the tunnel of an environment running an older version of
443T3 Code once it has been offline for seven days. That environment shows a message
444asking you to update. Start T3 Code on that computer and update it to the latest
445version; it reconnects at the same address without pairing again.
446
447On a command-line host, `t3 connect unlink` disables exposure while retaining
448your login; `t3 connect logout` also clears that login. Background-service
449[removal](./background-service.md#manage-the-service) is separate.
450
451Treat pairing URLs and authorization codes as passwords. Do not include them in
452screenshots, logs, or bug reports.
453
454## T3 Connect troubleshooting
455
456When a T3 Connect connection fails, see
457[T3 Connect troubleshooting](./t3-connect-troubleshooting.md). It explains each
458error, where the problem is, and how to fix it.
459
460## Using the Desktop App as a Remote Only
461
462If a computer should only drive work running elsewhere, turn off its local environment. In the
463desktop app, open **Settings → Environments** and switch off **Local
464environment**. T3 Code restarts without a local server: no local agents or terminals run, WSL
465backends stay off, and other devices can no longer connect to this computer. Your projects,
466history, and saved connections are kept, and you keep working through pairing, T3 Connect, or SSH.
467If a [background service](./background-service.md) on this computer uses the same T3 home, the
468app still treats it as this computer: **Open in** and file reveal for its projects run here,
469whichever connection you reach it through.
470
471Switch **Local environment** back on in the same place to restart with your previous local
472settings.