diff --git a/registry/coder/modules/claude-code/README.md b/registry/coder/modules/claude-code/README.md index a58ed223..340eb175 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.4" + version = "4.7.5" 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.4" + version = "4.7.5" 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.4" + version = "4.7.5" 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.4" + version = "4.7.5" 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.4" + version = "4.7.5" 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.4" + version = "4.7.5" 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.4" + version = "4.7.5" 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.4" + version = "4.7.5" 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.4" + version = "4.7.5" 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 3ed4a021..07e3eb5a 100644 --- a/registry/coder/modules/claude-code/main.tf +++ b/registry/coder/modules/claude-code/main.tf @@ -208,6 +208,11 @@ variable "claude_binary_path" { type = string description = "Directory where the Claude Code binary is located. Use this if Claude is pre-installed or installed outside the module to a non-default location." default = "$HOME/.local/bin" + + validation { + condition = var.claude_binary_path == "$HOME/.local/bin" || !var.install_claude_code + error_message = "Custom claude_binary_path can only be used when install_claude_code is false. The official installer always installs to $HOME/.local/bin and does not support custom paths." + } } variable "install_via_npm" { @@ -290,18 +295,6 @@ resource "coder_env" "disable_autoupdater" { value = "1" } -resource "coder_env" "claude_binary_path" { - agent_id = var.agent_id - name = "PATH" - value = "${var.claude_binary_path}:$PATH" - - lifecycle { - precondition { - condition = var.claude_binary_path == "$HOME/.local/bin" || !var.install_claude_code - error_message = "Custom claude_binary_path can only be used when install_claude_code is false. The official installer and npm both install to fixed locations." - } - } -} resource "coder_env" "anthropic_model" { count = var.model != "" ? 1 : 0 @@ -382,26 +375,27 @@ module "agentapi" { pre_install_script = var.pre_install_script post_install_script = var.post_install_script start_script = <<-EOT - #!/bin/bash - set -o errexit - set -o pipefail - echo -n '${base64encode(local.start_script)}' | base64 -d > /tmp/start.sh - chmod +x /tmp/start.sh + #!/bin/bash + set -o errexit + set -o pipefail + echo -n '${base64encode(local.start_script)}' | base64 -d > /tmp/start.sh + chmod +x /tmp/start.sh - ARG_RESUME_SESSION_ID='${var.resume_session_id}' \ - ARG_CONTINUE='${var.continue}' \ - ARG_DANGEROUSLY_SKIP_PERMISSIONS='${var.dangerously_skip_permissions}' \ - ARG_PERMISSION_MODE='${var.permission_mode}' \ - ARG_WORKDIR='${local.workdir}' \ - ARG_AI_PROMPT='${base64encode(var.ai_prompt)}' \ - ARG_REPORT_TASKS='${var.report_tasks}' \ - ARG_ENABLE_BOUNDARY='${var.enable_boundary}' \ - ARG_BOUNDARY_VERSION='${var.boundary_version}' \ - ARG_COMPILE_FROM_SOURCE='${var.compile_boundary_from_source}' \ - ARG_USE_BOUNDARY_DIRECTLY='${var.use_boundary_directly}' \ - ARG_CODER_HOST='${local.coder_host}' \ - /tmp/start.sh - EOT + ARG_RESUME_SESSION_ID='${var.resume_session_id}' \ + ARG_CONTINUE='${var.continue}' \ + ARG_DANGEROUSLY_SKIP_PERMISSIONS='${var.dangerously_skip_permissions}' \ + ARG_PERMISSION_MODE='${var.permission_mode}' \ + ARG_WORKDIR='${local.workdir}' \ + ARG_AI_PROMPT='${base64encode(var.ai_prompt)}' \ + ARG_REPORT_TASKS='${var.report_tasks}' \ + ARG_ENABLE_BOUNDARY='${var.enable_boundary}' \ + ARG_BOUNDARY_VERSION='${var.boundary_version}' \ + ARG_COMPILE_FROM_SOURCE='${var.compile_boundary_from_source}' \ + 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 + EOT install_script = <<-EOT #!/bin/bash diff --git a/registry/coder/modules/claude-code/scripts/install.sh b/registry/coder/modules/claude-code/scripts/install.sh index d87a83b7..9a393965 100644 --- a/registry/coder/modules/claude-code/scripts/install.sh +++ b/registry/coder/modules/claude-code/scripts/install.sh @@ -12,6 +12,7 @@ ARG_CLAUDE_CODE_VERSION=${ARG_CLAUDE_CODE_VERSION:-} ARG_WORKDIR=${ARG_WORKDIR:-"$HOME"} ARG_INSTALL_CLAUDE_CODE=${ARG_INSTALL_CLAUDE_CODE:-} ARG_CLAUDE_BINARY_PATH=${ARG_CLAUDE_BINARY_PATH:-"$HOME/.local/bin"} +ARG_CLAUDE_BINARY_PATH=$(eval echo "$ARG_CLAUDE_BINARY_PATH") 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:-} @@ -21,6 +22,8 @@ ARG_ALLOWED_TOOLS=${ARG_ALLOWED_TOOLS:-} ARG_DISALLOWED_TOOLS=${ARG_DISALLOWED_TOOLS:-} ARG_ENABLE_AIBRIDGE=${ARG_ENABLE_AIBRIDGE:-false} +export PATH="$ARG_CLAUDE_BINARY_PATH:$PATH" + echo "--------------------------------" printf "ARG_CLAUDE_CODE_VERSION: %s\n" "$ARG_CLAUDE_CODE_VERSION" @@ -51,39 +54,51 @@ function add_mcp_servers() { done < <(echo "$mcp_json" | jq -r '.mcpServers | to_entries[] | .key, (.value | @json)') } +function add_path_to_shell_profiles() { + local path_dir="$1" + + for profile in "$HOME/.profile" "$HOME/.bash_profile" "$HOME/.bashrc" "$HOME/.zprofile" "$HOME/.zshrc"; do + if [ -f "$profile" ]; then + if ! grep -q "$path_dir" "$profile" 2> /dev/null; then + echo "export PATH=\"\$PATH:$path_dir\"" >> "$profile" + echo "Added $path_dir to $profile" + fi + fi + done + + local fish_config="$HOME/.config/fish/config.fish" + if [ -f "$fish_config" ]; then + if ! grep -q "$path_dir" "$fish_config" 2> /dev/null; then + echo "fish_add_path $path_dir" >> "$fish_config" + echo "Added $path_dir to $fish_config" + fi + fi +} + function ensure_claude_in_path() { - if [ -z "${CODER_SCRIPT_BIN_DIR:-}" ]; then - echo "CODER_SCRIPT_BIN_DIR not set, skipping PATH setup" + local CLAUDE_BIN="" + if command -v claude > /dev/null 2>&1; then + CLAUDE_BIN=$(command -v claude) + elif [ -x "$ARG_CLAUDE_BINARY_PATH/claude" ]; then + CLAUDE_BIN="$ARG_CLAUDE_BINARY_PATH/claude" + elif [ -x "$HOME/.local/bin/claude" ]; then + CLAUDE_BIN="$HOME/.local/bin/claude" + fi + + if [ -z "$CLAUDE_BIN" ] || [ ! -x "$CLAUDE_BIN" ]; then + echo "Warning: Could not find claude binary" return fi - if [ ! -e "$CODER_SCRIPT_BIN_DIR/claude" ]; then - local CLAUDE_BIN="" - if command -v claude > /dev/null 2>&1; then - CLAUDE_BIN=$(command -v claude) - elif [ -x "$ARG_CLAUDE_BINARY_PATH/claude" ]; then - CLAUDE_BIN="$ARG_CLAUDE_BINARY_PATH/claude" - elif [ -x "$HOME/.local/bin/claude" ]; then - CLAUDE_BIN="$HOME/.local/bin/claude" - fi + local CLAUDE_DIR + CLAUDE_DIR=$(dirname "$CLAUDE_BIN") - if [ -n "$CLAUDE_BIN" ] && [ -x "$CLAUDE_BIN" ]; then - ln -s "$CLAUDE_BIN" "$CODER_SCRIPT_BIN_DIR/claude" - echo "Created symlink: $CODER_SCRIPT_BIN_DIR/claude -> $CLAUDE_BIN" - else - echo "Warning: Could not find claude binary to symlink" - fi - else - echo "Claude already available in CODER_SCRIPT_BIN_DIR" + if [ -n "${CODER_SCRIPT_BIN_DIR:-}" ] && [ ! -e "$CODER_SCRIPT_BIN_DIR/claude" ]; then + ln -s "$CLAUDE_BIN" "$CODER_SCRIPT_BIN_DIR/claude" + echo "Created symlink: $CODER_SCRIPT_BIN_DIR/claude -> $CLAUDE_BIN" fi - local marker="# Added by claude-code module" - for profile in "$HOME/.bashrc" "$HOME/.zshrc" "$HOME/.profile"; do - if [ -f "$profile" ] && ! grep -q "$marker" "$profile" 2> /dev/null; then - printf "\n%s\nexport PATH=\"%s:\$PATH\"\n" "$marker" "$CODER_SCRIPT_BIN_DIR" >> "$profile" - echo "Added $CODER_SCRIPT_BIN_DIR to PATH in $profile" - fi - done + add_path_to_shell_profiles "$CLAUDE_DIR" } function install_claude_code_cli() { diff --git a/registry/coder/modules/claude-code/scripts/start.sh b/registry/coder/modules/claude-code/scripts/start.sh index b20f3833..a38e7146 100644 --- a/registry/coder/modules/claude-code/scripts/start.sh +++ b/registry/coder/modules/claude-code/scripts/start.sh @@ -2,6 +2,11 @@ set -euo pipefail +ARG_CLAUDE_BINARY_PATH=${ARG_CLAUDE_BINARY_PATH:-"$HOME/.local/bin"} +ARG_CLAUDE_BINARY_PATH=$(eval echo "$ARG_CLAUDE_BINARY_PATH") + +export PATH="$ARG_CLAUDE_BINARY_PATH:$PATH" + command_exists() { command -v "$1" > /dev/null 2>&1 } diff --git a/registry/coder/modules/git-config/README.md b/registry/coder/modules/git-config/README.md index 753e8de3..155c3790 100644 --- a/registry/coder/modules/git-config/README.md +++ b/registry/coder/modules/git-config/README.md @@ -14,7 +14,7 @@ Runs a script that updates git credentials in the workspace to match the user's module "git-config" { count = data.coder_workspace.me.start_count source = "registry.coder.com/coder/git-config/coder" - version = "1.0.32" + version = "1.0.33" agent_id = coder_agent.main.id } ``` @@ -29,7 +29,7 @@ TODO: Add screenshot module "git-config" { count = data.coder_workspace.me.start_count source = "registry.coder.com/coder/git-config/coder" - version = "1.0.32" + version = "1.0.33" agent_id = coder_agent.main.id allow_email_change = true } @@ -43,7 +43,7 @@ TODO: Add screenshot module "git-config" { count = data.coder_workspace.me.start_count source = "registry.coder.com/coder/git-config/coder" - version = "1.0.32" + version = "1.0.33" agent_id = coder_agent.main.id allow_username_change = false allow_email_change = false diff --git a/registry/coder/modules/git-config/main.tf b/registry/coder/modules/git-config/main.tf index e8fea8fd..2d9f5440 100644 --- a/registry/coder/modules/git-config/main.tf +++ b/registry/coder/modules/git-config/main.tf @@ -44,6 +44,9 @@ data "coder_parameter" "user_email" { description = "Git user.email to be used for commits. Leave empty to default to Coder user's email." display_name = "Git config user.email" mutable = true + styling = jsonencode({ + placeholder = data.coder_workspace_owner.me.email + }) } data "coder_parameter" "username" { @@ -55,6 +58,9 @@ data "coder_parameter" "username" { description = "Git user.name to be used for commits. Leave empty to default to Coder user's Full Name." display_name = "Full Name for Git config" mutable = true + styling = jsonencode({ + placeholder = coalesce(data.coder_workspace_owner.me.full_name, data.coder_workspace_owner.me.name) + }) } resource "coder_env" "git_author_name" {