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