Skip to content

Commit 51ec6e3

Browse files
fix: resolve issues with claude-code session resumption (#496)
## Description Fixes session resumption logic by having the continue flag decide whether to continue a workspace based on session history ## Type of Change - [ ] New module - [ ] New template - [X] Bug fix - [X] Feature/enhancement - [ ] Documentation - [ ] Other ## Module Information <!-- Delete this section if not applicable --> **Path:** `registry/coder/modules/claude-code` **New version:** `v3.2.2` **Breaking change:** [ ] Yes [X] No ## Testing & Validation - [X] Tests pass (`bun test`) - [X] Code formatted (`bun fmt`) - [X] Changes tested locally ## Related Issues <!-- Link related issues or write "None" if not applicable --> --------- Co-authored-by: Copilot <[email protected]>
1 parent 843b1f1 commit 51ec6e3

File tree

4 files changed

+81
-32
lines changed

4 files changed

+81
-32
lines changed

registry/coder/modules/claude-code/README.md

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ Run the [Claude Code](https://docs.anthropic.com/en/docs/agents-and-tools/claude
1313
```tf
1414
module "claude-code" {
1515
source = "registry.coder.com/coder/claude-code/coder"
16-
version = "3.2.1"
16+
version = "3.2.2"
1717
agent_id = coder_agent.example.id
1818
workdir = "/home/coder/project"
1919
claude_api_key = "xxxx-xxxxx-xxxx"
@@ -32,6 +32,10 @@ module "claude-code" {
3232
- You can get the API key from the [Anthropic Console](https://console.anthropic.com/dashboard).
3333
- You can get the Session Token using the `claude setup-token` command. This is a long-lived authentication token (requires Claude subscription)
3434

35+
### Session Resumption Behavior
36+
37+
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`
38+
3539
## Examples
3640

3741
### Usage with Agent Boundaries
@@ -66,7 +70,7 @@ data "coder_parameter" "ai_prompt" {
6670
6771
module "claude-code" {
6872
source = "registry.coder.com/coder/claude-code/coder"
69-
version = "3.2.1"
73+
version = "3.2.2"
7074
agent_id = coder_agent.example.id
7175
workdir = "/home/coder/project"
7276
@@ -102,7 +106,7 @@ Run and configure Claude Code as a standalone CLI in your workspace.
102106
```tf
103107
module "claude-code" {
104108
source = "registry.coder.com/coder/claude-code/coder"
105-
version = "3.2.1"
109+
version = "3.2.2"
106110
agent_id = coder_agent.example.id
107111
workdir = "/home/coder"
108112
install_claude_code = true
@@ -125,7 +129,7 @@ variable "claude_code_oauth_token" {
125129
126130
module "claude-code" {
127131
source = "registry.coder.com/coder/claude-code/coder"
128-
version = "3.2.1"
132+
version = "3.2.2"
129133
agent_id = coder_agent.example.id
130134
workdir = "/home/coder/project"
131135
claude_code_oauth_token = var.claude_code_oauth_token
@@ -198,7 +202,7 @@ resource "coder_env" "bedrock_api_key" {
198202
199203
module "claude-code" {
200204
source = "registry.coder.com/coder/claude-code/coder"
201-
version = "3.2.1"
205+
version = "3.2.2"
202206
agent_id = coder_agent.example.id
203207
workdir = "/home/coder/project"
204208
model = "global.anthropic.claude-sonnet-4-5-20250929-v1:0"
@@ -255,7 +259,7 @@ resource "coder_env" "google_application_credentials" {
255259
256260
module "claude-code" {
257261
source = "registry.coder.com/coder/claude-code/coder"
258-
version = "3.2.1"
262+
version = "3.2.2"
259263
agent_id = coder_agent.example.id
260264
workdir = "/home/coder/project"
261265
model = "claude-sonnet-4@20250514"

registry/coder/modules/claude-code/main.test.ts

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -167,7 +167,7 @@ describe("claude-code", async () => {
167167
const { id } = await setup({
168168
moduleVariables: {
169169
permission_mode: mode,
170-
task_prompt: "test prompt",
170+
ai_prompt: "test prompt",
171171
},
172172
});
173173
await execModuleScript(id);
@@ -185,7 +185,7 @@ describe("claude-code", async () => {
185185
const { id } = await setup({
186186
moduleVariables: {
187187
model: model,
188-
task_prompt: "test prompt",
188+
ai_prompt: "test prompt",
189189
},
190190
});
191191
await execModuleScript(id);
@@ -198,21 +198,34 @@ describe("claude-code", async () => {
198198
expect(startLog.stdout).toContain(`--model ${model}`);
199199
});
200200

201-
test("claude-continue-previous-conversation", async () => {
201+
test("claude-continue-resume-existing-session", async () => {
202202
const { id } = await setup({
203203
moduleVariables: {
204204
continue: "true",
205-
task_prompt: "test prompt",
205+
ai_prompt: "test prompt",
206206
},
207207
});
208+
209+
// Create a mock session file with the predefined task session ID
210+
const taskSessionId = "cd32e253-ca16-4fd3-9825-d837e74ae3c2";
211+
const sessionDir = `/home/coder/.claude/projects/-home-coder-project`;
212+
await execContainer(id, ["mkdir", "-p", sessionDir]);
213+
await execContainer(id, [
214+
"bash",
215+
"-c",
216+
`touch ${sessionDir}/session-${taskSessionId}.jsonl`,
217+
]);
218+
208219
await execModuleScript(id);
209220

210221
const startLog = await execContainer(id, [
211222
"bash",
212223
"-c",
213224
"cat /home/coder/.claude-module/agentapi-start.log",
214225
]);
215-
expect(startLog.stdout).toContain("--continue");
226+
expect(startLog.stdout).toContain("--resume");
227+
expect(startLog.stdout).toContain(taskSessionId);
228+
expect(startLog.stdout).toContain("Resuming existing task session");
216229
});
217230

218231
test("pre-post-install-scripts", async () => {

registry/coder/modules/claude-code/main.tf

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -134,8 +134,8 @@ variable "resume_session_id" {
134134

135135
variable "continue" {
136136
type = bool
137-
description = "Load the most recent conversation in the current directory. Task will fail in a new workspace with no conversation/session to continue"
138-
default = false
137+
description = "Automatically continue existing sessions on workspace restart. When true, resumes existing conversation if found, otherwise runs prompt or starts new session. When false, always starts fresh (ignores existing sessions)."
138+
default = true
139139
}
140140

141141
variable "dangerously_skip_permissions" {

registry/coder/modules/claude-code/scripts/start.sh

Lines changed: 51 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -64,37 +64,70 @@ function validate_claude_installation() {
6464
fi
6565
}
6666

67-
ARGS=()
67+
TASK_SESSION_ID="cd32e253-ca16-4fd3-9825-d837e74ae3c2"
6868

69-
function build_claude_args() {
70-
if [ -n "$ARG_MODEL" ]; then
71-
ARGS+=(--model "$ARG_MODEL")
69+
task_session_exists() {
70+
if find "$HOME/.claude" -type f -name "*${TASK_SESSION_ID}*" 2> /dev/null | grep -q .; then
71+
return 0
72+
else
73+
return 1
7274
fi
75+
}
7376

74-
if [ -n "$ARG_RESUME_SESSION_ID" ]; then
75-
ARGS+=(--resume "$ARG_RESUME_SESSION_ID")
76-
fi
77+
ARGS=()
7778

78-
if [ "$ARG_CONTINUE" = "true" ]; then
79-
ARGS+=(--continue)
79+
function start_agentapi() {
80+
mkdir -p "$ARG_WORKDIR"
81+
cd "$ARG_WORKDIR"
82+
83+
if [ -n "$ARG_MODEL" ]; then
84+
ARGS+=(--model "$ARG_MODEL")
8085
fi
8186

8287
if [ -n "$ARG_PERMISSION_MODE" ]; then
8388
ARGS+=(--permission-mode "$ARG_PERMISSION_MODE")
8489
fi
8590

86-
}
87-
88-
function start_agentapi() {
89-
mkdir -p "$ARG_WORKDIR"
90-
cd "$ARG_WORKDIR"
91-
if [ -n "$ARG_AI_PROMPT" ]; then
92-
ARGS+=(--dangerously-skip-permissions "$ARG_AI_PROMPT")
93-
else
94-
if [ -n "$ARG_DANGEROUSLY_SKIP_PERMISSIONS" ]; then
91+
if [ -n "$ARG_RESUME_SESSION_ID" ]; then
92+
echo "Using explicit resume_session_id: $ARG_RESUME_SESSION_ID"
93+
ARGS+=(--resume "$ARG_RESUME_SESSION_ID")
94+
if [ "$ARG_DANGEROUSLY_SKIP_PERMISSIONS" = "true" ]; then
9595
ARGS+=(--dangerously-skip-permissions)
9696
fi
97+
elif [ "$ARG_CONTINUE" = "true" ]; then
98+
if task_session_exists; then
99+
echo "Task session detected (ID: $TASK_SESSION_ID)"
100+
ARGS+=(--resume "$TASK_SESSION_ID")
101+
if [ "$ARG_DANGEROUSLY_SKIP_PERMISSIONS" = "true" ]; then
102+
ARGS+=(--dangerously-skip-permissions)
103+
fi
104+
echo "Resuming existing task session"
105+
else
106+
echo "No existing task session found"
107+
ARGS+=(--session-id "$TASK_SESSION_ID")
108+
if [ -n "$ARG_AI_PROMPT" ]; then
109+
ARGS+=(--dangerously-skip-permissions "$ARG_AI_PROMPT")
110+
echo "Starting new task session with prompt"
111+
else
112+
if [ "$ARG_DANGEROUSLY_SKIP_PERMISSIONS" = "true" ]; then
113+
ARGS+=(--dangerously-skip-permissions)
114+
fi
115+
echo "Starting new task session"
116+
fi
117+
fi
118+
else
119+
echo "Continue disabled, starting fresh session"
120+
if [ -n "$ARG_AI_PROMPT" ]; then
121+
ARGS+=(--dangerously-skip-permissions "$ARG_AI_PROMPT")
122+
echo "Starting new session with prompt"
123+
else
124+
if [ "$ARG_DANGEROUSLY_SKIP_PERMISSIONS" = "true" ]; then
125+
ARGS+=(--dangerously-skip-permissions)
126+
fi
127+
echo "Starting claude code session"
128+
fi
97129
fi
130+
98131
printf "Running claude code with args: %s\n" "$(printf '%q ' "${ARGS[@]}")"
99132

100133
if [ "${ARG_ENABLE_BOUNDARY:-false}" = "true" ]; then
@@ -140,5 +173,4 @@ function start_agentapi() {
140173
}
141174

142175
validate_claude_installation
143-
build_claude_args
144176
start_agentapi

0 commit comments

Comments
 (0)