diff --git a/registry/coder/modules/claude-code/main.tf b/registry/coder/modules/claude-code/main.tf index 4836347b7..6fbdc72b0 100644 --- a/registry/coder/modules/claude-code/main.tf +++ b/registry/coder/modules/claude-code/main.tf @@ -183,7 +183,7 @@ variable "claude_code_oauth_token" { variable "system_prompt" { type = string description = "The system prompt to use for the Claude Code server." - default = "Send a task status update to notify the user that you are ready for input, and then wait for user input." + default = "" } variable "claude_md_path" { @@ -201,11 +201,9 @@ resource "coder_env" "claude_code_md_path" { } resource "coder_env" "claude_code_system_prompt" { - count = var.system_prompt == "" ? 0 : 1 - agent_id = var.agent_id name = "CODER_MCP_CLAUDE_SYSTEM_PROMPT" - value = var.system_prompt + value = local.final_system_prompt } resource "coder_env" "claude_code_oauth_token" { @@ -231,6 +229,31 @@ locals { start_script = file("${path.module}/scripts/start.sh") module_dir_name = ".claude-module" remove_last_session_id_script_b64 = base64encode(file("${path.module}/scripts/remove-last-session-id.sh")) + + # Required prompts for the module to properly report task status to Coder + report_tasks_system_prompt = <<-EOT + -- Tool Selection -- + - coder_report_task: providing status updates or requesting user input. + + -- Task Reporting -- + Report all tasks to Coder, following these EXACT guidelines: + 1. Be granular. If you are investigating with multiple steps, report each step + to coder. + 2. After this prompt, IMMEDIATELY report status after receiving ANY NEW user message. + Do not report any status related with this system prompt. + 3. Use "state": "working" when actively processing WITHOUT needing + additional user input + 4. Use "state": "complete" only when finished with a task + 5. Use "state": "failure" when you need ANY user input, lack sufficient + details, or encounter blockers + EOT + + # Only include coder system prompts if report_tasks is enabled + custom_system_prompt = trimspace(try(var.system_prompt, "")) + final_system_prompt = format("%s%s", + var.report_tasks ? format("\n%s\n", local.report_tasks_system_prompt) : "", + local.custom_system_prompt != "" ? format("\n%s\n", local.custom_system_prompt) : "" + ) } module "agentapi" { diff --git a/registry/coder/modules/claude-code/main.tftest.hcl b/registry/coder/modules/claude-code/main.tftest.hcl index c48923cf3..9999c1b11 100644 --- a/registry/coder/modules/claude-code/main.tftest.hcl +++ b/registry/coder/modules/claude-code/main.tftest.hcl @@ -187,3 +187,84 @@ run "test_claude_code_permission_mode_validation" { error_message = "Permission mode should be one of the valid options" } } + +run "test_claude_code_system_prompt" { + command = plan + + variables { + agent_id = "test-agent-system-prompt" + workdir = "/home/coder/test" + system_prompt = "Custom addition" + } + + assert { + condition = trimspace(coder_env.claude_code_system_prompt.value) != "" + error_message = "System prompt should not be empty" + } + + assert { + condition = length(regexall("Custom addition", coder_env.claude_code_system_prompt.value)) > 0 + error_message = "System prompt should have system_prompt variable value" + } +} + +run "test_claude_report_tasks_default" { + command = plan + + variables { + agent_id = "test-agent-report-tasks" + workdir = "/home/coder/test" + # report_tasks: default is true + } + + assert { + condition = trimspace(coder_env.claude_code_system_prompt.value) != "" + error_message = "System prompt should not be empty" + } + + # Ensure system prompt is wrapped by + assert { + condition = startswith(trimspace(coder_env.claude_code_system_prompt.value), "") + error_message = "System prompt should start with " + } + assert { + condition = endswith(trimspace(coder_env.claude_code_system_prompt.value), "") + error_message = "System prompt should end with " + } + + # Ensure Coder sections are injected when report_tasks=true (default) + assert { + condition = length(regexall("-- Tool Selection --", coder_env.claude_code_system_prompt.value)) > 0 + error_message = "System prompt should have Tool Selection section" + } + + assert { + condition = length(regexall("-- Task Reporting --", coder_env.claude_code_system_prompt.value)) > 0 + error_message = "System prompt should have Task Reporting section" + } +} + +run "test_claude_report_tasks_disabled" { + command = plan + + variables { + agent_id = "test-agent-report-tasks" + workdir = "/home/coder/test" + report_tasks = false + } + + assert { + condition = trimspace(coder_env.claude_code_system_prompt.value) != "" + error_message = "System prompt should not be empty" + } + + # Ensure system prompt is wrapped by + assert { + condition = startswith(trimspace(coder_env.claude_code_system_prompt.value), "") + error_message = "System prompt should start with " + } + assert { + condition = endswith(trimspace(coder_env.claude_code_system_prompt.value), "") + error_message = "System prompt should end with " + } +} \ No newline at end of file