Run T3 Code as a headless server in a container,
with coding agents and language toolchains installed on first start.
T3 Code is a control surface for coding agents. The server runs the agents, git and your terminals; the desktop, web and phone apps connect to it. This image packages that server with the agent CLIs, language toolchains, a headless browser, and a setup page for pairing devices, signing agents in and keeping everything up to date, all without a shell in the container.
Note
T3 Code is alpha software and changes quickly, and so does this image.
mkdir -p workspace
docker run -d --name t3code --restart unless-stopped \
-p 127.0.0.1:3773:3773 -p 127.0.0.1:3774:3774 \
-v t3-home:/home/t3 -v "$PWD/workspace:/workspace" \
-e PUID="$(id -u)" -e PGID="$(id -g)" \
--shm-size 1g \
dizys/t3code-docker- Get the setup key:
docker logs t3code 2>&1 | grep -A1 T3_SETUP_KEY - Open http://localhost:3774 and enter it. Overview walks you through the rest: set a public URL, pair a device with a QR code, and sign agents in.
- In T3 Code, turn the agents on under Settings → Providers.
On first start, the agents and toolchains install onto the t3-home volume in
the background. That takes a few minutes, and the setup page shows the
progress. Both ports listen on localhost only; see
Reaching it from your phone to go further.
For a server you keep running, save this as compose.yaml and run
docker compose up -d:
services:
t3code:
image: dizys/t3code-docker:latest
container_name: t3code
restart: unless-stopped
ports:
- "127.0.0.1:3773:3773" # T3 Code
- "127.0.0.1:3774:3774" # setup page
volumes:
- t3-home:/home/t3 # state, sign-ins, agents and toolchains
- ./workspace:/workspace # your repositories, one project per git checkout
environment:
PUID: 1000 # `id -u` on the host
PGID: 1000 # `id -g` on the host
shm_size: 1gb
logging:
driver: json-file
options: { max-size: "10m", max-file: "3" }
volumes:
t3-home:The setup key is in docker compose logs t3code | grep -A1 T3_SETUP_KEY.
Upgrade the image with docker compose pull && docker compose up -d.
Prefer to build from source, or want the optional Caddy HTTPS sidecar? Clone
the repository and use its compose.yaml with
.env.example, which documents every option:
git clone https://github.com/dizys/t3code-docker && cd t3code-docker
cp .env.example .env # set PUID/PGID and T3_WORKSPACE_HOST
docker compose up -d --build| Tag | Image | Download |
|---|---|---|
latest, browser |
Everything, including headless Chromium for the agents | ~1.0 GB |
core |
The same without the browser | ~0.7 GB |
X.Y.Z, X.Y, X.Y.Z-core, X.Y-core |
A pinned release |
Published to Docker Hub as dizys/t3code-docker
and to GHCR as ghcr.io/dizys/t3code-docker, each for linux/amd64 and
linux/arm64. The old full and slim tags are retired; see
Moving off full and slim.
- No shell needed. Pair devices, sign agents in, and install or update everything from the setup page, which also opens from T3 Code's Settings.
- Every T3 Code agent. Claude Code, Codex and OpenCode install on first start; Grok, Cursor, Muse Code and Antigravity take one click.
- Toolchains that survive upgrades. Go, Rust, Bun, Deno and uv, plus about a thousand more tools through mise, live on the volume at exact versions.
- A browser for the agents. Headless Chromium with Playwright and Chrome DevTools MCP servers.
- Publish a dev server. Any port gets a public
https://URL and a QR code, with no DNS or certificates. - Upgrade T3 Code in place. Pick Stable or Nightly; a failed update rolls back on its own.
- Pull requests on any host. GitHub, GitLab, Forgejo, Gitea and Azure DevOps.
browser (latest) |
core |
|
|---|---|---|
| T3 Code server and web app | ✅ | ✅ |
| git, gh, ssh, Node, Python, clang, ffmpeg, ImageMagick, psql | ✅ | ✅ |
| Claude Code, Codex, OpenCode | first start | first start |
| Grok, Cursor, Muse Code, Antigravity | one click | one click |
| Go, Rust, Bun, Deno, uv | first start | first start |
| glab, fj, tea, az (GitLab, Forgejo, Gitea, Azure DevOps) | one click | one click |
| mise, for per-project versions | ✅ | ✅ |
| cloudflared, for publishing a port | ✅ | ✅ |
| Headless Chromium and browser MCP servers | ✅ | — |
"First start" installs onto the /home/t3 volume once, in the background;
"one click" installs from the setup page when you ask. T3_PREINSTALL changes
what the first start installs. Neither image contains credentials or model
access: you bring your own subscriptions or API keys.
A phone needs an address it can reach. Pick one, then set it as the public URL on the setup page so pairing links point there:
- T3 Connect, no domain needed: Devices → From anywhere → Set up.
- One hostname behind a tunnel or proxy: set
T3_SINGLE_PORT=8080to serve T3 Code and the setup page together, and point Cloudflare Tunnel or your proxy at that port. - Your own domain with HTTPS: the repository's Compose file has a Caddy
sidecar,
docker compose --profile tls up -d. - Tailscale or a trusted LAN: use the machine's tailnet name or LAN address.
Ignore the pairing link in T3 Code's startup banner: it uses the container's
internal address and expires in five minutes. Use the setup page or t3-pair
instead. Details: Reaching the server from a phone.
| Guide | Covers |
|---|---|
| The setup page | The setup key, pairing, opening it from T3 Code |
| Reaching the server from a phone | Pairing, public URLs, tunnels, one hostname, link and session lifetimes |
| Agents | Installing, signing in and updating each agent |
| Upgrading T3 Code | Stable and Nightly, auto-update, rollback |
| Toolchains | Go, Rust and friends, any mise tool, per-project versions |
| Source control | gh, glab, fj, tea and az sign-in |
| Publishing a port | Public URLs for dev servers |
| Giving agents a browser | T3's server browser and the browser MCP servers |
| Context management | Global AGENTS.md and skills |
| Storage management | Disk usage, cache cleanup, version retention |
| Configuration | Every environment variable, volumes, building |
| Troubleshooting | Pairing, providers, terminals, permissions |
Helper commands in the container, each safe to run with plain docker exec:
docker exec t3code t3-doctor # what is installed, signed in and healthy
docker exec t3code t3-pair # a pairing link and QR code
docker exec -it t3code t3-login codex # sign an agent in from a shell
docker exec t3code t3-harness list # agents and their exact versions
docker exec t3code t3-expose 3000 # publish a portAn agent with a shell in this container can run anything, and the container is the only boundary.
- Pairing links and the setup key are credentials. Serve over HTTPS and
revoke what leaks, from the setup page or with
t3 auth pairing revoke <id>andt3 auth session revoke <id>. - Don't publish port 3773, 3774 or
T3_SINGLE_PORTunencrypted. The examples above bind to localhost for that reason; use TLS or a tunnel. - A browser paired with T3 Code can open the setup page without the key
when both share a hostname, because T3 Code already gives it a terminal.
T3_SETUP_ACCEPT_T3_SESSIONS=0turns this off. - Provider credentials live on the home volume. Protect it as you would your own home directory.
T3_ALLOW_SUDO=1gives agents root in the container. It's off by default.- T3 Code's own permission modes still apply. Start in supervised mode.
Issues and pull requests are welcome. See CONTRIBUTING.md for the smoke test, the development console and how releases are made.
MIT, see LICENSE. T3 Code and the agent CLIs have their own licenses; this repository packages them and does not relicense them.