@@ -115,6 +115,7 @@ func (*RootCmd) mcpConfigureClaudeCode() *serpent.Command {
115
115
claudeConfigPath string
116
116
claudeMDPath string
117
117
systemPrompt string
118
+ coderPrompt string
118
119
appStatusSlug string
119
120
testBinaryName string
120
121
@@ -177,8 +178,27 @@ func (*RootCmd) mcpConfigureClaudeCode() *serpent.Command {
177
178
}
178
179
cliui .Infof (inv .Stderr , "Wrote config to %s" , claudeConfigPath )
179
180
181
+ // Determine if we should include the reportTaskPrompt
182
+ var reportTaskPrompt string
183
+ if agentToken != "" && appStatusSlug != "" {
184
+ // Only include the report task prompt if both agent token and app
185
+ // status slug are defined. Otherwise, reporting a task will fail
186
+ // and confuse the agent (and by extension, the user).
187
+ reportTaskPrompt = defaultReportTaskPrompt
188
+ }
189
+
190
+ // If a user overrides the coder prompt, we don't want to append
191
+ // the report task prompt, as it then becomes the responsibility
192
+ // of the user.
193
+ actualCoderPrompt := defaultCoderPrompt
194
+ if coderPrompt != "" {
195
+ actualCoderPrompt = coderPrompt
196
+ } else if reportTaskPrompt != "" {
197
+ actualCoderPrompt += "\n \n " + reportTaskPrompt
198
+ }
199
+
180
200
// We also write the system prompt to the CLAUDE.md file.
181
- if err := injectClaudeMD (fs , systemPrompt , claudeMDPath ); err != nil {
201
+ if err := injectClaudeMD (fs , actualCoderPrompt , systemPrompt , claudeMDPath ); err != nil {
182
202
return xerrors .Errorf ("failed to modify CLAUDE.md: %w" , err )
183
203
}
184
204
cliui .Infof (inv .Stderr , "Wrote CLAUDE.md to %s" , claudeMDPath )
@@ -223,6 +243,14 @@ func (*RootCmd) mcpConfigureClaudeCode() *serpent.Command {
223
243
Value : serpent .StringOf (& systemPrompt ),
224
244
Default : "Send a task status update to notify the user that you are ready for input, and then wait for user input." ,
225
245
},
246
+ {
247
+ Name : "coder-prompt" ,
248
+ Description : "The coder prompt to use for the Claude Code server." ,
249
+ Env : "CODER_MCP_CLAUDE_CODER_PROMPT" ,
250
+ Flag : "claude-coder-prompt" ,
251
+ Value : serpent .StringOf (& coderPrompt ),
252
+ Default : "" , // Empty default means we'll use defaultCoderPrompt from the variable
253
+ },
226
254
{
227
255
Name : "app-status-slug" ,
228
256
Description : "The app status slug to use when running the Coder MCP server." ,
@@ -573,22 +601,25 @@ func configureClaude(fs afero.Fs, cfg ClaudeConfig) error {
573
601
}
574
602
575
603
var (
576
- coderPrompt = `YOU MUST REPORT YOUR STATUS IMMEDIATELY AFTER EACH USER MESSAGE.
577
- INTERRUPT READING FILES OR ANY OTHER TOOL CALL IF YOU HAVE NOT REPORTED A STATUS YET.
578
- You MUST use the mcp__coder__coder_report_task function with all required parameters:
579
- - summary: Short description of what you're doing
580
- - link: A relevant link for the status
581
- - done: Boolean indicating if the task is complete (true/false)
582
- - emoji: Relevant emoji for the status
583
- - need_user_attention: Boolean indicating if the task needs user attention (true/false)
584
- WHEN TO REPORT (MANDATORY):
585
- 1. IMMEDIATELY after receiving ANY user message, before any other actions
586
- 2. After completing any task
587
- 3. When making significant progress
588
- 4. When encountering roadblocks
589
- 5. When asking questions
590
- 6. Before and after using search tools or making code changes
591
- FAILING TO REPORT STATUS PROPERLY WILL RESULT IN INCORRECT BEHAVIOR.`
604
+ defaultCoderPrompt = `You are a helpful Coding assistant. Aim to autonomously investigate
605
+ and solve issues the user gives you and test your work, whenever possible.
606
+ Avoid shortcuts like mocking tests. When you get stuck, you can ask the user
607
+ but opt for autonomy.`
608
+
609
+ defaultReportTaskPrompt = `YOU MUST REPORT ALL TASKS TO CODER.
610
+ When reporting tasks, you MUST follow these EXACT instructions:
611
+ - IMMEDIATELY report status after receiving ANY user message.
612
+ - Be granular. If you are investigating with multiple steps, report each step to coder.
613
+
614
+ Task state MUST be one of the following:
615
+ - Use "state": "working" when actively processing WITHOUT needing additional user input.
616
+ - Use "state": "complete" only when finished with a task.
617
+ - Use "state": "failure" when you need ANY user input, lack sufficient details, or encounter blockers.
618
+
619
+ Task summaries MUST:
620
+ - Include specifics about what you're doing.
621
+ - Include clear and actionable steps for the user.
622
+ - Be less than 160 characters in length.`
592
623
593
624
// Define the guard strings
594
625
coderPromptStartGuard = "<coder-prompt>"
@@ -597,7 +628,7 @@ FAILING TO REPORT STATUS PROPERLY WILL RESULT IN INCORRECT BEHAVIOR.`
597
628
systemPromptEndGuard = "</system-prompt>"
598
629
)
599
630
600
- func injectClaudeMD (fs afero.Fs , systemPrompt string , claudeMDPath string ) error {
631
+ func injectClaudeMD (fs afero.Fs , coderPrompt , systemPrompt , claudeMDPath string ) error {
601
632
_ , err := fs .Stat (claudeMDPath )
602
633
if err != nil {
603
634
if ! os .IsNotExist (err ) {
0 commit comments