Skip to content

Commit 33a94d2

Browse files
cnzgraycexll
andauthored
fix(executor): isolate CLAUDE_CODE_TMPDIR for nested claude to fix (no output) (#154)
* fix(executor): isolate CLAUDE_CODE_TMPDIR for nested claude to fix (no output) Claude 2.1.45+ calls Nz7() in preAction to clean its tasks directory on startup. When claude runs as a nested subprocess, it deletes the parent session's *.output files, causing the parent to read an empty string and display "(no output)". Fix: assign each nested claude process its own unique CLAUDE_CODE_TMPDIR (os.TempDir()/cc-nested-<pid>-<ns>) so it only cleans its own tasks directory and never touches the parent's output files. * fix(executor): use MkdirTemp for nested tmpdir --------- Co-authored-by: cexll <evanxian9@gmail.com>
1 parent b204ca9 commit 33a94d2

2 files changed

Lines changed: 22 additions & 3 deletions

File tree

codeagent-wrapper/internal/executor/env_stderr_test.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,11 +125,17 @@ func TestEnvInjection_LogsToStderrAndMasksKey(t *testing.T) {
125125
if cmd.env["ANTHROPIC_API_KEY"] != apiKey {
126126
t.Fatalf("ANTHROPIC_API_KEY=%q, want %q", cmd.env["ANTHROPIC_API_KEY"], apiKey)
127127
}
128+
if cmd.env["CLAUDE_CODE_TMPDIR"] == "" {
129+
t.Fatalf("expected CLAUDE_CODE_TMPDIR to be set for nested claude, got empty")
130+
}
128131

129132
if !strings.Contains(got, "Env: ANTHROPIC_BASE_URL="+baseURL) {
130133
t.Fatalf("stderr missing base URL env log; stderr=%q", got)
131134
}
132135
if !strings.Contains(got, "Env: ANTHROPIC_API_KEY=eyJh****test") {
133136
t.Fatalf("stderr missing masked API key log; stderr=%q", got)
134137
}
138+
if !strings.Contains(got, "CLAUDE_CODE_TMPDIR: ") {
139+
t.Fatalf("stderr missing CLAUDE_CODE_TMPDIR log; stderr=%q", got)
140+
}
135141
}

codeagent-wrapper/internal/executor/executor.go

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1154,10 +1154,23 @@ func RunCodexTaskWithContext(parentCtx context.Context, taskSpec TaskSpec, backe
11541154

11551155
injectTempEnv(cmd)
11561156

1157-
// Claude Code sets CLAUDECODE=1 in its child processes. If we don't
1158-
// remove it, the spawned `claude -p` detects the variable and refuses
1159-
// to start ("cannot be launched inside another Claude Code session").
11601157
if commandName == "claude" {
1158+
// Claude 2.1.45+ calls Nz7() on startup to clean its tasks directory,
1159+
// which deletes the parent session's *.output files and causes "(no output)".
1160+
// Assign each nested claude its own isolated tmpdir so it only cleans its own files.
1161+
nestedTmpDir, err := os.MkdirTemp("", fmt.Sprintf("cc-nested-%d-", os.Getpid()))
1162+
if err != nil {
1163+
logWarnFn("Failed to create isolated CLAUDE_CODE_TMPDIR: " + err.Error())
1164+
} else {
1165+
cmd.SetEnv(map[string]string{"CLAUDE_CODE_TMPDIR": nestedTmpDir})
1166+
defer os.RemoveAll(nestedTmpDir) //nolint:errcheck
1167+
logInfoFn("CLAUDE_CODE_TMPDIR: " + nestedTmpDir)
1168+
fmt.Fprintln(os.Stderr, " CLAUDE_CODE_TMPDIR: "+nestedTmpDir)
1169+
}
1170+
1171+
// Claude Code sets CLAUDECODE=1 in its child processes. If we don't
1172+
// remove it, the spawned `claude -p` detects the variable and refuses
1173+
// to start ("cannot be launched inside another Claude Code session").
11611174
cmd.UnsetEnv("CLAUDECODE")
11621175
}
11631176

0 commit comments

Comments
 (0)