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