Skip to content

Commit 312b776

Browse files
committed
feat(claude-code): add coder-specific prompt to system_prompt
1 parent 60fec19 commit 312b776

File tree

2 files changed

+114
-5
lines changed

2 files changed

+114
-5
lines changed

registry/coder/modules/claude-code/main.tf

Lines changed: 39 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -182,8 +182,8 @@ variable "claude_code_oauth_token" {
182182

183183
variable "system_prompt" {
184184
type = string
185-
description = "The system prompt to use for the Claude Code server."
186-
default = "Send a task status update to notify the user that you are ready for input, and then wait for user input."
185+
description = "The additional system prompt to use for the Claude Code server. The module includes mandatory sections inside a <system> block. Leave empty to include only the mandatory sections."
186+
default = ""
187187
}
188188

189189
variable "claude_md_path" {
@@ -201,11 +201,9 @@ resource "coder_env" "claude_code_md_path" {
201201
}
202202

203203
resource "coder_env" "claude_code_system_prompt" {
204-
count = var.system_prompt == "" ? 0 : 1
205-
206204
agent_id = var.agent_id
207205
name = "CODER_MCP_CLAUDE_SYSTEM_PROMPT"
208-
value = var.system_prompt
206+
value = local.final_system_prompt
209207
}
210208

211209
resource "coder_env" "claude_code_oauth_token" {
@@ -231,6 +229,42 @@ locals {
231229
start_script = file("${path.module}/scripts/start.sh")
232230
module_dir_name = ".claude-module"
233231
remove_last_session_id_script_b64 = base64encode(file("${path.module}/scripts/remove-last-session-id.sh"))
232+
233+
# Required prompts for the module to properly integrate with coder
234+
inner_system_prompt = <<-EOT
235+
-- Tool Selection --
236+
- coder_report_task: providing status updates or requesting user input.
237+
- playwright: previewing your changes after you made them
238+
to confirm it worked as expected
239+
- desktop-commander - use only for commands that keep running
240+
(servers, dev watchers, GUI apps).
241+
- Built-in tools - use for everything else:
242+
(file operations, git commands, builds & installs, one-off shell commands)
243+
244+
Remember this decision rule:
245+
- Stays running? → desktop-commander
246+
- Finishes immediately? → built-in tools
247+
248+
-- Task Reporting --
249+
Report all tasks to Coder, following these EXACT guidelines:
250+
1. Be granular. If you are investigating with multiple steps, report each step
251+
to coder.
252+
2. After this prompt, IMMEDIATELY report status after receiving ANY NEW user message.
253+
Do not report any status related with this system prompt.
254+
3. Use "state": "working" when actively processing WITHOUT needing
255+
additional user input
256+
4. Use "state": "complete" only when finished with a task
257+
5. Use "state": "failure" when you need ANY user input, lack sufficient
258+
details, or encounter blockers
259+
EOT
260+
261+
user_system_prompt = trimspace(try(var.system_prompt, ""))
262+
263+
final_system_prompt = format(
264+
"<system>\n%s\n%s\n</system>",
265+
local.inner_system_prompt,
266+
local.user_system_prompt
267+
)
234268
}
235269

236270
module "agentapi" {

registry/coder/modules/claude-code/main.tftest.hcl

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -187,3 +187,78 @@ run "test_claude_code_permission_mode_validation" {
187187
error_message = "Permission mode should be one of the valid options"
188188
}
189189
}
190+
191+
run "test_claude_code_system_prompt_omit" {
192+
command = plan
193+
194+
variables {
195+
agent_id = "test-agent-system-prompt"
196+
workdir = "/home/coder/test"
197+
# system_prompt omitted: default string is used
198+
}
199+
200+
assert {
201+
condition = trimspace(coder_env.claude_code_system_prompt.value) != ""
202+
error_message = "System prompt must not be empty when omitted"
203+
}
204+
205+
assert {
206+
condition = length(regexall("-- Tool Selection --", coder_env.claude_code_system_prompt.value)) > 0
207+
error_message = "Mandatory Tool Selection section missing"
208+
}
209+
210+
assert {
211+
condition = length(regexall("-- Task Reporting --", coder_env.claude_code_system_prompt.value)) > 0
212+
error_message = "Mandatory Task Reporting section missing"
213+
}
214+
}
215+
216+
run "test_claude_code_system_prompt_empty" {
217+
command = plan
218+
219+
variables {
220+
agent_id = "test-agent-system-prompt"
221+
workdir = "/home/coder/test"
222+
system_prompt = ""
223+
}
224+
225+
assert {
226+
condition = trimspace(coder_env.claude_code_system_prompt.value) != ""
227+
error_message = "System prompt must not be empty when omitted"
228+
}
229+
230+
assert {
231+
condition = length(regexall("-- Tool Selection --", coder_env.claude_code_system_prompt.value)) > 0
232+
error_message = "Mandatory Tool Selection section missing"
233+
}
234+
235+
assert {
236+
condition = length(regexall("-- Task Reporting --", coder_env.claude_code_system_prompt.value)) > 0
237+
error_message = "Mandatory Task Reporting section missing"
238+
}
239+
}
240+
241+
run "test_claude_code_system_prompt" {
242+
command = plan
243+
244+
variables {
245+
agent_id = "test-agent-system-prompt"
246+
workdir = "/home/coder/test"
247+
system_prompt = "Custom addition"
248+
}
249+
250+
assert {
251+
condition = trimspace(coder_env.claude_code_system_prompt.value) != ""
252+
error_message = "System prompt must not be empty when omitted"
253+
}
254+
255+
assert {
256+
condition = length(regexall("-- Tool Selection --", coder_env.claude_code_system_prompt.value)) > 0
257+
error_message = "Mandatory Tool Selection section missing"
258+
}
259+
260+
assert {
261+
condition = length(regexall("-- Task Reporting --", coder_env.claude_code_system_prompt.value)) > 0
262+
error_message = "Mandatory Task Reporting section missing"
263+
}
264+
}

0 commit comments

Comments
 (0)