From 8c45c65835f4be46fc8d29eba56148c42c691a46 Mon Sep 17 00:00:00 2001 From: Mathias Fredriksson Date: Fri, 27 Feb 2026 14:49:35 +0000 Subject: [PATCH] fix(registry/coder/modules): write bootstrap scripts to module dir instead of /tmp Bootstrap scripts used fixed /tmp paths with generic names like /tmp/main.sh, making them easy to collide with or accidentally overwrite. Write them into $HOME//scripts/ instead, following the pattern used by the agent-helper module. Also fix install.sh hardcoding port 3284 instead of using ARG_AGENTAPI_PORT. Refs #736 --- registry/coder/modules/agentapi/README.md | 2 +- registry/coder/modules/agentapi/main.test.ts | 10 ++++++++-- registry/coder/modules/agentapi/main.tf | 16 ++++++++++------ registry/coder/modules/claude-code/README.md | 18 +++++++++--------- registry/coder/modules/claude-code/main.tf | 19 +++++++++++++------ .../modules/claude-code/scripts/install.sh | 4 +++- 6 files changed, 44 insertions(+), 25 deletions(-) diff --git a/registry/coder/modules/agentapi/README.md b/registry/coder/modules/agentapi/README.md index e7a9869fb..a7e8e39b8 100644 --- a/registry/coder/modules/agentapi/README.md +++ b/registry/coder/modules/agentapi/README.md @@ -16,7 +16,7 @@ The AgentAPI module is a building block for modules that need to run an AgentAPI ```tf module "agentapi" { source = "registry.coder.com/coder/agentapi/coder" - version = "2.1.1" + version = "2.1.2" agent_id = var.agent_id web_app_slug = local.app_slug diff --git a/registry/coder/modules/agentapi/main.test.ts b/registry/coder/modules/agentapi/main.test.ts index 20b47b1a0..5669b22e5 100644 --- a/registry/coder/modules/agentapi/main.test.ts +++ b/registry/coder/modules/agentapi/main.test.ts @@ -309,16 +309,22 @@ describe("agentapi", async () => { "../scripts/agentapi-shutdown.sh", ); + const shutdownScriptPath = `/home/coder/${moduleDirName}/scripts/agentapi-shutdown.sh`; + await execContainer(containerId, [ + "bash", + "-c", + `mkdir -p /home/coder/${moduleDirName}/scripts`, + ]); await writeExecutable({ containerId, - filePath: "/tmp/shutdown.sh", + filePath: shutdownScriptPath, content: shutdownScript, }); return await execContainer(containerId, [ "bash", "-c", - `ARG_TASK_ID=${taskId} ARG_AGENTAPI_PORT=3284 CODER_AGENT_URL=http://localhost:18080 CODER_AGENT_TOKEN=test-token /tmp/shutdown.sh`, + `ARG_TASK_ID=${taskId} ARG_AGENTAPI_PORT=3284 CODER_AGENT_URL=http://localhost:18080 CODER_AGENT_TOKEN=test-token ${shutdownScriptPath}`, ]); }; diff --git a/registry/coder/modules/agentapi/main.tf b/registry/coder/modules/agentapi/main.tf index 6914be779..4dcd0fd1b 100644 --- a/registry/coder/modules/agentapi/main.tf +++ b/registry/coder/modules/agentapi/main.tf @@ -193,8 +193,10 @@ resource "coder_script" "agentapi" { set -o errexit set -o pipefail - echo -n '${base64encode(local.main_script)}' | base64 -d > /tmp/main.sh - chmod +x /tmp/main.sh + SCRIPT_DIR="$HOME/${var.module_dir_name}/scripts" + mkdir -p "$SCRIPT_DIR" + echo -n '${base64encode(local.main_script)}' | base64 -d > "$SCRIPT_DIR/agentapi-main.sh" + chmod +x "$SCRIPT_DIR/agentapi-main.sh" ARG_MODULE_DIR_NAME='${var.module_dir_name}' \ ARG_WORKDIR="$(echo -n '${base64encode(local.workdir)}' | base64 -d)" \ @@ -209,7 +211,7 @@ resource "coder_script" "agentapi" { ARG_AGENTAPI_CHAT_BASE_PATH='${local.agentapi_chat_base_path}' \ ARG_TASK_ID='${try(data.coder_task.me.id, "")}' \ ARG_TASK_LOG_SNAPSHOT='${var.task_log_snapshot}' \ - /tmp/main.sh + "$SCRIPT_DIR/agentapi-main.sh" EOT run_on_start = true } @@ -223,13 +225,15 @@ resource "coder_script" "agentapi_shutdown" { #!/bin/bash set -o pipefail - echo -n '${base64encode(local.shutdown_script)}' | base64 -d > /tmp/agentapi-shutdown.sh - chmod +x /tmp/agentapi-shutdown.sh + SCRIPT_DIR="$HOME/${var.module_dir_name}/scripts" + mkdir -p "$SCRIPT_DIR" + echo -n '${base64encode(local.shutdown_script)}' | base64 -d > "$SCRIPT_DIR/agentapi-shutdown.sh" + chmod +x "$SCRIPT_DIR/agentapi-shutdown.sh" ARG_TASK_ID='${try(data.coder_task.me.id, "")}' \ ARG_TASK_LOG_SNAPSHOT='${var.task_log_snapshot}' \ ARG_AGENTAPI_PORT='${var.agentapi_port}' \ - /tmp/agentapi-shutdown.sh + "$SCRIPT_DIR/agentapi-shutdown.sh" EOT } 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" diff --git a/registry/coder/modules/claude-code/main.tf b/registry/coder/modules/claude-code/main.tf index 07e3eb5a4..247533728 100644 --- a/registry/coder/modules/claude-code/main.tf +++ b/registry/coder/modules/claude-code/main.tf @@ -318,6 +318,7 @@ locals { install_script = file("${path.module}/scripts/install.sh") start_script = file("${path.module}/scripts/start.sh") module_dir_name = ".claude-module" + agentapi_port = 3284 # 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 @@ -378,8 +379,11 @@ module "agentapi" { #!/bin/bash set -o errexit set -o pipefail - echo -n '${base64encode(local.start_script)}' | base64 -d > /tmp/start.sh - chmod +x /tmp/start.sh + + SCRIPT_DIR="$HOME/${local.module_dir_name}/scripts" + mkdir -p "$SCRIPT_DIR" + echo -n '${base64encode(local.start_script)}' | base64 -d > "$SCRIPT_DIR/claude-code-start.sh" + chmod +x "$SCRIPT_DIR/claude-code-start.sh" ARG_RESUME_SESSION_ID='${var.resume_session_id}' \ ARG_CONTINUE='${var.continue}' \ @@ -394,7 +398,7 @@ module "agentapi" { ARG_USE_BOUNDARY_DIRECTLY='${var.use_boundary_directly}' \ ARG_CODER_HOST='${local.coder_host}' \ ARG_CLAUDE_BINARY_PATH='${var.claude_binary_path}' \ - /tmp/start.sh + "$SCRIPT_DIR/claude-code-start.sh" EOT install_script = <<-EOT @@ -402,8 +406,10 @@ module "agentapi" { set -o errexit set -o pipefail - echo -n '${base64encode(local.install_script)}' | base64 -d > /tmp/install.sh - chmod +x /tmp/install.sh + SCRIPT_DIR="$HOME/${local.module_dir_name}/scripts" + mkdir -p "$SCRIPT_DIR" + echo -n '${base64encode(local.install_script)}' | base64 -d > "$SCRIPT_DIR/claude-code-install.sh" + chmod +x "$SCRIPT_DIR/claude-code-install.sh" ARG_CLAUDE_CODE_VERSION='${var.claude_code_version}' \ ARG_MCP_APP_STATUS_SLUG='${local.app_slug}' \ ARG_INSTALL_CLAUDE_CODE='${var.install_claude_code}' \ @@ -416,7 +422,8 @@ module "agentapi" { ARG_MCP='${var.mcp != null ? base64encode(replace(var.mcp, "'", "'\\''")) : ""}' \ ARG_MCP_CONFIG_REMOTE_PATH='${base64encode(jsonencode(var.mcp_config_remote_path))}' \ ARG_ENABLE_AIBRIDGE='${var.enable_aibridge}' \ - /tmp/install.sh + ARG_AGENTAPI_PORT='${local.agentapi_port}' \ + "$SCRIPT_DIR/claude-code-install.sh" EOT } diff --git a/registry/coder/modules/claude-code/scripts/install.sh b/registry/coder/modules/claude-code/scripts/install.sh index 0a2ba7033..e7f9606b1 100644 --- a/registry/coder/modules/claude-code/scripts/install.sh +++ b/registry/coder/modules/claude-code/scripts/install.sh @@ -17,6 +17,7 @@ ARG_CLAUDE_BINARY_PATH="${ARG_CLAUDE_BINARY_PATH//\$HOME/$HOME}" ARG_INSTALL_VIA_NPM=${ARG_INSTALL_VIA_NPM:-false} ARG_REPORT_TASKS=${ARG_REPORT_TASKS:-true} ARG_MCP_APP_STATUS_SLUG=${ARG_MCP_APP_STATUS_SLUG:-} +ARG_AGENTAPI_PORT=${ARG_AGENTAPI_PORT:-3284} ARG_MCP=$(echo -n "${ARG_MCP:-}" | base64 -d) ARG_MCP_CONFIG_REMOTE_PATH=$(echo -n "${ARG_MCP_CONFIG_REMOTE_PATH:-}" | base64 -d) ARG_ALLOWED_TOOLS=${ARG_ALLOWED_TOOLS:-} @@ -34,6 +35,7 @@ printf "ARG_CLAUDE_BINARY_PATH: %s\n" "$ARG_CLAUDE_BINARY_PATH" printf "ARG_INSTALL_VIA_NPM: %s\n" "$ARG_INSTALL_VIA_NPM" printf "ARG_REPORT_TASKS: %s\n" "$ARG_REPORT_TASKS" printf "ARG_MCP_APP_STATUS_SLUG: %s\n" "$ARG_MCP_APP_STATUS_SLUG" +printf "ARG_AGENTAPI_PORT: %s\n" "$ARG_AGENTAPI_PORT" printf "ARG_MCP: %s\n" "$ARG_MCP" printf "ARG_MCP_CONFIG_REMOTE_PATH: %s\n" "$ARG_MCP_CONFIG_REMOTE_PATH" printf "ARG_ALLOWED_TOOLS: %s\n" "$ARG_ALLOWED_TOOLS" @@ -228,7 +230,7 @@ function report_tasks() { if [ "$ARG_REPORT_TASKS" = "true" ]; then echo "Configuring Claude Code to report tasks via Coder MCP..." export CODER_MCP_APP_STATUS_SLUG="$ARG_MCP_APP_STATUS_SLUG" - export CODER_MCP_AI_AGENTAPI_URL="http://localhost:3284" + export CODER_MCP_AI_AGENTAPI_URL="http://localhost:${ARG_AGENTAPI_PORT:-3284}" coder exp mcp configure claude-code "$ARG_WORKDIR" else configure_standalone_mode