From 15189aa4de5d97b80a4db77ae4d6cc164a0b2b12 Mon Sep 17 00:00:00 2001 From: Cian Johnston Date: Tue, 12 Aug 2025 18:00:40 +0100 Subject: [PATCH 1/4] feat(dogfood): integrate tasks support --- .github/workflows/dogfood.yaml | 1 + dogfood/coder/main.tf | 158 +++++++++++++++++++++++++++++++++ dogfood/main.tf | 13 +++ 3 files changed, 172 insertions(+) diff --git a/.github/workflows/dogfood.yaml b/.github/workflows/dogfood.yaml index db3292392db19..6735f7d2ce8ae 100644 --- a/.github/workflows/dogfood.yaml +++ b/.github/workflows/dogfood.yaml @@ -169,6 +169,7 @@ jobs: CODER_URL: https://dev.coder.com CODER_SESSION_TOKEN: ${{ secrets.CODER_SESSION_TOKEN }} # Template source & details + TF_VAR_CODER_DOGFOOD_ANTHROPIC_API_KEY: ${{ secrets.CODER_DOGFOOD_ANTHROPIC_API_KEY }} TF_VAR_CODER_TEMPLATE_NAME: ${{ secrets.CODER_TEMPLATE_NAME }} TF_VAR_CODER_TEMPLATE_VERSION: ${{ steps.vars.outputs.sha_short }} TF_VAR_CODER_TEMPLATE_DIR: ./coder diff --git a/dogfood/coder/main.tf b/dogfood/coder/main.tf index ae4088ec40fe7..e03553dac2371 100644 --- a/dogfood/coder/main.tf +++ b/dogfood/coder/main.tf @@ -38,6 +38,7 @@ locals { repo_base_dir = data.coder_parameter.repo_base_dir.value == "~" ? "/home/coder" : replace(data.coder_parameter.repo_base_dir.value, "/^~\\//", "/home/coder/") repo_dir = replace(try(module.git-clone[0].repo_dir, ""), "/^~\\//", "/home/coder/") container_name = "coder-${data.coder_workspace_owner.me.name}-${lower(data.coder_workspace.me.name)}" + has_ai_prompt = data.coder_parameter.ai_prompt.value != "" } data "coder_workspace_preset" "cpt" { @@ -150,6 +151,13 @@ data "coder_parameter" "image_type" { } } +variable "anthropic_api_key" { + type = string + description = "The API key used to authenticate with the Anthropic API." + default = "" + sensitive = true +} + locals { default_regions = { // keys should match group names @@ -242,6 +250,14 @@ data "coder_parameter" "devcontainer_autostart" { mutable = true } +data "coder_parameter" "ai_prompt" { + type = "string" + name = "AI Prompt" + default = "" + description = "Prompt for Claude Code" + mutable = false +} + provider "docker" { host = lookup(local.docker_host, data.coder_parameter.region.value) } @@ -380,6 +396,24 @@ module "devcontainers-cli" { agent_id = coder_agent.dev.id } +module "claude-code" { + count = local.has_ai_prompt ? data.coder_workspace.me.start_count : 0 + source = "dev.registry.coder.com/coder/claude-code/coder" + version = "~>2.0" + agent_id = coder_agent.dev.id + folder = local.repo_dir + install_claude_code = true + claude_code_version = "latest" + order = 999 + + experiment_report_tasks = true + experiment_post_install_script = <<-EOT + claude mcp add playwright npx -- @playwright/mcp@latest --headless --isolated --no-sandbox + claude mcp add desktop-commander npx -- @wonderwhy-er/desktop-commander@latest + EOT +} + + resource "coder_agent" "dev" { arch = "amd64" os = "linux" @@ -710,4 +744,128 @@ resource "coder_metadata" "container_info" { key = "region" value = data.coder_parameter.region.option[index(data.coder_parameter.region.option.*.value, data.coder_parameter.region.value)].name } + item { + key = "ai_task" + value = local.has_ai_prompt ? "yes" : "no" + } +} + +resource "coder_env" "claude_system_prompt" { + count = local.has_ai_prompt ? data.coder_workspace.me.start_count : 0 + agent_id = coder_agent.dev.id + name = "CODER_MCP_CLAUDE_SYSTEM_PROMPT" + value = <<-EOT + + -- Framing -- + You are a helpful Coding assistant. Aim to autonomously investigate + and solve issues the user gives you and test your work, whenever possible. + + Avoid shortcuts like mocking tests. When you get stuck, you can ask the user + but opt for autonomy. + + -- Tool Selection -- + - coder_report_task: providing status updates or requesting user input. + - playwright: previewing your changes after you made them + to confirm it worked as expected + - desktop-commander - use only for commands that keep running + (servers, dev watchers, GUI apps). + - Built-in tools - use for everything else: + (file operations, git commands, builds & installs, one-off shell commands) + + Remember this decision rule: + - Stays running? → desktop-commander + - Finishes immediately? → built-in tools + + -- 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. IMMEDIATELY report status after receiving ANY user message + 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 + + In your summary: + - Be specific about what you're doing + - Clearly indicate what information you need from the user when in + "failure" state + - Keep it under 160 characters + - Make it actionable + + -- Context -- + There is an existing application in the current directory. + Be sure to read CLAUDE.md before making any changes. + + This is a real-world production application. As such, make sure to think carefully, use TODO lists, and plan carefully before making changes. + + EOT +} + +resource "coder_env" "claude_task_prompt" { + count = local.has_ai_prompt ? data.coder_workspace.me.start_count : 0 + agent_id = coder_agent.dev.id + name = "CODER_MCP_CLAUDE_TASK_PROMPT" + value = data.coder_parameter.ai_prompt.value +} + +resource "coder_env" "anthropic_api_key" { + count = local.has_ai_prompt ? data.coder_workspace.me.start_count : 0 + agent_id = coder_agent.dev.id + name = "ANTHROPIC_API_KEY" + value = var.anthropic_api_key +} + +resource "coder_app" "develop_sh" { + count = local.has_ai_prompt ? data.coder_workspace.me.start_count : 0 + agent_id = coder_agent.dev.id + slug = "develop-sh" + display_name = "develop.sh" + icon = "${data.coder_workspace.me.access_url}/emojis/1f4bb.png" // 💻 + command = "screen -x develop_sh" + share = "authenticated" + subdomain = true + open_in = "tab" + order = 0 +} + +resource "coder_script" "develop_sh" { + count = local.has_ai_prompt ? data.coder_workspace.me.start_count : 0 + display_name = "develop.sh" + agent_id = coder_agent.dev.id + run_on_start = true + start_blocks_login = false + script = <<-EOT + #!/usr/bin/env bash + set -eux -o pipefail + + # Wait for the agent startup script to finish. + for attempt in {1..60}; do + if [[ -f /tmp/.coder-startup-script.done ]]; then + break + fi + echo "Waiting for agent startup script to finish... ($attempt/60)" + sleep 10 + done + 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' + EOT +} + +resource "coder_app" "preview" { + count = local.has_ai_prompt ? data.coder_workspace.me.start_count : 0 + agent_id = coder_agent.dev.id + slug = "preview" + display_name = "Preview" + icon = "${data.coder_workspace.me.access_url}/emojis/1f50e.png" // 🔎 + url = "http://localhost:8080" + share = "authenticated" + subdomain = true + open_in = "tab" + order = 1 + healthcheck { + url = "http://localhost:8080/healthz" + interval = 5 + threshold = 15 + } } diff --git a/dogfood/main.tf b/dogfood/main.tf index 72cd868f61645..c79e950efadf4 100644 --- a/dogfood/main.tf +++ b/dogfood/main.tf @@ -33,6 +33,13 @@ variable "CODER_TEMPLATE_MESSAGE" { type = string } +variable "CODER_DOGFOOD_ANTHROPIC_API_KEY" { + type = string + description = "The API key that workspaces will use to authenticate with the Anthropic API." + default = "" + sensitive = true +} + resource "coderd_template" "dogfood" { name = var.CODER_TEMPLATE_NAME display_name = "Write Coder on Coder" @@ -45,6 +52,12 @@ resource "coderd_template" "dogfood" { message = var.CODER_TEMPLATE_MESSAGE directory = var.CODER_TEMPLATE_DIR active = true + tf_vars = [ + { + name = "anthropic_api_key" + value = var.CODER_DOGFOOD_ANTHROPIC_API_KEY + } + ] } ] acl = { From fb0f771c568f56f4488636b39c65416a9c3b0f1c Mon Sep 17 00:00:00 2001 From: Cian Johnston Date: Fri, 15 Aug 2025 13:15:18 +0100 Subject: [PATCH 2/4] add corresponding icon to develop_sh script --- dogfood/coder/main.tf | 1 + 1 file changed, 1 insertion(+) diff --git a/dogfood/coder/main.tf b/dogfood/coder/main.tf index e03553dac2371..8ec22dfb56351 100644 --- a/dogfood/coder/main.tf +++ b/dogfood/coder/main.tf @@ -836,6 +836,7 @@ resource "coder_script" "develop_sh" { agent_id = coder_agent.dev.id run_on_start = true start_blocks_login = false + icon = "${data.coder_workspace.me.access_url}/emojis/1f4bb.png" // 💻 script = <<-EOT #!/usr/bin/env bash set -eux -o pipefail From e00acd79fae713085dcd16d79004b83e3b0a9dd2 Mon Sep 17 00:00:00 2001 From: Cian Johnston Date: Fri, 15 Aug 2025 16:02:25 +0100 Subject: [PATCH 3/4] adjust var name to match env --- dogfood/coder/main.tf | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dogfood/coder/main.tf b/dogfood/coder/main.tf index 8ec22dfb56351..ba1ac3a5efc4c 100644 --- a/dogfood/coder/main.tf +++ b/dogfood/coder/main.tf @@ -151,7 +151,7 @@ data "coder_parameter" "image_type" { } } -variable "anthropic_api_key" { +variable "coder_dogfood_anthropic_api_key" { type = string description = "The API key used to authenticate with the Anthropic API." default = "" @@ -814,7 +814,7 @@ resource "coder_env" "anthropic_api_key" { count = local.has_ai_prompt ? data.coder_workspace.me.start_count : 0 agent_id = coder_agent.dev.id name = "ANTHROPIC_API_KEY" - value = var.anthropic_api_key + value = var.coder_dogfood_anthropic_api_key } resource "coder_app" "develop_sh" { From 48a4ab0b92dafe61e623b3f290daefcab85d0d35 Mon Sep 17 00:00:00 2001 From: Cian Johnston Date: Fri, 15 Aug 2025 16:08:38 +0100 Subject: [PATCH 4/4] Revert "adjust var name to match env" This reverts commit e00acd79fae713085dcd16d79004b83e3b0a9dd2. --- dogfood/coder/main.tf | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dogfood/coder/main.tf b/dogfood/coder/main.tf index ba1ac3a5efc4c..8ec22dfb56351 100644 --- a/dogfood/coder/main.tf +++ b/dogfood/coder/main.tf @@ -151,7 +151,7 @@ data "coder_parameter" "image_type" { } } -variable "coder_dogfood_anthropic_api_key" { +variable "anthropic_api_key" { type = string description = "The API key used to authenticate with the Anthropic API." default = "" @@ -814,7 +814,7 @@ resource "coder_env" "anthropic_api_key" { count = local.has_ai_prompt ? data.coder_workspace.me.start_count : 0 agent_id = coder_agent.dev.id name = "ANTHROPIC_API_KEY" - value = var.coder_dogfood_anthropic_api_key + value = var.anthropic_api_key } resource "coder_app" "develop_sh" { pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy