From 26748a72e3e75a9458b09b7a13bf599e6b899745 Mon Sep 17 00:00:00 2001 From: Mathias Fredriksson Date: Mon, 23 Feb 2026 14:50:13 +0000 Subject: [PATCH] feat(registry/coder/modules/claude-code): add enable_state_persistence variable Add the enable_state_persistence variable (bool, default true) and pass it through to the agentapi sub-module. Bump agentapi version to 2.2.0. Add test runs for default and disabled state persistence. Add State Persistence documentation section to README. Refs coder/internal#1258 --- registry/coder/modules/claude-code/README.md | 32 +++++++++---- registry/coder/modules/claude-code/main.tf | 45 +++++++++++-------- .../coder/modules/claude-code/main.tftest.hcl | 30 +++++++++++++ 3 files changed, 79 insertions(+), 28 deletions(-) diff --git a/registry/coder/modules/claude-code/README.md b/registry/coder/modules/claude-code/README.md index 340eb175d..9f6312997 100644 --- a/registry/coder/modules/claude-code/README.md +++ b/registry/coder/modules/claude-code/README.md @@ -13,7 +13,7 @@ Run the [Claude Code](https://docs.anthropic.com/en/docs/agents-and-tools/claude ```tf module "claude-code" { source = "registry.coder.com/coder/claude-code/coder" - version = "4.7.5" + version = "4.8.0" agent_id = coder_agent.main.id workdir = "/home/coder/project" claude_api_key = "xxxx-xxxxx-xxxx" @@ -36,6 +36,20 @@ module "claude-code" { By default, Claude Code automatically resumes existing conversations when your workspace restarts. Sessions are tracked per workspace directory, so conversations continue where you left off. If no session exists (first start), your `ai_prompt` will run normally. To disable this behavior and always start fresh, set `continue = false` +## State Persistence + +AgentAPI can save and restore conversation state across workspace restarts. +This is enabled by default. + +To disable: + +```tf +module "claude-code" { + # ... other config + enable_state_persistence = false +} +``` + ## Examples ### Usage with Agent Boundaries @@ -47,7 +61,7 @@ By default, when `enable_boundary = true`, the module uses `coder boundary` subc ```tf module "claude-code" { source = "registry.coder.com/coder/claude-code/coder" - version = "4.7.5" + version = "4.8.0" agent_id = coder_agent.main.id workdir = "/home/coder/project" enable_boundary = true @@ -68,7 +82,7 @@ For tasks integration with AI Bridge, add `enable_aibridge = true` to the [Usage ```tf module "claude-code" { source = "registry.coder.com/coder/claude-code/coder" - version = "4.7.5" + version = "4.8.0" agent_id = coder_agent.main.id workdir = "/home/coder/project" enable_aibridge = true @@ -97,7 +111,7 @@ data "coder_task" "me" {} module "claude-code" { source = "registry.coder.com/coder/claude-code/coder" - version = "4.7.5" + version = "4.8.0" agent_id = coder_agent.main.id workdir = "/home/coder/project" ai_prompt = data.coder_task.me.prompt @@ -120,7 +134,7 @@ This example shows additional configuration options for version pinning, custom ```tf module "claude-code" { source = "registry.coder.com/coder/claude-code/coder" - version = "4.7.5" + version = "4.8.0" agent_id = coder_agent.main.id workdir = "/home/coder/project" @@ -176,7 +190,7 @@ Run and configure Claude Code as a standalone CLI in your workspace. ```tf module "claude-code" { source = "registry.coder.com/coder/claude-code/coder" - version = "4.7.5" + version = "4.8.0" agent_id = coder_agent.main.id workdir = "/home/coder/project" install_claude_code = true @@ -198,7 +212,7 @@ variable "claude_code_oauth_token" { module "claude-code" { source = "registry.coder.com/coder/claude-code/coder" - version = "4.7.5" + version = "4.8.0" agent_id = coder_agent.main.id workdir = "/home/coder/project" claude_code_oauth_token = var.claude_code_oauth_token @@ -271,7 +285,7 @@ resource "coder_env" "bedrock_api_key" { module "claude-code" { source = "registry.coder.com/coder/claude-code/coder" - version = "4.7.5" + version = "4.8.0" agent_id = coder_agent.main.id workdir = "/home/coder/project" model = "global.anthropic.claude-sonnet-4-5-20250929-v1:0" @@ -328,7 +342,7 @@ resource "coder_env" "google_application_credentials" { module "claude-code" { source = "registry.coder.com/coder/claude-code/coder" - version = "4.7.5" + version = "4.8.0" agent_id = coder_agent.main.id workdir = "/home/coder/project" model = "claude-sonnet-4@20250514" diff --git a/registry/coder/modules/claude-code/main.tf b/registry/coder/modules/claude-code/main.tf index 07e3eb5a4..8f517ebce 100644 --- a/registry/coder/modules/claude-code/main.tf +++ b/registry/coder/modules/claude-code/main.tf @@ -261,6 +261,12 @@ variable "enable_aibridge" { } } +variable "enable_state_persistence" { + type = bool + description = "Enable AgentAPI conversation state persistence across restarts." + default = true +} + resource "coder_env" "claude_code_md_path" { count = var.claude_md_path == "" ? 0 : 1 agent_id = var.agent_id @@ -356,25 +362,26 @@ locals { module "agentapi" { source = "registry.coder.com/coder/agentapi/coder" - version = "2.0.0" - - agent_id = var.agent_id - web_app_slug = local.app_slug - web_app_order = var.order - web_app_group = var.group - web_app_icon = var.icon - web_app_display_name = var.web_app_display_name - folder = local.workdir - cli_app = var.cli_app - cli_app_slug = var.cli_app ? "${local.app_slug}-cli" : null - cli_app_display_name = var.cli_app ? var.cli_app_display_name : null - agentapi_subdomain = var.subdomain - module_dir_name = local.module_dir_name - install_agentapi = var.install_agentapi - agentapi_version = var.agentapi_version - pre_install_script = var.pre_install_script - post_install_script = var.post_install_script - start_script = <<-EOT + version = "2.2.0" + + agent_id = var.agent_id + web_app_slug = local.app_slug + web_app_order = var.order + web_app_group = var.group + web_app_icon = var.icon + web_app_display_name = var.web_app_display_name + folder = local.workdir + cli_app = var.cli_app + cli_app_slug = var.cli_app ? "${local.app_slug}-cli" : null + cli_app_display_name = var.cli_app ? var.cli_app_display_name : null + agentapi_subdomain = var.subdomain + module_dir_name = local.module_dir_name + install_agentapi = var.install_agentapi + agentapi_version = var.agentapi_version + enable_state_persistence = var.enable_state_persistence + pre_install_script = var.pre_install_script + post_install_script = var.post_install_script + start_script = <<-EOT #!/bin/bash set -o errexit set -o pipefail diff --git a/registry/coder/modules/claude-code/main.tftest.hcl b/registry/coder/modules/claude-code/main.tftest.hcl index e273d3211..3d11989bc 100644 --- a/registry/coder/modules/claude-code/main.tftest.hcl +++ b/registry/coder/modules/claude-code/main.tftest.hcl @@ -387,6 +387,36 @@ run "test_aibridge_disabled_with_api_key" { } } +run "test_enable_state_persistence_default" { + command = plan + + variables { + agent_id = "test-agent" + workdir = "/home/coder" + } + + assert { + condition = var.enable_state_persistence == true + error_message = "enable_state_persistence should default to true" + } +} + +run "test_disable_state_persistence" { + command = plan + + variables { + agent_id = "test-agent" + workdir = "/home/coder" + enable_state_persistence = false + } + + assert { + condition = var.enable_state_persistence == false + error_message = "enable_state_persistence should be false when explicitly disabled" + } +} + + run "test_no_api_key_no_env" { command = plan