Skip to content

Commit cb990bb

Browse files
authored
fix(registry/modules/claude-code): default subdomain to false (#419)
Relates to coder/coder#18779 By default, we set `subdomain = true`. Most folks testing this out don't have a wildcard subdomain setup. This switches to path-based behaviour by default and adds a note to the troubleshooting section.
1 parent 213aabb commit cb990bb

File tree

4 files changed

+46
-9
lines changed

4 files changed

+46
-9
lines changed

registry/coder/modules/claude-code/README.md

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ Run the [Claude Code](https://docs.anthropic.com/en/docs/agents-and-tools/claude
1313
```tf
1414
module "claude-code" {
1515
source = "registry.coder.com/coder/claude-code/coder"
16-
version = "2.2.0"
16+
version = "2.2.1"
1717
agent_id = coder_agent.example.id
1818
folder = "/home/coder"
1919
install_claude_code = true
@@ -26,6 +26,9 @@ module "claude-code" {
2626
> this enables more functionality, it also means Claude Code can potentially execute commands with the same privileges as
2727
> the user running it. Use this module _only_ in trusted environments and be aware of the security implications.
2828
29+
> [!NOTE]
30+
> 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.
31+
2932
## Prerequisites
3033

3134
- You must add the [Coder Login](https://registry.coder.com/modules/coder-login) module to your template
@@ -83,7 +86,7 @@ resource "coder_agent" "main" {
8386
module "claude-code" {
8487
count = data.coder_workspace.me.start_count
8588
source = "registry.coder.com/coder/claude-code/coder"
86-
version = "2.2.0"
89+
version = "2.2.1"
8790
agent_id = coder_agent.example.id
8891
folder = "/home/coder"
8992
install_claude_code = true
@@ -101,7 +104,7 @@ Run Claude Code as a standalone app in your workspace. This will install Claude
101104
```tf
102105
module "claude-code" {
103106
source = "registry.coder.com/coder/claude-code/coder"
104-
version = "2.2.0"
107+
version = "2.2.1"
105108
agent_id = coder_agent.example.id
106109
folder = "/home/coder"
107110
install_claude_code = true

registry/coder/modules/claude-code/main.test.ts

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import {
33
afterEach,
44
expect,
55
describe,
6+
it,
67
setDefaultTimeout,
78
beforeAll,
89
} from "bun:test";
@@ -100,6 +101,7 @@ const writeAgentAPIMockControl = async ({
100101
interface SetupProps {
101102
skipAgentAPIMock?: boolean;
102103
skipClaudeMock?: boolean;
104+
extraVars?: Record<string, string>;
103105
}
104106

105107
const projectDir = "/home/coder/project";
@@ -112,6 +114,7 @@ const setup = async (props?: SetupProps): Promise<{ id: string }> => {
112114
install_claude_code: "false",
113115
agentapi_version: "preview",
114116
folder: projectDir,
117+
...props?.extraVars,
115118
},
116119
});
117120
await execContainer(id, ["bash", "-c", `mkdir -p '${projectDir}'`]);
@@ -335,6 +338,36 @@ describe("claude-code", async () => {
335338
id,
336339
"/home/coder/agentapi-mock.log",
337340
);
338-
expect(agentApiStartLog).toContain("AGENTAPI_ALLOWED_HOSTS: *");
341+
expect(agentApiStartLog).toContain("AGENTAPI_ALLOWED_HOSTS=*");
342+
});
343+
344+
describe("subdomain", async () => {
345+
it("sets AGENTAPI_CHAT_BASE_PATH when false", async () => {
346+
const { id } = await setup();
347+
const respModuleScript = await execModuleScript(id);
348+
expect(respModuleScript.exitCode).toBe(0);
349+
await expectAgentAPIStarted(id);
350+
const agentApiStartLog = await readFileContainer(
351+
id,
352+
"/home/coder/agentapi-mock.log",
353+
);
354+
expect(agentApiStartLog).toContain(
355+
"AGENTAPI_CHAT_BASE_PATH=/@default/default.foo/apps/ccw/chat",
356+
);
357+
});
358+
359+
it("does not set AGENTAPI_CHAT_BASE_PATH when true", async () => {
360+
const { id } = await setup({
361+
extraVars: { subdomain: "true" },
362+
});
363+
const respModuleScript = await execModuleScript(id);
364+
expect(respModuleScript.exitCode).toBe(0);
365+
await expectAgentAPIStarted(id);
366+
const agentApiStartLog = await readFileContainer(
367+
id,
368+
"/home/coder/agentapi-mock.log",
369+
);
370+
expect(agentApiStartLog).toMatch(/AGENTAPI_CHAT_BASE_PATH=$/m);
371+
});
339372
});
340373
});

registry/coder/modules/claude-code/main.tf

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -106,12 +106,12 @@ variable "agentapi_version" {
106106
variable "subdomain" {
107107
type = bool
108108
description = "Whether to use a subdomain for the Claude Code app."
109-
default = true
109+
default = false
110110
}
111111

112112
locals {
113113
# we have to trim the slash because otherwise coder exp mcp will
114-
# set up an invalid claude config
114+
# set up an invalid claude config
115115
workdir = trimsuffix(var.folder, "/")
116116
encoded_pre_install_script = var.experiment_pre_install_script != null ? base64encode(var.experiment_pre_install_script) : ""
117117
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" {
244244
245245
# Disable host header check since AgentAPI is proxied by Coder (which does its own validation)
246246
export AGENTAPI_ALLOWED_HOSTS="*"
247-
247+
248248
# Set chat base path for non-subdomain routing (only set if not using subdomain)
249249
export AGENTAPI_CHAT_BASE_PATH="${local.agentapi_chat_base_path}"
250250
@@ -295,4 +295,4 @@ resource "coder_ai_task" "claude_code" {
295295
sidebar_app {
296296
id = coder_app.claude_code_web.id
297297
}
298-
}
298+
}

registry/coder/modules/claude-code/testdata/agentapi-mock.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,8 @@ if (
2222

2323
fs.writeFileSync(
2424
"/home/coder/agentapi-mock.log",
25-
`AGENTAPI_ALLOWED_HOSTS: ${process.env.AGENTAPI_ALLOWED_HOSTS}`,
25+
`AGENTAPI_ALLOWED_HOSTS=${process.env.AGENTAPI_ALLOWED_HOSTS}
26+
AGENTAPI_CHAT_BASE_PATH=${process.env.AGENTAPI_CHAT_BASE_PATH}`,
2627
);
2728

2829
console.log(`starting server on port ${port}`);

0 commit comments

Comments
 (0)