From 80d2320686838a24cae5b40fed50f8f586ff9e3e Mon Sep 17 00:00:00 2001 From: Claude Date: Sat, 25 Jul 2026 22:17:06 +0000 Subject: [PATCH 1/3] fx: install T3 Code (t3) browser GUI Bundle T3 Code (https://github.com/pingdotgg/t3code) in the fx image only. It is a browser GUI that drives the coding agents (OpenCode, Claude, Codex) and serves a web UI on port 3773; `t3 serve` runs it headless. - fx/Dockerfile: `npm install -g t3` alongside the other npm-based CLIs. - Makefile: add an fx-only `t3 --version` smoke test (test-fx). - README: document t3 as fx-only, and add a Coder-template snippet that starts T3 Code in the background, exposes it as a workspace icon, and gates it behind a workspace-creation parameter (opencode only by default, T3 Code opt-in). Co-Authored-By: Claude Opus 4.8 Claude-Session: https://claude.ai/code/session_01Eszmn7WakQXem76vE9g7ZL --- Makefile | 6 +++- README.md | 78 +++++++++++++++++++++++++++++++++++++++++++++++++++ fx/Dockerfile | 4 +++ 3 files changed, 87 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 6a13e4a..e2aba04 100644 --- a/Makefile +++ b/Makefile @@ -35,7 +35,7 @@ test-all: .PHONY: test-fx test-fx: DOCKER_TAG=fx -test-fx: _testcase-node _testcase-pnpm _testcase-deno _testcase-bun _testcase-php _testcase-php-coverage _testcase-python _testcase-golang _testcase-common +test-fx: _testcase-node _testcase-pnpm _testcase-deno _testcase-bun _testcase-php _testcase-php-coverage _testcase-python _testcase-golang _testcase-t3code _testcase-common .PHONY: test-php test-php: DOCKER_TAG=php @@ -90,6 +90,10 @@ _testcase-python: _testcase-golang: $(TEST_RUN) go version +.PHONY: _testcase-t3code +_testcase-t3code: + $(TEST_RUN) t3 --version + .PHONY: _testcase-common _testcase-common: $(TEST_RUN) agent-browser --version diff --git a/README.md b/README.md index dc6bb6f..af856a9 100644 --- a/README.md +++ b/README.md @@ -39,6 +39,7 @@ one tag per template: > Node.js (with `npm`) ships in every image because the shared AI CLIs are installed from npm. > The `nodejs` tag additionally provides Deno and Bun; only the `fx` tag adds `pnpm`. +> The [T3 Code](https://github.com/pingdotgg/t3code) browser GUI (`t3`) is bundled only in the `fx` tag. ### Shared baseline @@ -67,6 +68,10 @@ Choose this when a workspace is polyglot or you don’t want to commit to one st - **Python 3** with `pip` and `venv`. - **Go 1.26.5** (installed to `/usr/local/go`; `GOROOT`/`GOPATH`/PATH set for login shells). - **Rootless Docker** (docker-in-docker) — see [Rootless Docker](#rootless-docker) below. +- **[T3 Code](https://github.com/pingdotgg/t3code)** (`t3`) — a browser GUI that drives the coding + agents (OpenCode, Claude, Codex). Serves a web UI on port `3773`; `t3 serve` runs it headless + (no browser popup). Only bundled in the `fx` tag — see + [AI coding agents in a Coder workspace](#ai-coding-agents-in-a-coder-workspace). ### `dockette/coder:php` @@ -113,6 +118,79 @@ resource "docker_container" "workspace" { Swap `fx` for `php`, `nodejs`, `golang`, or `python` to use a lighter, stack-specific image. +## AI coding agents in a Coder workspace + +The `fx` image ships both `opencode` (a terminal agent) and +[T3 Code](https://github.com/pingdotgg/t3code) (`t3`) — a browser GUI that drives OpenCode, Claude, +and Codex. T3 Code serves a web UI on port `3773`; `t3 serve` runs it headless (no browser popup), +which is what you want on a remote workspace. + +Wire them into your Coder Terraform template so a workspace can start T3 Code in the **background** +and expose it as a clickable **icon** on the dashboard. A workspace-creation parameter picks which +agents are enabled — by default only `opencode`, with T3 Code opt-in at create time: + +```hcl +# Shown when creating a workspace. Default: OpenCode only; T3 Code is opt-in. +data "coder_parameter" "ai_agents" { + name = "ai_agents" + display_name = "AI coding agents" + description = "Which AI coding agents to enable in this workspace." + type = "list(string)" + form_type = "multi-select" + default = jsonencode(["opencode"]) + mutable = true + + option { + name = "OpenCode" + value = "opencode" + } + option { + name = "T3 Code" + value = "t3code" + } +} + +locals { + agents = jsondecode(data.coder_parameter.ai_agents.value) + opencode_on = contains(local.agents, "opencode") + t3code_on = contains(local.agents, "t3code") +} + +resource "coder_agent" "main" { + # ... arch / os / other startup steps ... + startup_script = <<-EOT + set -e + # `if true; then` / `if false; then` — the interpolated bool is a shell builtin. + if ${local.t3code_on}; then + # Start T3 Code headless in the background, bound to localhost:3773. + T3CODE_NO_BROWSER=1 nohup t3 serve --host 127.0.0.1 --port 3773 \ + > "$HOME/.t3code.log" 2>&1 & + fi + # opencode is a terminal agent — launch it from a workspace terminal with `opencode`. + EOT +} + +# Clickable "T3 Code" icon in the dashboard, only when it's enabled. +resource "coder_app" "t3code" { + count = local.t3code_on ? 1 : 0 + agent_id = coder_agent.main.id + slug = "t3code" + display_name = "T3 Code" + icon = "/icon/code.svg" + url = "http://localhost:3773" + subdomain = true + share = "owner" + + healthcheck { + url = "http://localhost:3773" + interval = 5 + threshold = 30 + } +} +``` + +To enable T3 Code by default instead, set `default = jsonencode(["opencode", "t3code"])`. + ## Rootless Docker The `fx` image can run Docker-in-Docker without privileged root. Start the daemon inside the workspace: diff --git a/fx/Dockerfile b/fx/Dockerfile index ebff358..507c8a8 100644 --- a/fx/Dockerfile +++ b/fx/Dockerfile @@ -90,6 +90,10 @@ RUN \ chmod 0755 /usr/local/bin/opencode && \ # NPM: CODEX, COPILOT ####################################################### npm install -g @openai/codex @github/copilot && \ + # T3CODE (browser GUI for coding agents) ################################### + # fx-only: a web front-end that drives opencode/claude/codex. `t3 serve` + # runs it headless (no browser popup); default UI port is 3773. + npm install -g t3 && \ # PNPM ###################################################################### npm install -g pnpm && \ # AGENT-BROWSER ############################################################## From 097fbeccd085ed36f8b733e6b6fc0447a632957d Mon Sep 17 00:00:00 2001 From: Claude Date: Sat, 25 Jul 2026 22:19:06 +0000 Subject: [PATCH 2/3] docs: drop Coder template snippet for T3 Code MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Remove the Coder-template wiring (coder_parameter / coder_app / startup_script) added earlier — that belongs in a workspace template, not in this image repo. Keep only the factual note that T3 Code (`t3`) is installed in the fx image. Co-Authored-By: Claude Opus 4.8 Claude-Session: https://claude.ai/code/session_01Eszmn7WakQXem76vE9g7ZL --- README.md | 76 +------------------------------------------------------ 1 file changed, 1 insertion(+), 75 deletions(-) diff --git a/README.md b/README.md index af856a9..2ba1eaf 100644 --- a/README.md +++ b/README.md @@ -70,8 +70,7 @@ Choose this when a workspace is polyglot or you don’t want to commit to one st - **Rootless Docker** (docker-in-docker) — see [Rootless Docker](#rootless-docker) below. - **[T3 Code](https://github.com/pingdotgg/t3code)** (`t3`) — a browser GUI that drives the coding agents (OpenCode, Claude, Codex). Serves a web UI on port `3773`; `t3 serve` runs it headless - (no browser popup). Only bundled in the `fx` tag — see - [AI coding agents in a Coder workspace](#ai-coding-agents-in-a-coder-workspace). + (no browser popup). Only bundled in the `fx` tag. ### `dockette/coder:php` @@ -118,79 +117,6 @@ resource "docker_container" "workspace" { Swap `fx` for `php`, `nodejs`, `golang`, or `python` to use a lighter, stack-specific image. -## AI coding agents in a Coder workspace - -The `fx` image ships both `opencode` (a terminal agent) and -[T3 Code](https://github.com/pingdotgg/t3code) (`t3`) — a browser GUI that drives OpenCode, Claude, -and Codex. T3 Code serves a web UI on port `3773`; `t3 serve` runs it headless (no browser popup), -which is what you want on a remote workspace. - -Wire them into your Coder Terraform template so a workspace can start T3 Code in the **background** -and expose it as a clickable **icon** on the dashboard. A workspace-creation parameter picks which -agents are enabled — by default only `opencode`, with T3 Code opt-in at create time: - -```hcl -# Shown when creating a workspace. Default: OpenCode only; T3 Code is opt-in. -data "coder_parameter" "ai_agents" { - name = "ai_agents" - display_name = "AI coding agents" - description = "Which AI coding agents to enable in this workspace." - type = "list(string)" - form_type = "multi-select" - default = jsonencode(["opencode"]) - mutable = true - - option { - name = "OpenCode" - value = "opencode" - } - option { - name = "T3 Code" - value = "t3code" - } -} - -locals { - agents = jsondecode(data.coder_parameter.ai_agents.value) - opencode_on = contains(local.agents, "opencode") - t3code_on = contains(local.agents, "t3code") -} - -resource "coder_agent" "main" { - # ... arch / os / other startup steps ... - startup_script = <<-EOT - set -e - # `if true; then` / `if false; then` — the interpolated bool is a shell builtin. - if ${local.t3code_on}; then - # Start T3 Code headless in the background, bound to localhost:3773. - T3CODE_NO_BROWSER=1 nohup t3 serve --host 127.0.0.1 --port 3773 \ - > "$HOME/.t3code.log" 2>&1 & - fi - # opencode is a terminal agent — launch it from a workspace terminal with `opencode`. - EOT -} - -# Clickable "T3 Code" icon in the dashboard, only when it's enabled. -resource "coder_app" "t3code" { - count = local.t3code_on ? 1 : 0 - agent_id = coder_agent.main.id - slug = "t3code" - display_name = "T3 Code" - icon = "/icon/code.svg" - url = "http://localhost:3773" - subdomain = true - share = "owner" - - healthcheck { - url = "http://localhost:3773" - interval = 5 - threshold = 30 - } -} -``` - -To enable T3 Code by default instead, set `default = jsonencode(["opencode", "t3code"])`. - ## Rootless Docker The `fx` image can run Docker-in-Docker without privileged root. Start the daemon inside the workspace: From 0788ff9482ef68d3c0fb7cc51066b4c32e08ae06 Mon Sep 17 00:00:00 2001 From: Claude Date: Sat, 25 Jul 2026 22:21:10 +0000 Subject: [PATCH 3/3] fx: trim T3 Code install comment Match the single-line banner style used by the other sections. Co-Authored-By: Claude Opus 4.8 Claude-Session: https://claude.ai/code/session_01Eszmn7WakQXem76vE9g7ZL --- fx/Dockerfile | 2 -- 1 file changed, 2 deletions(-) diff --git a/fx/Dockerfile b/fx/Dockerfile index 507c8a8..4fa0075 100644 --- a/fx/Dockerfile +++ b/fx/Dockerfile @@ -91,8 +91,6 @@ RUN \ # NPM: CODEX, COPILOT ####################################################### npm install -g @openai/codex @github/copilot && \ # T3CODE (browser GUI for coding agents) ################################### - # fx-only: a web front-end that drives opencode/claude/codex. `t3 serve` - # runs it headless (no browser popup); default UI port is 3773. npm install -g t3 && \ # PNPM ###################################################################### npm install -g pnpm && \