diff --git a/registry/coder/modules/claude-code/README.md b/registry/coder/modules/claude-code/README.md index 657435f96..11172010f 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 = "4.2.6" + version = "4.2.7" agent_id = coder_agent.main.id workdir = "/home/coder/project" claude_api_key = "xxxx-xxxxx-xxxx" @@ -45,7 +45,7 @@ This example shows how to configure the Claude Code module to run the agent behi ```tf module "claude-code" { source = "dev.registry.coder.com/coder/claude-code/coder" - version = "4.2.6" + version = "4.2.7" agent_id = coder_agent.main.id workdir = "/home/coder/project" enable_boundary = true @@ -72,7 +72,7 @@ data "coder_parameter" "ai_prompt" { module "claude-code" { source = "registry.coder.com/coder/claude-code/coder" - version = "4.2.6" + version = "4.2.7" agent_id = coder_agent.main.id workdir = "/home/coder/project" @@ -92,10 +92,9 @@ module "claude-code" { { "mcpServers": { "my-custom-tool": { - "command": "my-tool-server" + "command": "my-tool-server", "args": ["--port", "8080"] } - } } EOF @@ -109,7 +108,7 @@ Run and configure Claude Code as a standalone CLI in your workspace. ```tf module "claude-code" { source = "registry.coder.com/coder/claude-code/coder" - version = "4.2.6" + version = "4.2.7" agent_id = coder_agent.main.id workdir = "/home/coder/project" install_claude_code = true @@ -131,7 +130,7 @@ variable "claude_code_oauth_token" { module "claude-code" { source = "registry.coder.com/coder/claude-code/coder" - version = "4.2.6" + version = "4.2.7" agent_id = coder_agent.main.id workdir = "/home/coder/project" claude_code_oauth_token = var.claude_code_oauth_token @@ -204,7 +203,7 @@ resource "coder_env" "bedrock_api_key" { module "claude-code" { source = "registry.coder.com/coder/claude-code/coder" - version = "4.2.6" + version = "4.2.7" agent_id = coder_agent.main.id workdir = "/home/coder/project" model = "global.anthropic.claude-sonnet-4-5-20250929-v1:0" @@ -261,7 +260,7 @@ resource "coder_env" "google_application_credentials" { module "claude-code" { source = "registry.coder.com/coder/claude-code/coder" - version = "4.2.6" + version = "4.2.7" agent_id = coder_agent.main.id workdir = "/home/coder/project" model = "claude-sonnet-4@20250514" diff --git a/registry/coder/modules/claude-code/main.test.ts b/registry/coder/modules/claude-code/main.test.ts index 6e37501da..c62493cf8 100644 --- a/registry/coder/modules/claude-code/main.test.ts +++ b/registry/coder/modules/claude-code/main.test.ts @@ -39,9 +39,11 @@ interface SetupProps { agentapiMockScript?: string; } -const setup = async (props?: SetupProps): Promise<{ id: string }> => { +const setup = async ( + props?: SetupProps, +): Promise<{ id: string; coderEnvVars: Record }> => { const projectDir = "/home/coder/project"; - const { id } = await setupUtil({ + const { id, coderEnvVars } = await setupUtil({ moduleDir: import.meta.dir, moduleVariables: { install_claude_code: props?.skipClaudeMock ? "true" : "false", @@ -61,7 +63,7 @@ const setup = async (props?: SetupProps): Promise<{ id: string }> => { content: await loadTestFile(import.meta.dir, "claude-mock.sh"), }); } - return { id }; + return { id, coderEnvVars }; }; setDefaultTimeout(60 * 1000); @@ -79,14 +81,14 @@ describe("claude-code", async () => { test("install-claude-code-version", async () => { const version_to_install = "1.0.40"; - const { id } = await setup({ + const { id, coderEnvVars } = await setup({ skipClaudeMock: true, moduleVariables: { install_claude_code: "true", claude_code_version: version_to_install, }, }); - await execModuleScript(id); + await execModuleScript(id, coderEnvVars); const resp = await execContainer(id, [ "bash", "-c", @@ -96,14 +98,14 @@ describe("claude-code", async () => { }); test("check-latest-claude-code-version-works", async () => { - const { id } = await setup({ + const { id, coderEnvVars } = await setup({ skipClaudeMock: true, skipAgentAPIMock: true, moduleVariables: { install_claude_code: "true", }, }); - await execModuleScript(id); + await execModuleScript(id, coderEnvVars); await expectAgentAPIStarted(id); }); @@ -133,13 +135,13 @@ describe("claude-code", async () => { }, }, }); - const { id } = await setup({ + const { id, coderEnvVars } = await setup({ skipClaudeMock: true, moduleVariables: { mcp: mcpConfig, }, }); - await execModuleScript(id); + await execModuleScript(id, coderEnvVars); const resp = await readFileContainer(id, "/home/coder/.claude.json"); expect(resp).toContain("test-cmd"); diff --git a/registry/coder/modules/claude-code/main.tf b/registry/coder/modules/claude-code/main.tf index bef2a219e..8531a9f9a 100644 --- a/registry/coder/modules/claude-code/main.tf +++ b/registry/coder/modules/claude-code/main.tf @@ -288,6 +288,12 @@ resource "coder_env" "disable_autoupdater" { value = "1" } +resource "coder_env" "claude_binary_path" { + agent_id = var.agent_id + name = "PATH" + value = "$HOME/.local/bin:$PATH" +} + locals { # we have to trim the slash because otherwise coder exp mcp will # set up an invalid claude config diff --git a/registry/coder/modules/claude-code/scripts/install.sh b/registry/coder/modules/claude-code/scripts/install.sh index ba4420fa3..15981e8b5 100644 --- a/registry/coder/modules/claude-code/scripts/install.sh +++ b/registry/coder/modules/claude-code/scripts/install.sh @@ -1,10 +1,5 @@ #!/bin/bash -if [ -f "$HOME/.bashrc" ]; then - source "$HOME"/.bashrc -fi - -# Set strict error handling AFTER sourcing bashrc to avoid unbound variable errors from user dotfiles set -euo pipefail BOLD='\033[0;1m' @@ -45,11 +40,6 @@ function install_claude_code_cli() { if [ $CURL_EXIT -ne 0 ]; then echo "Claude Code installer failed with exit code $$CURL_EXIT" fi - - # Ensure binaries are discoverable. - echo "Creating a symlink for claude" - sudo ln -s /home/coder/.local/bin/claude /usr/local/bin/claude - echo "Installed Claude Code successfully. Version: $(claude --version || echo 'unknown')" else echo "Skipping Claude Code installation as per configuration." diff --git a/registry/coder/modules/claude-code/scripts/start.sh b/registry/coder/modules/claude-code/scripts/start.sh index 93ff4f723..ebca736cc 100644 --- a/registry/coder/modules/claude-code/scripts/start.sh +++ b/registry/coder/modules/claude-code/scripts/start.sh @@ -1,14 +1,7 @@ #!/bin/bash -if [ -f "$HOME/.bashrc" ]; then - source "$HOME"/.bashrc -fi - -# Set strict error handling AFTER sourcing bashrc to avoid unbound variable errors from user dotfiles set -euo pipefail -export PATH="$HOME/.local/bin:$PATH" - command_exists() { command -v "$1" > /dev/null 2>&1 }