From d5d0c00df6fe306ca2ef2c12aa35082c107d2921 Mon Sep 17 00:00:00 2001 From: Cian Johnston Date: Fri, 12 Sep 2025 12:56:57 +0100 Subject: [PATCH 1/4] fix(registry/modules/claude-code): default subdomain to false --- registry/coder/modules/claude-code/README.md | 2 ++ .../coder/modules/claude-code/main.test.ts | 35 ++++++++++++++++++- registry/coder/modules/claude-code/main.tf | 8 ++--- .../claude-code/testdata/agentapi-mock.js | 3 +- 4 files changed, 42 insertions(+), 6 deletions(-) diff --git a/registry/coder/modules/claude-code/README.md b/registry/coder/modules/claude-code/README.md index 91e966362..3aa34ef0c 100644 --- a/registry/coder/modules/claude-code/README.md +++ b/registry/coder/modules/claude-code/README.md @@ -114,4 +114,6 @@ module "claude-code" { ## Troubleshooting +By default, this module is configured to run the embedded chat interface as a path-based application. In production, we recommend that you configure a [wildcard access URL](https://coder.com/docs/admin/setup#wildcard-access-url) and set `subdomain = true`. + The module will create log files in the workspace's `~/.claude-module` directory. If you run into any issues, look at them for more information. diff --git a/registry/coder/modules/claude-code/main.test.ts b/registry/coder/modules/claude-code/main.test.ts index 08e4b488e..e1647022e 100644 --- a/registry/coder/modules/claude-code/main.test.ts +++ b/registry/coder/modules/claude-code/main.test.ts @@ -3,6 +3,7 @@ import { afterEach, expect, describe, + it, setDefaultTimeout, beforeAll, } from "bun:test"; @@ -100,6 +101,7 @@ const writeAgentAPIMockControl = async ({ interface SetupProps { skipAgentAPIMock?: boolean; skipClaudeMock?: boolean; + extraVars?: Record; } const projectDir = "/home/coder/project"; @@ -112,6 +114,7 @@ const setup = async (props?: SetupProps): Promise<{ id: string }> => { install_claude_code: "false", agentapi_version: "preview", folder: projectDir, + ...props?.extraVars, }, }); await execContainer(id, ["bash", "-c", `mkdir -p '${projectDir}'`]); @@ -335,6 +338,36 @@ describe("claude-code", async () => { id, "/home/coder/agentapi-mock.log", ); - expect(agentApiStartLog).toContain("AGENTAPI_ALLOWED_HOSTS: *"); + expect(agentApiStartLog).toContain("AGENTAPI_ALLOWED_HOSTS=*"); + }); + + describe("subdomain", async () => { + it("sets AGENTAPI_CHAT_BASE_PATH when false", async () => { + const { id } = await setup(); + const respModuleScript = await execModuleScript(id); + expect(respModuleScript.exitCode).toBe(0); + await expectAgentAPIStarted(id); + const agentApiStartLog = await readFileContainer( + id, + "/home/coder/agentapi-mock.log", + ); + expect(agentApiStartLog).toContain( + "AGENTAPI_CHAT_BASE_PATH=/@default/default.foo/apps/ccw/chat", + ); + }); + + it("does not set AGENTAPI_CHAT_BASE_PATH when true", async () => { + const { id } = await setup({ + extraVars: { subdomain: "true" }, + }); + const respModuleScript = await execModuleScript(id); + expect(respModuleScript.exitCode).toBe(0); + await expectAgentAPIStarted(id); + const agentApiStartLog = await readFileContainer( + id, + "/home/coder/agentapi-mock.log", + ); + expect(agentApiStartLog).toMatch(/AGENTAPI_CHAT_BASE_PATH=$/m); + }); }); }); diff --git a/registry/coder/modules/claude-code/main.tf b/registry/coder/modules/claude-code/main.tf index e56b8844b..52fd32951 100644 --- a/registry/coder/modules/claude-code/main.tf +++ b/registry/coder/modules/claude-code/main.tf @@ -106,12 +106,12 @@ variable "agentapi_version" { variable "subdomain" { type = bool description = "Whether to use a subdomain for the Claude Code app." - default = true + default = false } locals { # we have to trim the slash because otherwise coder exp mcp will - # set up an invalid claude config + # set up an invalid claude config workdir = trimsuffix(var.folder, "/") encoded_pre_install_script = var.experiment_pre_install_script != null ? base64encode(var.experiment_pre_install_script) : "" encoded_post_install_script = var.experiment_post_install_script != null ? base64encode(var.experiment_post_install_script) : "" @@ -244,7 +244,7 @@ resource "coder_script" "claude_code" { # Disable host header check since AgentAPI is proxied by Coder (which does its own validation) export AGENTAPI_ALLOWED_HOSTS="*" - + # Set chat base path for non-subdomain routing (only set if not using subdomain) export AGENTAPI_CHAT_BASE_PATH="${local.agentapi_chat_base_path}" @@ -295,4 +295,4 @@ resource "coder_ai_task" "claude_code" { sidebar_app { id = coder_app.claude_code_web.id } -} \ No newline at end of file +} diff --git a/registry/coder/modules/claude-code/testdata/agentapi-mock.js b/registry/coder/modules/claude-code/testdata/agentapi-mock.js index 5f37d3ca7..e74f3c680 100644 --- a/registry/coder/modules/claude-code/testdata/agentapi-mock.js +++ b/registry/coder/modules/claude-code/testdata/agentapi-mock.js @@ -22,7 +22,8 @@ if ( fs.writeFileSync( "/home/coder/agentapi-mock.log", - `AGENTAPI_ALLOWED_HOSTS: ${process.env.AGENTAPI_ALLOWED_HOSTS}`, + `AGENTAPI_ALLOWED_HOSTS=${process.env.AGENTAPI_ALLOWED_HOSTS} + AGENTAPI_CHAT_BASE_PATH=${process.env.AGENTAPI_CHAT_BASE_PATH}`, ); console.log(`starting server on port ${port}`); From e77603e74d0a8a29c9f4bd22a7360a727d4e5a79 Mon Sep 17 00:00:00 2001 From: Cian Johnston Date: Fri, 12 Sep 2025 13:09:04 +0100 Subject: [PATCH 2/4] add link to recommendations re path-based apps --- registry/coder/modules/claude-code/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/registry/coder/modules/claude-code/README.md b/registry/coder/modules/claude-code/README.md index 3aa34ef0c..0283ad311 100644 --- a/registry/coder/modules/claude-code/README.md +++ b/registry/coder/modules/claude-code/README.md @@ -114,6 +114,6 @@ module "claude-code" { ## Troubleshooting -By default, this module is configured to run the embedded chat interface as a path-based application. In production, we recommend that you configure a [wildcard access URL](https://coder.com/docs/admin/setup#wildcard-access-url) and set `subdomain = true`. +By default, this module is configured to run the embedded chat interface as a path-based application. In production, we recommend that you configure a [wildcard access URL](https://coder.com/docs/admin/setup#wildcard-access-url) and set `subdomain = true`. See [here](https://coder.com/docs/tutorials/best-practices/security-best-practices#disable-path-based-apps) for more details. The module will create log files in the workspace's `~/.claude-module` directory. If you run into any issues, look at them for more information. From edebb143547783967b1f3babed1e0f61a1deac8a Mon Sep 17 00:00:00 2001 From: Cian Johnston Date: Fri, 12 Sep 2025 14:10:12 +0100 Subject: [PATCH 3/4] chore: bump claude-code module version (patch) --- registry/coder/modules/claude-code/README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/registry/coder/modules/claude-code/README.md b/registry/coder/modules/claude-code/README.md index 0283ad311..23fc68aae 100644 --- a/registry/coder/modules/claude-code/README.md +++ b/registry/coder/modules/claude-code/README.md @@ -13,7 +13,7 @@ Run the [Claude Code](https://docs.anthropic.com/en/docs/agents-and-tools/claude ```tf module "claude-code" { source = "registry.coder.com/coder/claude-code/coder" - version = "2.2.0" + version = "2.2.1" agent_id = coder_agent.example.id folder = "/home/coder" install_claude_code = true @@ -83,7 +83,7 @@ resource "coder_agent" "main" { module "claude-code" { count = data.coder_workspace.me.start_count source = "registry.coder.com/coder/claude-code/coder" - version = "2.2.0" + version = "2.2.1" agent_id = coder_agent.example.id folder = "/home/coder" install_claude_code = true @@ -101,7 +101,7 @@ Run Claude Code as a standalone app in your workspace. This will install Claude ```tf module "claude-code" { source = "registry.coder.com/coder/claude-code/coder" - version = "2.2.0" + version = "2.2.1" agent_id = coder_agent.example.id folder = "/home/coder" install_claude_code = true From 789cf405504ee88a6c3dd3f2afa11db39906740b Mon Sep 17 00:00:00 2001 From: Cian Johnston Date: Fri, 12 Sep 2025 14:12:08 +0100 Subject: [PATCH 4/4] fmt --- registry/coder/modules/claude-code/README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/registry/coder/modules/claude-code/README.md b/registry/coder/modules/claude-code/README.md index 23fc68aae..dfebcebc2 100644 --- a/registry/coder/modules/claude-code/README.md +++ b/registry/coder/modules/claude-code/README.md @@ -13,7 +13,7 @@ Run the [Claude Code](https://docs.anthropic.com/en/docs/agents-and-tools/claude ```tf module "claude-code" { source = "registry.coder.com/coder/claude-code/coder" - version = "2.2.1" + version = "2.2.1" agent_id = coder_agent.example.id folder = "/home/coder" install_claude_code = true @@ -83,7 +83,7 @@ resource "coder_agent" "main" { module "claude-code" { count = data.coder_workspace.me.start_count source = "registry.coder.com/coder/claude-code/coder" - version = "2.2.1" + version = "2.2.1" agent_id = coder_agent.example.id folder = "/home/coder" install_claude_code = true @@ -101,7 +101,7 @@ Run Claude Code as a standalone app in your workspace. This will install Claude ```tf module "claude-code" { source = "registry.coder.com/coder/claude-code/coder" - version = "2.2.1" + version = "2.2.1" agent_id = coder_agent.example.id folder = "/home/coder" install_claude_code = true