From eb2da40cf7afbe0e2075151104456283a598e9b8 Mon Sep 17 00:00:00 2001 From: DevelopmentCats Date: Wed, 11 Mar 2026 16:36:57 -0500 Subject: [PATCH 1/8] feat: enhance boundary configuration options in Claude Code module - Added new variables `boundary_config` and `boundary_config_path` for inline YAML and file path configurations, respectively. - Implemented validation rules to ensure proper configuration when `enable_boundary` is true. - Updated README with usage examples for both configuration methods. - Enhanced test cases to cover various boundary configuration scenarios, including validation failures. --- registry/coder/modules/claude-code/README.md | 30 +++++- registry/coder/modules/claude-code/main.tf | 29 ++++++ .../coder/modules/claude-code/main.tftest.hcl | 93 ++++++++++++++++++- .../modules/claude-code/scripts/start.sh | 17 ++++ 4 files changed, 167 insertions(+), 2 deletions(-) diff --git a/registry/coder/modules/claude-code/README.md b/registry/coder/modules/claude-code/README.md index ea845f6ec..76f656dc1 100644 --- a/registry/coder/modules/claude-code/README.md +++ b/registry/coder/modules/claude-code/README.md @@ -55,7 +55,14 @@ module "claude-code" { This example shows how to configure the Claude Code module to run the agent behind a process-level boundary that restricts its network access. -By default, when `enable_boundary = true`, the module uses `coder boundary` subcommand (provided by Coder) without requiring any installation. +When `enable_boundary = true`, you must provide network filtering rules via one of two options: + +- `boundary_config` — inline YAML string (config lives in the template) +- `boundary_config_path` — path to a config file already on disk + +The module writes the config to `~/.config/coder_boundary/config.yaml` automatically. + +#### Inline boundary config ```tf module "claude-code" { @@ -64,6 +71,27 @@ module "claude-code" { agent_id = coder_agent.main.id workdir = "/home/coder/project" enable_boundary = true + + boundary_config = <<-EOT + allow: + - "*.anthropic.com" + - "*.github.com" + EOT +} +``` + +#### Boundary config from file path + +Use this when the config file is provisioned separately or managed outside the template: + +```tf +module "claude-code" { + source = "registry.coder.com/coder/claude-code/coder" + version = "4.8.0" + agent_id = coder_agent.main.id + workdir = "/home/coder/project" + enable_boundary = true + boundary_config_path = "/home/coder/.config/coder_boundary/config.yaml" } ``` diff --git a/registry/coder/modules/claude-code/main.tf b/registry/coder/modules/claude-code/main.tf index 7a08aa82f..c35fd05de 100644 --- a/registry/coder/modules/claude-code/main.tf +++ b/registry/coder/modules/claude-code/main.tf @@ -231,6 +231,33 @@ variable "enable_boundary" { type = bool description = "Whether to enable coder boundary for network filtering" default = false + + validation { + condition = !var.enable_boundary || var.boundary_config != null || var.boundary_config_path != null + error_message = "When enable_boundary is true, at least one of boundary_config or boundary_config_path must be provided." + } + + validation { + condition = !var.enable_boundary || var.boundary_config == null || var.boundary_config_path == null + error_message = "Only one of boundary_config or boundary_config_path can be provided, not both." + } + + validation { + condition = (var.boundary_config == null && var.boundary_config_path == null) || var.enable_boundary + error_message = "boundary_config and boundary_config_path can only be set when enable_boundary is true." + } +} + +variable "boundary_config" { + type = string + description = "Inline YAML config for coder boundary network filtering rules. Written to ~/.config/coder_boundary/config.yaml before boundary starts. Mutually exclusive with boundary_config_path." + default = null +} + +variable "boundary_config_path" { + type = string + description = "Path to an existing boundary config file on disk. Symlinked to ~/.config/coder_boundary/config.yaml before boundary starts. Mutually exclusive with boundary_config." + default = null } variable "boundary_version" { @@ -407,6 +434,8 @@ module "agentapi" { ARG_COMPILE_FROM_SOURCE='${var.compile_boundary_from_source}' \ ARG_USE_BOUNDARY_DIRECTLY='${var.use_boundary_directly}' \ ARG_CODER_HOST='${local.coder_host}' \ + ARG_BOUNDARY_CONFIG='${var.boundary_config != null ? base64encode(var.boundary_config) : ""}' \ + ARG_BOUNDARY_CONFIG_PATH='${var.boundary_config_path != null ? var.boundary_config_path : ""}' \ ARG_CLAUDE_BINARY_PATH='${var.claude_binary_path}' \ /tmp/start.sh EOT diff --git a/registry/coder/modules/claude-code/main.tftest.hcl b/registry/coder/modules/claude-code/main.tftest.hcl index 66c79bab7..9646c5da6 100644 --- a/registry/coder/modules/claude-code/main.tftest.hcl +++ b/registry/coder/modules/claude-code/main.tftest.hcl @@ -188,13 +188,18 @@ run "test_claude_code_permission_mode_validation" { } } -run "test_claude_code_with_boundary" { +run "test_claude_code_with_boundary_inline_config" { command = plan variables { agent_id = "test-agent-boundary" workdir = "/home/coder/boundary-test" enable_boundary = true + boundary_config = <<-EOT + allow: + - "*.anthropic.com" + - "*.github.com" + EOT } assert { @@ -202,12 +207,98 @@ run "test_claude_code_with_boundary" { error_message = "Boundary should be enabled" } + assert { + condition = var.boundary_config != null + error_message = "Boundary config should be set" + } + assert { condition = local.coder_host != "" error_message = "Coder host should be extracted from access URL" } } +run "test_claude_code_with_boundary_config_path" { + command = plan + + variables { + agent_id = "test-agent-boundary-path" + workdir = "/home/coder/boundary-test" + enable_boundary = true + boundary_config_path = "/home/coder/.config/coder_boundary/config.yaml" + } + + assert { + condition = var.enable_boundary == true + error_message = "Boundary should be enabled" + } + + assert { + condition = var.boundary_config_path == "/home/coder/.config/coder_boundary/config.yaml" + error_message = "Boundary config path should be set correctly" + } +} + +run "test_boundary_without_config_fails" { + command = plan + + variables { + agent_id = "test-agent-boundary-fail" + workdir = "/home/coder/boundary-test" + enable_boundary = true + } + + expect_failures = [ + var.enable_boundary, + ] +} + +run "test_boundary_both_configs_fails" { + command = plan + + variables { + agent_id = "test-agent-boundary-both" + workdir = "/home/coder/boundary-test" + enable_boundary = true + boundary_config = "allow:\n - '*.example.com'" + boundary_config_path = "/home/coder/.config/coder_boundary/config.yaml" + } + + expect_failures = [ + var.enable_boundary, + ] +} + +run "test_boundary_config_without_boundary_fails" { + command = plan + + variables { + agent_id = "test-agent-no-boundary" + workdir = "/home/coder/boundary-test" + enable_boundary = false + boundary_config = "allow:\n - '*.example.com'" + } + + expect_failures = [ + var.enable_boundary, + ] +} + +run "test_boundary_config_path_without_boundary_fails" { + command = plan + + variables { + agent_id = "test-agent-no-boundary-path" + workdir = "/home/coder/boundary-test" + enable_boundary = false + boundary_config_path = "/home/coder/.config/coder_boundary/config.yaml" + } + + expect_failures = [ + var.enable_boundary, + ] +} + run "test_claude_code_system_prompt" { command = plan diff --git a/registry/coder/modules/claude-code/scripts/start.sh b/registry/coder/modules/claude-code/scripts/start.sh index 5ccbc8fa1..0567772e5 100644 --- a/registry/coder/modules/claude-code/scripts/start.sh +++ b/registry/coder/modules/claude-code/scripts/start.sh @@ -24,6 +24,8 @@ ARG_BOUNDARY_VERSION=${ARG_BOUNDARY_VERSION:-"latest"} ARG_COMPILE_FROM_SOURCE=${ARG_COMPILE_FROM_SOURCE:-false} ARG_USE_BOUNDARY_DIRECTLY=${ARG_USE_BOUNDARY_DIRECTLY:-false} ARG_CODER_HOST=${ARG_CODER_HOST:-} +ARG_BOUNDARY_CONFIG=${ARG_BOUNDARY_CONFIG:-} +ARG_BOUNDARY_CONFIG_PATH=${ARG_BOUNDARY_CONFIG_PATH:-} echo "--------------------------------" @@ -223,6 +225,21 @@ function start_agentapi() { printf "Running claude code with args: %s\n" "$(printf '%q ' "${ARGS[@]}")" if [ "$ARG_ENABLE_BOUNDARY" = "true" ]; then + BOUNDARY_CONFIG_DIR="$HOME/.config/coder_boundary" + BOUNDARY_CONFIG_FILE="$BOUNDARY_CONFIG_DIR/config.yaml" + + if [ -n "$ARG_BOUNDARY_CONFIG" ]; then + printf "Writing inline boundary config to %s\n" "$BOUNDARY_CONFIG_FILE" + mkdir -p "$BOUNDARY_CONFIG_DIR" + echo -n "$ARG_BOUNDARY_CONFIG" | base64 -d > "$BOUNDARY_CONFIG_FILE" + elif [ -n "$ARG_BOUNDARY_CONFIG_PATH" ]; then + printf "Linking boundary config from %s to %s\n" "$ARG_BOUNDARY_CONFIG_PATH" "$BOUNDARY_CONFIG_FILE" + if [ "$ARG_BOUNDARY_CONFIG_PATH" != "$BOUNDARY_CONFIG_FILE" ]; then + mkdir -p "$BOUNDARY_CONFIG_DIR" + ln -sf "$ARG_BOUNDARY_CONFIG_PATH" "$BOUNDARY_CONFIG_FILE" + fi + fi + install_boundary printf "Starting with coder boundary enabled\n" From 9578f81982acdc847fbdcdc338de63715b29c96d Mon Sep 17 00:00:00 2001 From: DevelopmentCats Date: Wed, 11 Mar 2026 16:41:23 -0500 Subject: [PATCH 2/8] chore: update Claude Code module version to 4.9.0 in README --- 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 76f656dc1..01d00f1de 100644 --- a/registry/coder/modules/claude-code/README.md +++ b/registry/coder/modules/claude-code/README.md @@ -87,7 +87,7 @@ Use this when the config file is provisioned separately or managed outside the t ```tf module "claude-code" { source = "registry.coder.com/coder/claude-code/coder" - version = "4.8.0" + version = "4.9.0" agent_id = coder_agent.main.id workdir = "/home/coder/project" enable_boundary = true From fe3cf30ac2c224b9c3d8642fad51552dbdeb2080 Mon Sep 17 00:00:00 2001 From: DevelopmentCats Date: Thu, 12 Mar 2026 08:29:18 -0500 Subject: [PATCH 3/8] refactor: button up boundary related testing --- registry/coder/modules/claude-code/main.tf | 12 +++---- .../coder/modules/claude-code/main.tftest.hcl | 32 +++++++++++++++---- 2 files changed, 29 insertions(+), 15 deletions(-) diff --git a/registry/coder/modules/claude-code/main.tf b/registry/coder/modules/claude-code/main.tf index c35fd05de..099d04924 100644 --- a/registry/coder/modules/claude-code/main.tf +++ b/registry/coder/modules/claude-code/main.tf @@ -232,11 +232,6 @@ variable "enable_boundary" { description = "Whether to enable coder boundary for network filtering" default = false - validation { - condition = !var.enable_boundary || var.boundary_config != null || var.boundary_config_path != null - error_message = "When enable_boundary is true, at least one of boundary_config or boundary_config_path must be provided." - } - validation { condition = !var.enable_boundary || var.boundary_config == null || var.boundary_config_path == null error_message = "Only one of boundary_config or boundary_config_path can be provided, not both." @@ -358,8 +353,9 @@ locals { start_script = file("${path.module}/scripts/start.sh") module_dir_name = ".claude-module" # Extract hostname from access_url for boundary --allow flag - coder_host = replace(replace(data.coder_workspace.me.access_url, "https://", ""), "http://", "") - claude_api_key = var.enable_aibridge ? data.coder_workspace_owner.me.session_token : var.claude_api_key + coder_host = replace(replace(data.coder_workspace.me.access_url, "https://", ""), "http://", "") + boundary_config_b64 = var.boundary_config != null ? base64encode(var.boundary_config) : "" + claude_api_key = var.enable_aibridge ? data.coder_workspace_owner.me.session_token : var.claude_api_key # Required prompts for the module to properly report task status to Coder report_tasks_system_prompt = <<-EOT @@ -434,7 +430,7 @@ module "agentapi" { ARG_COMPILE_FROM_SOURCE='${var.compile_boundary_from_source}' \ ARG_USE_BOUNDARY_DIRECTLY='${var.use_boundary_directly}' \ ARG_CODER_HOST='${local.coder_host}' \ - ARG_BOUNDARY_CONFIG='${var.boundary_config != null ? base64encode(var.boundary_config) : ""}' \ + ARG_BOUNDARY_CONFIG='${local.boundary_config_b64}' \ ARG_BOUNDARY_CONFIG_PATH='${var.boundary_config_path != null ? var.boundary_config_path : ""}' \ ARG_CLAUDE_BINARY_PATH='${var.claude_binary_path}' \ /tmp/start.sh diff --git a/registry/coder/modules/claude-code/main.tftest.hcl b/registry/coder/modules/claude-code/main.tftest.hcl index 9646c5da6..97d0c905f 100644 --- a/registry/coder/modules/claude-code/main.tftest.hcl +++ b/registry/coder/modules/claude-code/main.tftest.hcl @@ -202,6 +202,13 @@ run "test_claude_code_with_boundary_inline_config" { EOT } + override_data { + target = data.coder_workspace.me + values = { + access_url = "https://coder.example.com" + } + } + assert { condition = var.enable_boundary == true error_message = "Boundary should be enabled" @@ -213,8 +220,18 @@ run "test_claude_code_with_boundary_inline_config" { } assert { - condition = local.coder_host != "" - error_message = "Coder host should be extracted from access URL" + condition = local.coder_host == "coder.example.com" + error_message = "Coder host should be 'coder.example.com' after stripping https:// from access URL" + } + + assert { + condition = local.boundary_config_b64 != "" + error_message = "Boundary config should be base64-encoded for the start script" + } + + assert { + condition = base64decode(local.boundary_config_b64) == var.boundary_config + error_message = "Base64-encoded boundary config should decode back to the original config" } } @@ -239,18 +256,19 @@ run "test_claude_code_with_boundary_config_path" { } } -run "test_boundary_without_config_fails" { +run "test_claude_code_with_boundary_no_config" { command = plan variables { - agent_id = "test-agent-boundary-fail" + agent_id = "test-agent-boundary" workdir = "/home/coder/boundary-test" enable_boundary = true } - expect_failures = [ - var.enable_boundary, - ] + assert { + condition = var.enable_boundary == true + error_message = "Boundary should be enabled" + } } run "test_boundary_both_configs_fails" { From 352b7752fb262f856401b3c270434e9d087dbf99 Mon Sep 17 00:00:00 2001 From: DevelopmentCats Date: Thu, 12 Mar 2026 08:58:22 -0500 Subject: [PATCH 4/8] feat: address comments from Copilot and tighten up config behaviour and validation --- registry/coder/modules/claude-code/main.tf | 10 ++++ .../coder/modules/claude-code/main.tftest.hcl | 60 +++++++++++++++++++ .../modules/claude-code/scripts/start.sh | 7 +++ 3 files changed, 77 insertions(+) diff --git a/registry/coder/modules/claude-code/main.tf b/registry/coder/modules/claude-code/main.tf index 099d04924..a8a781c3a 100644 --- a/registry/coder/modules/claude-code/main.tf +++ b/registry/coder/modules/claude-code/main.tf @@ -247,12 +247,22 @@ variable "boundary_config" { type = string description = "Inline YAML config for coder boundary network filtering rules. Written to ~/.config/coder_boundary/config.yaml before boundary starts. Mutually exclusive with boundary_config_path." default = null + + validation { + condition = var.boundary_config == null || trimspace(var.boundary_config) != "" + error_message = "boundary_config must not be empty or whitespace-only when provided." + } } variable "boundary_config_path" { type = string description = "Path to an existing boundary config file on disk. Symlinked to ~/.config/coder_boundary/config.yaml before boundary starts. Mutually exclusive with boundary_config." default = null + + validation { + condition = var.boundary_config_path == null || trimspace(var.boundary_config_path) != "" + error_message = "boundary_config_path must not be empty or whitespace-only when provided." + } } variable "boundary_version" { diff --git a/registry/coder/modules/claude-code/main.tftest.hcl b/registry/coder/modules/claude-code/main.tftest.hcl index 97d0c905f..44ca6501d 100644 --- a/registry/coder/modules/claude-code/main.tftest.hcl +++ b/registry/coder/modules/claude-code/main.tftest.hcl @@ -317,6 +317,66 @@ run "test_boundary_config_path_without_boundary_fails" { ] } +run "test_boundary_empty_config_fails" { + command = plan + + variables { + agent_id = "test-agent-empty-config" + workdir = "/home/coder/boundary-test" + enable_boundary = true + boundary_config = "" + } + + expect_failures = [ + var.boundary_config, + ] +} + +run "test_boundary_empty_config_path_fails" { + command = plan + + variables { + agent_id = "test-agent-empty-config-path" + workdir = "/home/coder/boundary-test" + enable_boundary = true + boundary_config_path = "" + } + + expect_failures = [ + var.boundary_config_path, + ] +} + +run "test_boundary_whitespace_config_fails" { + command = plan + + variables { + agent_id = "test-agent-whitespace-config" + workdir = "/home/coder/boundary-test" + enable_boundary = true + boundary_config = " " + } + + expect_failures = [ + var.boundary_config, + ] +} + +run "test_boundary_whitespace_config_path_fails" { + command = plan + + variables { + agent_id = "test-agent-whitespace-config-path" + workdir = "/home/coder/boundary-test" + enable_boundary = true + boundary_config_path = " " + } + + expect_failures = [ + var.boundary_config_path, + ] +} + run "test_claude_code_system_prompt" { command = plan diff --git a/registry/coder/modules/claude-code/scripts/start.sh b/registry/coder/modules/claude-code/scripts/start.sh index 0567772e5..f85c6ca13 100644 --- a/registry/coder/modules/claude-code/scripts/start.sh +++ b/registry/coder/modules/claude-code/scripts/start.sh @@ -26,6 +26,8 @@ ARG_USE_BOUNDARY_DIRECTLY=${ARG_USE_BOUNDARY_DIRECTLY:-false} ARG_CODER_HOST=${ARG_CODER_HOST:-} ARG_BOUNDARY_CONFIG=${ARG_BOUNDARY_CONFIG:-} ARG_BOUNDARY_CONFIG_PATH=${ARG_BOUNDARY_CONFIG_PATH:-} +ARG_BOUNDARY_CONFIG_PATH="${ARG_BOUNDARY_CONFIG_PATH/#\~/$HOME}" +ARG_BOUNDARY_CONFIG_PATH="${ARG_BOUNDARY_CONFIG_PATH//\$HOME/$HOME}" echo "--------------------------------" @@ -240,6 +242,11 @@ function start_agentapi() { fi fi + if [ ! -s "$BOUNDARY_CONFIG_FILE" ]; then + printf "Error: boundary configuration file '%s' does not exist or is empty. Check boundary_config/boundary_config_path.\n" "$BOUNDARY_CONFIG_FILE" >&2 + exit 1 + fi + install_boundary printf "Starting with coder boundary enabled\n" From 5f83d8188ac81ed957a00fc661f2ad883caa7519 Mon Sep 17 00:00:00 2001 From: DevelopmentCats Date: Thu, 12 Mar 2026 13:12:05 -0500 Subject: [PATCH 5/8] fix: improve boundary configuration validation in start script - Added a check to ensure the boundary configuration file is not empty after writing inline config. - Enhanced error messages for better clarity on configuration issues. --- registry/coder/modules/claude-code/scripts/start.sh | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/registry/coder/modules/claude-code/scripts/start.sh b/registry/coder/modules/claude-code/scripts/start.sh index f85c6ca13..c0b89ade0 100644 --- a/registry/coder/modules/claude-code/scripts/start.sh +++ b/registry/coder/modules/claude-code/scripts/start.sh @@ -234,17 +234,20 @@ function start_agentapi() { printf "Writing inline boundary config to %s\n" "$BOUNDARY_CONFIG_FILE" mkdir -p "$BOUNDARY_CONFIG_DIR" echo -n "$ARG_BOUNDARY_CONFIG" | base64 -d > "$BOUNDARY_CONFIG_FILE" + if [ ! -s "$BOUNDARY_CONFIG_FILE" ]; then + printf "Error: boundary configuration file '%s' does not exist or is empty after writing inline config.\n" "$BOUNDARY_CONFIG_FILE" >&2 + exit 1 + fi elif [ -n "$ARG_BOUNDARY_CONFIG_PATH" ]; then printf "Linking boundary config from %s to %s\n" "$ARG_BOUNDARY_CONFIG_PATH" "$BOUNDARY_CONFIG_FILE" if [ "$ARG_BOUNDARY_CONFIG_PATH" != "$BOUNDARY_CONFIG_FILE" ]; then mkdir -p "$BOUNDARY_CONFIG_DIR" ln -sf "$ARG_BOUNDARY_CONFIG_PATH" "$BOUNDARY_CONFIG_FILE" fi - fi - - if [ ! -s "$BOUNDARY_CONFIG_FILE" ]; then - printf "Error: boundary configuration file '%s' does not exist or is empty. Check boundary_config/boundary_config_path.\n" "$BOUNDARY_CONFIG_FILE" >&2 - exit 1 + if [ ! -s "$BOUNDARY_CONFIG_FILE" ]; then + printf "Error: boundary configuration file '%s' does not exist or is empty. Check that '%s' exists and is not empty.\n" "$BOUNDARY_CONFIG_FILE" "$ARG_BOUNDARY_CONFIG_PATH" >&2 + exit 1 + fi fi install_boundary From 738c97246e3fcc9c236bf929dca9b01312181e67 Mon Sep 17 00:00:00 2001 From: DevelopmentCats Date: Sat, 4 Apr 2026 01:09:13 +0000 Subject: [PATCH 6/8] fix: add boundary config validation and path normalization Update enable_boundary validation to treat empty/whitespace strings as unset using trimspace checks, so callers providing "" are handled consistently with null. Per-variable validations already reject empty strings. Bump to v4.9.2. Closes coder/registry#797 Generated with OpenClaw using Claude --- registry/coder/modules/claude-code/README.md | 20 ++++++++++---------- registry/coder/modules/claude-code/main.tf | 4 ++-- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/registry/coder/modules/claude-code/README.md b/registry/coder/modules/claude-code/README.md index 01d00f1de..2b0583745 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.9.1" + version = "4.9.2" agent_id = coder_agent.main.id workdir = "/home/coder/project" claude_api_key = "xxxx-xxxxx-xxxx" @@ -67,7 +67,7 @@ The module writes the config to `~/.config/coder_boundary/config.yaml` automatic ```tf module "claude-code" { source = "registry.coder.com/coder/claude-code/coder" - version = "4.9.1" + version = "4.9.2" agent_id = coder_agent.main.id workdir = "/home/coder/project" enable_boundary = true @@ -87,7 +87,7 @@ Use this when the config file is provisioned separately or managed outside the t ```tf module "claude-code" { source = "registry.coder.com/coder/claude-code/coder" - version = "4.9.0" + version = "4.9.2" agent_id = coder_agent.main.id workdir = "/home/coder/project" enable_boundary = true @@ -109,7 +109,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.9.1" + version = "4.9.2" agent_id = coder_agent.main.id workdir = "/home/coder/project" enable_aibridge = true @@ -138,7 +138,7 @@ data "coder_task" "me" {} module "claude-code" { source = "registry.coder.com/coder/claude-code/coder" - version = "4.9.1" + version = "4.9.2" agent_id = coder_agent.main.id workdir = "/home/coder/project" ai_prompt = data.coder_task.me.prompt @@ -161,7 +161,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.9.1" + version = "4.9.2" agent_id = coder_agent.main.id workdir = "/home/coder/project" @@ -217,7 +217,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.9.1" + version = "4.9.2" agent_id = coder_agent.main.id workdir = "/home/coder/project" install_claude_code = true @@ -239,7 +239,7 @@ variable "claude_code_oauth_token" { module "claude-code" { source = "registry.coder.com/coder/claude-code/coder" - version = "4.9.1" + version = "4.9.2" agent_id = coder_agent.main.id workdir = "/home/coder/project" claude_code_oauth_token = var.claude_code_oauth_token @@ -312,7 +312,7 @@ resource "coder_env" "bedrock_api_key" { module "claude-code" { source = "registry.coder.com/coder/claude-code/coder" - version = "4.9.1" + version = "4.9.2" agent_id = coder_agent.main.id workdir = "/home/coder/project" model = "global.anthropic.claude-sonnet-4-5-20250929-v1:0" @@ -369,7 +369,7 @@ resource "coder_env" "google_application_credentials" { module "claude-code" { source = "registry.coder.com/coder/claude-code/coder" - version = "4.9.1" + version = "4.9.2" agent_id = coder_agent.main.id workdir = "/home/coder/project" model = "claude-sonnet-4@20250514" diff --git a/registry/coder/modules/claude-code/main.tf b/registry/coder/modules/claude-code/main.tf index a8a781c3a..fed672af2 100644 --- a/registry/coder/modules/claude-code/main.tf +++ b/registry/coder/modules/claude-code/main.tf @@ -233,12 +233,12 @@ variable "enable_boundary" { default = false validation { - condition = !var.enable_boundary || var.boundary_config == null || var.boundary_config_path == null + condition = !var.enable_boundary || (var.boundary_config == null || trimspace(var.boundary_config) == "") || (var.boundary_config_path == null || trimspace(var.boundary_config_path) == "") error_message = "Only one of boundary_config or boundary_config_path can be provided, not both." } validation { - condition = (var.boundary_config == null && var.boundary_config_path == null) || var.enable_boundary + condition = ((var.boundary_config == null || trimspace(var.boundary_config) == "") && (var.boundary_config_path == null || trimspace(var.boundary_config_path) == "")) || var.enable_boundary error_message = "boundary_config and boundary_config_path can only be set when enable_boundary is true." } } From 20993b042ff3884f983f47c2a09edb3dbd201ad7 Mon Sep 17 00:00:00 2001 From: DevelopmentCats Date: Sat, 4 Apr 2026 09:51:53 +0000 Subject: [PATCH 7/8] fix: align version attribute in tf code blocks for Prettier formatting Co-Authored-By: Claude Sonnet 4.6 --- registry/coder/modules/claude-code/README.md | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/registry/coder/modules/claude-code/README.md b/registry/coder/modules/claude-code/README.md index 2b0583745..cbe0cd3b1 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.9.2" + version = "4.9.2" agent_id = coder_agent.main.id workdir = "/home/coder/project" claude_api_key = "xxxx-xxxxx-xxxx" @@ -67,7 +67,7 @@ The module writes the config to `~/.config/coder_boundary/config.yaml` automatic ```tf module "claude-code" { source = "registry.coder.com/coder/claude-code/coder" - version = "4.9.2" + version = "4.9.2" agent_id = coder_agent.main.id workdir = "/home/coder/project" enable_boundary = true @@ -87,7 +87,7 @@ Use this when the config file is provisioned separately or managed outside the t ```tf module "claude-code" { source = "registry.coder.com/coder/claude-code/coder" - version = "4.9.2" + version = "4.9.2" agent_id = coder_agent.main.id workdir = "/home/coder/project" enable_boundary = true @@ -109,7 +109,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.9.2" + version = "4.9.2" agent_id = coder_agent.main.id workdir = "/home/coder/project" enable_aibridge = true @@ -138,7 +138,7 @@ data "coder_task" "me" {} module "claude-code" { source = "registry.coder.com/coder/claude-code/coder" - version = "4.9.2" + version = "4.9.2" agent_id = coder_agent.main.id workdir = "/home/coder/project" ai_prompt = data.coder_task.me.prompt @@ -161,7 +161,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.9.2" + version = "4.9.2" agent_id = coder_agent.main.id workdir = "/home/coder/project" @@ -217,7 +217,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.9.2" + version = "4.9.2" agent_id = coder_agent.main.id workdir = "/home/coder/project" install_claude_code = true @@ -239,7 +239,7 @@ variable "claude_code_oauth_token" { module "claude-code" { source = "registry.coder.com/coder/claude-code/coder" - version = "4.9.2" + version = "4.9.2" agent_id = coder_agent.main.id workdir = "/home/coder/project" claude_code_oauth_token = var.claude_code_oauth_token @@ -312,7 +312,7 @@ resource "coder_env" "bedrock_api_key" { module "claude-code" { source = "registry.coder.com/coder/claude-code/coder" - version = "4.9.2" + version = "4.9.2" agent_id = coder_agent.main.id workdir = "/home/coder/project" model = "global.anthropic.claude-sonnet-4-5-20250929-v1:0" @@ -369,7 +369,7 @@ resource "coder_env" "google_application_credentials" { module "claude-code" { source = "registry.coder.com/coder/claude-code/coder" - version = "4.9.2" + version = "4.9.2" agent_id = coder_agent.main.id workdir = "/home/coder/project" model = "claude-sonnet-4@20250514" From 8f6853522d70029de4293b3e5f036c4eeac453c5 Mon Sep 17 00:00:00 2001 From: DevelopmentCats Date: Sat, 4 Apr 2026 15:27:22 +0000 Subject: [PATCH 8/8] fix: address review comments on boundary config validation and safety checks - Update boundary_config_b64 local and ARG_BOUNDARY_CONFIG_PATH interpolation to treat empty/whitespace-only strings as not set using trimspace() checks, not just null checks - Add unified post-fi check in start.sh that BOUNDARY_CONFIG_FILE exists and is non-empty after writing/linking, exits with clear error if not Generated with OpenClaw using Claude --- registry/coder/modules/claude-code/main.tf | 4 ++-- registry/coder/modules/claude-code/scripts/start.sh | 5 +++++ 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/registry/coder/modules/claude-code/main.tf b/registry/coder/modules/claude-code/main.tf index fed672af2..16331c2c0 100644 --- a/registry/coder/modules/claude-code/main.tf +++ b/registry/coder/modules/claude-code/main.tf @@ -364,7 +364,7 @@ locals { module_dir_name = ".claude-module" # Extract hostname from access_url for boundary --allow flag coder_host = replace(replace(data.coder_workspace.me.access_url, "https://", ""), "http://", "") - boundary_config_b64 = var.boundary_config != null ? base64encode(var.boundary_config) : "" + boundary_config_b64 = var.boundary_config != null && trimspace(var.boundary_config) != "" ? base64encode(var.boundary_config) : "" claude_api_key = var.enable_aibridge ? data.coder_workspace_owner.me.session_token : var.claude_api_key # Required prompts for the module to properly report task status to Coder @@ -441,7 +441,7 @@ module "agentapi" { ARG_USE_BOUNDARY_DIRECTLY='${var.use_boundary_directly}' \ ARG_CODER_HOST='${local.coder_host}' \ ARG_BOUNDARY_CONFIG='${local.boundary_config_b64}' \ - ARG_BOUNDARY_CONFIG_PATH='${var.boundary_config_path != null ? var.boundary_config_path : ""}' \ + ARG_BOUNDARY_CONFIG_PATH='${var.boundary_config_path != null && trimspace(var.boundary_config_path) != "" ? trimspace(var.boundary_config_path) : ""}' \ ARG_CLAUDE_BINARY_PATH='${var.claude_binary_path}' \ /tmp/start.sh EOT diff --git a/registry/coder/modules/claude-code/scripts/start.sh b/registry/coder/modules/claude-code/scripts/start.sh index c0b89ade0..488d9a292 100644 --- a/registry/coder/modules/claude-code/scripts/start.sh +++ b/registry/coder/modules/claude-code/scripts/start.sh @@ -250,6 +250,11 @@ function start_agentapi() { fi fi + if [ ! -s "$BOUNDARY_CONFIG_FILE" ]; then + printf "Error: boundary configuration file '%s' does not exist or is empty. Check ARG_BOUNDARY_CONFIG/ARG_BOUNDARY_CONFIG_PATH.\n" "$BOUNDARY_CONFIG_FILE" >&2 + exit 1 + fi + install_boundary printf "Starting with coder boundary enabled\n"