From fb4a8977682cb4d4d50d2f1ab96b3a84008350eb Mon Sep 17 00:00:00 2001 From: Riajul Islam Date: Sun, 1 Mar 2026 11:57:19 +0600 Subject: [PATCH 1/4] fix: respect `CLAUDE_CODE_OAUTH_TOKEN` env authentication check in standalone mode Update guard condition to skip authentication only when: - CLAUDE_API_KEY is unset - CLAUDE_CODE_OAUTH_TOKEN is unset - ARG_ENABLE_AIBRIDGE is false This enables authentication flow for OAuth-based usage and AIBridge scenarios. --- registry/coder/modules/claude-code/scripts/install.sh | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/registry/coder/modules/claude-code/scripts/install.sh b/registry/coder/modules/claude-code/scripts/install.sh index 0a2ba7033..0b2e8f624 100644 --- a/registry/coder/modules/claude-code/scripts/install.sh +++ b/registry/coder/modules/claude-code/scripts/install.sh @@ -179,8 +179,10 @@ function setup_claude_configurations() { function configure_standalone_mode() { echo "Configuring Claude Code for standalone mode..." - if [ -z "${CLAUDE_API_KEY:-}" ] && [ "$ARG_ENABLE_AIBRIDGE" = "false" ]; then - echo "Note: Neither claude_api_key nor enable_aibridge is set, skipping authentication setup" + if [ -z "${CLAUDE_API_KEY:-}" ] \ + && [ -z "${CLAUDE_CODE_OAUTH_TOKEN:-}" ] \ + && [ "${ARG_ENABLE_AIBRIDGE:-false}" = "false" ]; then + echo "Note: No CLAUDE_API_KEY, no CLAUDE_CODE_OAUTH_TOKEN, and AIBridge disabled — skipping authentication setup" return fi From 2e19ba05d8d16d596cfc7c0a3313c28f27a5f77a Mon Sep 17 00:00:00 2001 From: Riajul Islam Date: Sun, 1 Mar 2026 12:01:12 +0600 Subject: [PATCH 2/4] style: code formatting fixed. --- registry/coder/modules/claude-code/scripts/install.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/registry/coder/modules/claude-code/scripts/install.sh b/registry/coder/modules/claude-code/scripts/install.sh index 0b2e8f624..7dd36ac59 100644 --- a/registry/coder/modules/claude-code/scripts/install.sh +++ b/registry/coder/modules/claude-code/scripts/install.sh @@ -180,8 +180,8 @@ function configure_standalone_mode() { echo "Configuring Claude Code for standalone mode..." if [ -z "${CLAUDE_API_KEY:-}" ] \ - && [ -z "${CLAUDE_CODE_OAUTH_TOKEN:-}" ] \ - && [ "${ARG_ENABLE_AIBRIDGE:-false}" = "false" ]; then + && [ -z "${CLAUDE_CODE_OAUTH_TOKEN:-}" ] \ + && [ "${ARG_ENABLE_AIBRIDGE:-false}" = "false" ]; then echo "Note: No CLAUDE_API_KEY, no CLAUDE_CODE_OAUTH_TOKEN, and AIBridge disabled — skipping authentication setup" return fi From 17bd752dc74934e2127d611a28ad2dba2d755c06 Mon Sep 17 00:00:00 2001 From: Riajul Islam Date: Sun, 1 Mar 2026 12:02:23 +0600 Subject: [PATCH 3/4] chore: bump module versions (patch) --- registry/coder/modules/claude-code/README.md | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/registry/coder/modules/claude-code/README.md b/registry/coder/modules/claude-code/README.md index 340eb175d..a78a2e501 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.7.5" + version = "4.7.6" agent_id = coder_agent.main.id workdir = "/home/coder/project" claude_api_key = "xxxx-xxxxx-xxxx" @@ -47,7 +47,7 @@ By default, when `enable_boundary = true`, the module uses `coder boundary` subc ```tf module "claude-code" { source = "registry.coder.com/coder/claude-code/coder" - version = "4.7.5" + version = "4.7.6" agent_id = coder_agent.main.id workdir = "/home/coder/project" enable_boundary = true @@ -68,7 +68,7 @@ For tasks integration with AI Bridge, add `enable_aibridge = true` to the [Usage ```tf module "claude-code" { source = "registry.coder.com/coder/claude-code/coder" - version = "4.7.5" + version = "4.7.6" agent_id = coder_agent.main.id workdir = "/home/coder/project" enable_aibridge = true @@ -97,7 +97,7 @@ data "coder_task" "me" {} module "claude-code" { source = "registry.coder.com/coder/claude-code/coder" - version = "4.7.5" + version = "4.7.6" agent_id = coder_agent.main.id workdir = "/home/coder/project" ai_prompt = data.coder_task.me.prompt @@ -120,7 +120,7 @@ This example shows additional configuration options for version pinning, custom ```tf module "claude-code" { source = "registry.coder.com/coder/claude-code/coder" - version = "4.7.5" + version = "4.7.6" agent_id = coder_agent.main.id workdir = "/home/coder/project" @@ -176,7 +176,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.7.5" + version = "4.7.6" agent_id = coder_agent.main.id workdir = "/home/coder/project" install_claude_code = true @@ -198,7 +198,7 @@ variable "claude_code_oauth_token" { module "claude-code" { source = "registry.coder.com/coder/claude-code/coder" - version = "4.7.5" + version = "4.7.6" agent_id = coder_agent.main.id workdir = "/home/coder/project" claude_code_oauth_token = var.claude_code_oauth_token @@ -271,7 +271,7 @@ resource "coder_env" "bedrock_api_key" { module "claude-code" { source = "registry.coder.com/coder/claude-code/coder" - version = "4.7.5" + version = "4.7.6" agent_id = coder_agent.main.id workdir = "/home/coder/project" model = "global.anthropic.claude-sonnet-4-5-20250929-v1:0" @@ -328,7 +328,7 @@ resource "coder_env" "google_application_credentials" { module "claude-code" { source = "registry.coder.com/coder/claude-code/coder" - version = "4.7.5" + version = "4.7.6" agent_id = coder_agent.main.id workdir = "/home/coder/project" model = "claude-sonnet-4@20250514" From f56068907c9d200935e89b74ec7e8e5886baf9c8 Mon Sep 17 00:00:00 2001 From: Riajul Islam Date: Wed, 11 Mar 2026 12:02:38 +0600 Subject: [PATCH 4/4] fix: preserve claude api key in standalone oauth mode --- .../coder/modules/claude-code/main.test.ts | 52 +++++++++++++++++++ .../modules/claude-code/scripts/install.sh | 36 ++++++------- 2 files changed, 69 insertions(+), 19 deletions(-) diff --git a/registry/coder/modules/claude-code/main.test.ts b/registry/coder/modules/claude-code/main.test.ts index 19ab98c04..1f3904a32 100644 --- a/registry/coder/modules/claude-code/main.test.ts +++ b/registry/coder/modules/claude-code/main.test.ts @@ -415,6 +415,58 @@ EOF`, expect(startLog.stdout).toContain("--continue"); }); + test("standalone-oauth-only-does-not-create-empty-primary-api-key", async () => { + const { id, coderEnvVars } = await setup({ + moduleVariables: { + report_tasks: "false", + claude_code_oauth_token: "oauth-token-123", + }, + }); + + await execModuleScript(id, coderEnvVars); + + const claudeConfig = JSON.parse( + await readFileContainer(id, "/home/coder/.claude.json"), + ); + + expect(claudeConfig.primaryApiKey).toBeUndefined(); + expect(claudeConfig.hasCompletedOnboarding).toBe(true); + expect( + claudeConfig.projects["/home/coder/project"] + .hasCompletedProjectOnboarding, + ).toBe(true); + }); + + test("standalone-oauth-only-preserves-existing-primary-api-key", async () => { + const existingApiKey = "existing-api-key"; + const { id, coderEnvVars } = await setup({ + moduleVariables: { + report_tasks: "false", + claude_code_oauth_token: "oauth-token-123", + }, + }); + + await execContainer(id, [ + "bash", + "-c", + `cat > /home/coder/.claude.json << 'EOF' +{"primaryApiKey":"${existingApiKey}","projects":{}} +EOF`, + ]); + + await execModuleScript(id, coderEnvVars); + + const claudeConfig = JSON.parse( + await readFileContainer(id, "/home/coder/.claude.json"), + ); + + expect(claudeConfig.primaryApiKey).toBe(existingApiKey); + expect(claudeConfig.hasCompletedOnboarding).toBe(true); + expect( + claudeConfig.projects["/home/coder/project"].hasTrustDialogAccepted, + ).toBe(true); + }); + test("task-mode-ignores-manual-sessions", async () => { const { id } = await setup({ moduleVariables: { diff --git a/registry/coder/modules/claude-code/scripts/install.sh b/registry/coder/modules/claude-code/scripts/install.sh index 7dd36ac59..da02691a9 100644 --- a/registry/coder/modules/claude-code/scripts/install.sh +++ b/registry/coder/modules/claude-code/scripts/install.sh @@ -187,8 +187,6 @@ function configure_standalone_mode() { fi local claude_config="$HOME/.claude.json" - local workdir_normalized - workdir_normalized=$(echo "$ARG_WORKDIR" | tr '/' '-') # Create or update .claude.json with minimal configuration for API key auth # This skips the interactive login prompt and onboarding screens @@ -200,27 +198,27 @@ function configure_standalone_mode() { .bypassPermissionsModeAccepted = true | .hasAcknowledgedCostThreshold = true | .hasCompletedOnboarding = true | - .primaryApiKey = $apikey | .projects[$workdir].hasCompletedProjectOnboarding = true | - .projects[$workdir].hasTrustDialogAccepted = true' \ + .projects[$workdir].hasTrustDialogAccepted = true | + if $apikey != "" then .primaryApiKey = $apikey else . end' \ "$claude_config" > "${claude_config}.tmp" && mv "${claude_config}.tmp" "$claude_config" else echo "Creating new Claude configuration at $claude_config" - cat > "$claude_config" << EOF -{ - "autoUpdaterStatus": "disabled", - "bypassPermissionsModeAccepted": true, - "hasAcknowledgedCostThreshold": true, - "hasCompletedOnboarding": true, - "primaryApiKey": "${CLAUDE_API_KEY:-}", - "projects": { - "$ARG_WORKDIR": { - "hasCompletedProjectOnboarding": true, - "hasTrustDialogAccepted": true - } - } -} -EOF + jq -n --arg workdir "$ARG_WORKDIR" --arg apikey "${CLAUDE_API_KEY:-}" \ + '{ + autoUpdaterStatus: "disabled", + bypassPermissionsModeAccepted: true, + hasAcknowledgedCostThreshold: true, + hasCompletedOnboarding: true, + projects: { + ($workdir): { + hasCompletedProjectOnboarding: true, + hasTrustDialogAccepted: true + } + } + } | + if $apikey != "" then . + {primaryApiKey: $apikey} else . end' \ + > "$claude_config" fi echo "Standalone mode configured successfully"