@@ -38,6 +38,7 @@ locals {
38
38
repo_base_dir = data. coder_parameter . repo_base_dir . value == " ~" ? " /home/coder" : replace (data. coder_parameter . repo_base_dir . value , " /^~\\ //" , " /home/coder/" )
39
39
repo_dir = replace (try (module. git-clone [0 ]. repo_dir , " " ), " /^~\\ //" , " /home/coder/" )
40
40
container_name = " coder-${ data . coder_workspace_owner . me . name } -${ lower (data. coder_workspace . me . name )} "
41
+ has_ai_prompt = data. coder_parameter . ai_prompt . value != " "
41
42
}
42
43
43
44
data "coder_workspace_preset" "cpt" {
@@ -150,6 +151,13 @@ data "coder_parameter" "image_type" {
150
151
}
151
152
}
152
153
154
+ variable "anthropic_api_key" {
155
+ type = string
156
+ description = " The API key used to authenticate with the Anthropic API."
157
+ default = " "
158
+ sensitive = true
159
+ }
160
+
153
161
locals {
154
162
default_regions = {
155
163
// keys should match group names
@@ -242,6 +250,14 @@ data "coder_parameter" "devcontainer_autostart" {
242
250
mutable = true
243
251
}
244
252
253
+ data "coder_parameter" "ai_prompt" {
254
+ type = " string"
255
+ name = " AI Prompt"
256
+ default = " "
257
+ description = " Prompt for Claude Code"
258
+ mutable = false
259
+ }
260
+
245
261
provider "docker" {
246
262
host = lookup (local. docker_host , data. coder_parameter . region . value )
247
263
}
@@ -380,6 +396,24 @@ module "devcontainers-cli" {
380
396
agent_id = coder_agent. dev . id
381
397
}
382
398
399
+ module "claude-code" {
400
+ count = local. has_ai_prompt ? data. coder_workspace . me . start_count : 0
401
+ source = " dev.registry.coder.com/coder/claude-code/coder"
402
+ version = " ~>2.0"
403
+ agent_id = coder_agent. dev . id
404
+ folder = local. repo_dir
405
+ install_claude_code = true
406
+ claude_code_version = " latest"
407
+ order = 999
408
+
409
+ experiment_report_tasks = true
410
+ experiment_post_install_script = <<- EOT
411
+ claude mcp add playwright npx -- @playwright/mcp@latest --headless --isolated --no-sandbox
412
+ claude mcp add desktop-commander npx -- @wonderwhy-er/desktop-commander@latest
413
+ EOT
414
+ }
415
+
416
+
383
417
resource "coder_agent" "dev" {
384
418
arch = " amd64"
385
419
os = " linux"
@@ -710,4 +744,128 @@ resource "coder_metadata" "container_info" {
710
744
key = " region"
711
745
value = data. coder_parameter . region . option [index (data. coder_parameter . region . option . * . value , data. coder_parameter . region . value )]. name
712
746
}
747
+ item {
748
+ key = " ai_task"
749
+ value = local. has_ai_prompt ? " yes" : " no"
750
+ }
751
+ }
752
+
753
+ resource "coder_env" "claude_system_prompt" {
754
+ count = local. has_ai_prompt ? data. coder_workspace . me . start_count : 0
755
+ agent_id = coder_agent. dev . id
756
+ name = " CODER_MCP_CLAUDE_SYSTEM_PROMPT"
757
+ value = <<- EOT
758
+ <system>
759
+ -- Framing --
760
+ You are a helpful Coding assistant. Aim to autonomously investigate
761
+ and solve issues the user gives you and test your work, whenever possible.
762
+
763
+ Avoid shortcuts like mocking tests. When you get stuck, you can ask the user
764
+ but opt for autonomy.
765
+
766
+ -- Tool Selection --
767
+ - coder_report_task: providing status updates or requesting user input.
768
+ - playwright: previewing your changes after you made them
769
+ to confirm it worked as expected
770
+ - desktop-commander - use only for commands that keep running
771
+ (servers, dev watchers, GUI apps).
772
+ - Built-in tools - use for everything else:
773
+ (file operations, git commands, builds & installs, one-off shell commands)
774
+
775
+ Remember this decision rule:
776
+ - Stays running? → desktop-commander
777
+ - Finishes immediately? → built-in tools
778
+
779
+ -- Task Reporting --
780
+ Report all tasks to Coder, following these EXACT guidelines:
781
+ 1. Be granular. If you are investigating with multiple steps, report each step
782
+ to coder.
783
+ 2. IMMEDIATELY report status after receiving ANY user message
784
+ 3. Use "state": "working" when actively processing WITHOUT needing
785
+ additional user input
786
+ 4. Use "state": "complete" only when finished with a task
787
+ 5. Use "state": "failure" when you need ANY user input, lack sufficient
788
+ details, or encounter blockers
789
+
790
+ In your summary:
791
+ - Be specific about what you're doing
792
+ - Clearly indicate what information you need from the user when in
793
+ "failure" state
794
+ - Keep it under 160 characters
795
+ - Make it actionable
796
+
797
+ -- Context --
798
+ There is an existing application in the current directory.
799
+ Be sure to read CLAUDE.md before making any changes.
800
+
801
+ This is a real-world production application. As such, make sure to think carefully, use TODO lists, and plan carefully before making changes.
802
+ </system>
803
+ EOT
804
+ }
805
+
806
+ resource "coder_env" "claude_task_prompt" {
807
+ count = local. has_ai_prompt ? data. coder_workspace . me . start_count : 0
808
+ agent_id = coder_agent. dev . id
809
+ name = " CODER_MCP_CLAUDE_TASK_PROMPT"
810
+ value = data. coder_parameter . ai_prompt . value
811
+ }
812
+
813
+ resource "coder_env" "anthropic_api_key" {
814
+ count = local. has_ai_prompt ? data. coder_workspace . me . start_count : 0
815
+ agent_id = coder_agent. dev . id
816
+ name = " ANTHROPIC_API_KEY"
817
+ value = var. anthropic_api_key
818
+ }
819
+
820
+ resource "coder_app" "develop_sh" {
821
+ count = local. has_ai_prompt ? data. coder_workspace . me . start_count : 0
822
+ agent_id = coder_agent. dev . id
823
+ slug = " develop-sh"
824
+ display_name = " develop.sh"
825
+ icon = " ${ data . coder_workspace . me . access_url } /emojis/1f4bb.png" // 💻
826
+ command = " screen -x develop_sh"
827
+ share = " authenticated"
828
+ subdomain = true
829
+ open_in = " tab"
830
+ order = 0
831
+ }
832
+
833
+ resource "coder_script" "develop_sh" {
834
+ count = local. has_ai_prompt ? data. coder_workspace . me . start_count : 0
835
+ display_name = " develop.sh"
836
+ agent_id = coder_agent. dev . id
837
+ run_on_start = true
838
+ start_blocks_login = false
839
+ script = <<- EOT
840
+ #!/usr/bin/env bash
841
+ set -eux -o pipefail
842
+
843
+ # Wait for the agent startup script to finish.
844
+ for attempt in {1..60}; do
845
+ if [[ -f /tmp/.coder-startup-script.done ]]; then
846
+ break
847
+ fi
848
+ echo "Waiting for agent startup script to finish... ($attempt/60)"
849
+ sleep 10
850
+ done
851
+ cd "${ local . repo_dir } " && screen -dmS develop_sh /bin/sh -c 'while true; do ./scripts/develop.sh --; echo "develop.sh exited with code $? restarting in 30s"; sleep 30; done'
852
+ EOT
853
+ }
854
+
855
+ resource "coder_app" "preview" {
856
+ count = local. has_ai_prompt ? data. coder_workspace . me . start_count : 0
857
+ agent_id = coder_agent. dev . id
858
+ slug = " preview"
859
+ display_name = " Preview"
860
+ icon = " ${ data . coder_workspace . me . access_url } /emojis/1f50e.png" // 🔎
861
+ url = " http://localhost:8080"
862
+ share = " authenticated"
863
+ subdomain = true
864
+ open_in = " tab"
865
+ order = 1
866
+ healthcheck {
867
+ url = " http://localhost:8080/healthz"
868
+ interval = 5
869
+ threshold = 15
870
+ }
713
871
}
0 commit comments