Deploy T3 Code on Civo and keep coding with AI when your PC is off

Move the T3 Code server to a Civo Compute instance and your coding agents keep running overnight, through tunnel dropouts, and across every device you own — laptop closed or not.

11 minutes reading time

Written by

Fulvio Denza
Fulvio Denza

Software Engineer at Civo

Your coding agent doesn't need your laptop. If you close the lid on a long refactor, the agent stops. If your machine sleeps overnight, the review you asked for never finishes. T3 Code is an open source web and desktop GUI for running coding agents, and this post walks you through putting it on a Civo Compute instance. The agent then keeps working on a machine that never sleeps, and you connect to it from a browser, your phone, or the desktop app whenever you feel like it.

What you are building

T3 Code has two halves: a server that owns your projects, your git checkouts, your terminals and your agent processes, and a client that draws the UI. Normally both run on your laptop. We are going to move the server to a Civo instance and leave only the client on your devices.

The result:

  • Agent sessions run on the instance, so they survive your laptop sleeping, your train going into a tunnel, and your PC being shut down entirely.
  • You reconnect from any device (desktop app, https://app.t3.codes, or your phone) and pick up the same threads, terminals, and diffs.
  • You keep your own agent subscriptions. T3 Code drives provider CLIs such as Claude Code and Codex CLI; it does not resell tokens, and it does not ship the CLIs either.

A word on what this is not: T3 Code is early software and it gives whoever reaches it a shell and an agent on your box. We will bind it to a private network rather than the public internet, and I would strongly encourage you not to skip that part.

Tools you will need

Civo CLI

Everything below can be done from the Civo dashboard, but the CLI is faster to follow along with. Install it from the Civo CLI repository and add your API key:

$ civo apikey add production <your-api-key>
$ civo instance size ls

That second command lists the size codes available in your region. Worth running now, because you will pass one of them in a moment.

An SSH key

You will be logging into this instance to authenticate your agent CLIs, so upload a key rather than relying on the generated password:

$ civo sshkey create laptop --key ~/.ssh/id_ed25519.pub

A private network between your devices

The T3 Code server speaks plain HTTP on port 3773 and authenticates devices through pairing tokens. That is fine on a trusted network and not fine on the open internet. The upstream docs recommend meshing your devices with something like Tailscale, and T3 Code has first-class support for it, so that is what this guide uses. A free Tailscale account is enough. Install it on the device you will browse from as well.

An agent subscription

T3 Code is a front end. You need at least one provider CLI installed and logged in on the server:

  • Codex: log in with codex login
  • Claude: log in with claude auth login
  • Cursor: cursor-agent, log in with agent login
  • Grok Build: grok, log in with grok login
  • OpenCode: opencode, log in with opencode auth login

Codex and Claude are enabled by default; the others you switch on in Settings. The important detail is that these logins happen on the instance, not on the device you browse from.

Creating the Civo instance

Sizing it

The agent itself is an API client, so the CPU work is your build and test commands, not the model. Two cores and 4 GB of RAM is a comfortable starting point for a couple of concurrent agent threads on a typical web project. That is the Medium standard instance at around $21.73 a month, with the 50 GB NVMe disk holding your checkouts and node_modules. Go to Large (4 cores, 8 GB) if you run heavy test suites or several agents at once. You can resize later, so start small.

A firewall that only allows SSH

Custom Civo firewalls close every port by default, which is exactly what we want. Create one with no default rules and open SSH only:

$ civo firewall create t3code --no-default-rules
Created a firewall called t3code with ID ab2a25d7-edd4-4ecd-95c4-58cb6bc402de
$ civo firewall rule create t3code --startport=22 --endport=22 \
--direction=ingress --protocol=TCP --action=allow \
--label='SSH access'
New rule SSH access created

Note what is missing: no rule for 3773. Tailscale connects outbound and needs no inbound port, so T3 Code will be reachable over your tailnet while the instance stays invisible from the internet. If your home connection has a static IP you can narrow SSH further with --cidr 203.0.113.4/32.

Launching it

$ civo instance create --hostname=t3code \
--size=g4s.medium \
--diskimage=ubuntu-noble \
--firewall=t3code \
--sshkey=laptop \
--initialuser=dev \
--wait
The instance t3code has been created
$ civo instance show t3code

Substitute the size code you saw in civo instance size ls. Take the public IP from the output of instance show and log in:

$ ssh dev@<instance-public-ip>

Preparing the instance

Node.js and build essentials

The T3 Code server requires Node.js ^22.16 || ^23.11 || >=24.10. Ubuntu's repositories lag well behind that, so install from NodeSource:

$ sudo apt update && sudo apt install -y curl git build-essential
$ curl -fsSL https://deb.nodesource.com/setup_24.x | sudo -E bash -
$ sudo apt install -y nodejs
$ node --version
v24.12.0

Any version inside the supported range is fine. If you prefer a version manager, use one, but read the note about non-interactive shells further down, because it matters when the server starts at boot.

Git identity and repository access

The agent commits and opens pull requests from this machine, so it needs its own identity and its own credentials:

$ git config --global user.name "Your Name"
$ git config --global user.email "you@example.com"
$ ssh-keygen -t ed25519 -C "t3code-civo"
$ cat ~/.ssh/id_ed25519.pub

Add that public key to GitHub as a new SSH key: a deploy key if you only need one repository, an account key if you want the agent to roam. If you want T3 Code's one-click pull request flow, also install and authenticate the GitHub CLI:

$ sudo apt install -y gh
$ gh auth login

Your agent CLI

Install and log in to whichever provider you are paying for. Using Claude Code as the example:

$ claude auth login

The login opens a URL. On a headless box, copy it into the browser on your laptop and paste the code back. Do this now rather than later, because an unauthenticated provider will happily let T3 Code start and then fail the moment you open a session.

Tailscale

$ curl -fsSL https://tailscale.com/install.sh | sh
$ sudo tailscale up
$ tailscale ip -4
100.86.12.31

Follow the printed URL to authorise the machine in your tailnet. That 100.x.y.z address is now a stable, private, encrypted route to the instance from any of your devices, and it does not change when you move between networks.

Installing and starting T3 Code

There is nothing to build. Run the server headless, bound to your tailnet address:

$ npx t3@latest serve --host "$(tailscale ip -4)"

t3 serve starts the server without opening a browser and prints four things: a connection string, a one-time pairing token, a pairing URL, and a QR code for that URL. Use npx t3@latest serve --help for the full flag reference; it accepts the same startup options as the normal command, including an optional working directory argument.

Binding to the tailnet IP rather than 0.0.0.0 is the whole security model here. Anyone who can reach the port and hold a valid pairing credential gets an authenticated session, an agent, and a terminal on this instance.

Pairing your first device

Scan the QR code with your phone, or paste the pairing URL into the T3 Code desktop app, or enter the host and token separately. Pairing works as a token exchange: the server issues a one-time owner token, your device trades it for an authenticated session, and from then on access is session-based. You do not need to keep the original token around unless you are pairing another device.

Treat pairing URLs like passwords. They end up in browser history and screenshots, and they are valid until they expire or you revoke them. t3 auth is where you issue new tokens, inspect active sessions and revoke anything you do not recognise.

Using the hosted web app

https://app.t3.codes is served over HTTPS, and browsers refuse to let an HTTPS page talk to a plain http://100.x.y.z:3773 backend. If you want to use the hosted client, which is the nicest option on a phone, publish the server over Tailscale Serve HTTPS instead:

$ npx t3@latest serve --tailscale-serve

This configures Tailscale Serve on HTTPS port 443 and advertises a clean MagicDNS URL such as https://t3code.your-tailnet.ts.net/. Pass --tailscale-serve-port 8443 if 443 is taken. The desktop app has the same switch under SettingsConnectionsEnable Tailscale HTTPS.

If a server is already running and you just want a fresh token for a new device, you do not need to restart anything:

$ npx t3@latest pair --tailscale

t3 pair finds the running server, mints a one-time token with a lifetime you can set via --ttl, and prints the QR code.

Surviving your PC being shut down

Right now the server is a foreground process attached to your SSH session, which dies the moment you disconnect. That defeats the entire point. T3 Code ships a background service for exactly this:

$ npx t3@latest service install
$ npx t3@latest service status

On Linux, this installs a systemd user unit at ~/.config/systemd/user/t3code.service and enables lingering, so the server starts when the instance boots and keeps running after you log out. Stop the foreground t3 serve before installing it, and enable network access so the service binds somewhere your other devices can reach. The desktop app's Network access toggle and the Tailscale HTTPS switch both restart the backend with the right binding.

Two things to know about the service:

  • Version managers can bite here: The service and the SSH launcher both start from a non-interactive shell. If your Node install only resolves inside an interactive shell profile, it will not be found. Test it the way T3 Code does: ssh dev@<ip> 'sh -lc "command -v node && node --version"'. With nvm, nvm alias default 24 usually fixes it; with mise, asdf, fnm or nodenv, make sure the shim directory resolves without an interactive shell. A NodeSource install, as above, sidesteps this entirely.
  • Updates restart the server: npx t3@latest service update repairs or updates it, briefly interrupting the server, so let running agent work and terminal commands finish first.

Now you can close your laptop. The agent is running on an instance in a Civo datacentre, and the process does not care whether any of your devices are awake.

Adding your projects

With a device paired, open the command palette and choose Add Project, then pick the environment the project lives on. Every saved environment is offered, not just the local one. Clone your repositories onto the instance first:

$ mkdir -p ~/projects && cd ~/projects
$ git clone git@github.com:you/your-project.git

From there it is the T3 Code you would run locally: threads per agent, a branch per thread, integrated terminals, file diffs, worktree management, model switching mid-conversation, and one-click pull requests with generated titles and descriptions. The difference is that the terminal you are typing into and the agent you are talking to both live on the instance.

Worth reading before you hand over the keys: permission modes control how much T3 Code asks before acting. On a cloud box with credentials for your repositories attached, be deliberate about that setting rather than reaching for the most permissive one out of habit.

Two remote options you did not use

For completeness, T3 Code has two other ways to reach a remote server, and both are worth knowing about.

  • Desktop-managed SSH launch skips pairing entirely. Under SettingsConnectionsRemote EnvironmentsAdd environment, choose the SSH flow and give it dev@<instance-ip>. The desktop app probes the host, starts or reuses a T3 server there, opens a local port forward, and saves the environment. It is the least exposed option, since nothing listens beyond loopback on the instance, but it only works from the desktop app, because it needs local SSH and process access. No phone.
  • Opening port 3773 to the internet with a Civo firewall rule and a CIDR restricted to your home IP will also work. It is plain HTTP, so your pairing token and everything you type crosses the internet in the clear, and a home IP is rarely as static as people assume. If you want a publicly reachable endpoint, put a reverse proxy with a real certificate in front of it and keep the backend on loopback.

Housekeeping

  • Keep client and server in step: Version skew between the app and a remote server raises a warning in the conversation and in SettingsConnections, along with the action to take.
  • Audit your sessions: t3 auth lists active sessions and revokes credentials. Do this after pairing a device you no longer use.
  • Watch the spend: The Usage page aggregates Codex and Claude Code activity across connected environments: token cost, cache savings, model breakdown. Handy when an agent has been grinding away unattended overnight.
  • Stop paying when you are not using it: A Civo instance bills hourly. If this is a weekday habit, civo instance stop t3code and civo instance start t3code are cheaper than leaving it running, though a stopped instance cannot run agents either, which rather undermines the point.

Conclusion

You now have a T3 Code server on a Civo Compute instance, reachable only over your own private network, starting automatically at boot and running as a background service. Your agent threads live on that instance with your repositories and your provider credentials, so work continues while your laptop is closed, asleep, or off, and you rejoin from whatever device is nearest.

Fulvio Denza
Fulvio Denza

Software Engineer at Civo

Fulvio Denza is a Software Engineer at Civo focused on building cloud-native infrastructure and distributed systems. His work involves developing components of the Civo cloud provider using technologies such as Go, Rust, Kubernetes, Docker, and PostgreSQL.

Alongside his engineering work, Fulvio develops independent projects including Allinmap, an application that helps users discover public amenities and create custom shareable maps. His background combines software engineering with strong analytical and mathematical foundations.

View author profile