From 9248881d42d02764751c7e9ca14afd26511a187e Mon Sep 17 00:00:00 2001 From: Jayakrishnan Date: Tue, 10 Mar 2026 12:01:46 +0000 Subject: [PATCH 1/2] fix(adapter-utils): strip Claude Code env vars from child processes When the Paperclip server is started from within a Claude Code session (e.g. `npx paperclipai run` in a Claude Code terminal), the `CLAUDECODE` and related env vars (`CLAUDE_CODE_ENTRYPOINT`, `CLAUDE_CODE_SESSION`, `CLAUDE_CODE_PARENT_SESSION`) leak into `process.env`. Since `runChildProcess()` spreads `process.env` into the child environment, every spawned `claude` CLI process inherits these vars and immediately exits with: "Claude Code cannot be launched inside another Claude Code session." This is particularly disruptive for the `claude-local` adapter, where every agent run spawns a `claude` child process. A single contaminated server start (or cron job that inherits the env) silently breaks all agent executions until the server is restarted in a clean environment. The fix deletes the four known Claude Code nesting-guard env vars from the merged environment before passing it to `spawn()`. Co-Authored-By: Claude Opus 4.6 --- packages/adapter-utils/src/server-utils.ts | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/packages/adapter-utils/src/server-utils.ts b/packages/adapter-utils/src/server-utils.ts index 3d273cd9..8e28fbff 100644 --- a/packages/adapter-utils/src/server-utils.ts +++ b/packages/adapter-utils/src/server-utils.ts @@ -272,7 +272,19 @@ export async function runChildProcess( const onLogError = opts.onLogError ?? ((err, id, msg) => console.warn({ err, runId: id }, msg)); return new Promise((resolve, reject) => { - const mergedEnv = ensurePathInEnv({ ...process.env, ...opts.env }); + const rawMerged: NodeJS.ProcessEnv = { ...process.env, ...opts.env }; + + // Strip Claude Code nesting-guard env vars so spawned `claude` processes + // don't refuse to start with "cannot be launched inside another session". + // These vars leak in when the Paperclip server itself is started from + // within a Claude Code session (e.g. `npx paperclipai run` in a terminal + // owned by Claude Code) or when cron inherits a contaminated shell env. + delete rawMerged.CLAUDECODE; + delete rawMerged.CLAUDE_CODE_ENTRYPOINT; + delete rawMerged.CLAUDE_CODE_SESSION; + delete rawMerged.CLAUDE_CODE_PARENT_SESSION; + + const mergedEnv = ensurePathInEnv(rawMerged); void resolveSpawnTarget(command, args, opts.cwd, mergedEnv) .then((target) => { const child = spawn(target.command, target.args, { From 1a53567cb6195a34f51aeb44979fe2f9aa7e5b9e Mon Sep 17 00:00:00 2001 From: Dotta <34892728+cryppadotta@users.noreply.github.com> Date: Tue, 10 Mar 2026 07:24:48 -0500 Subject: [PATCH 2/2] Apply suggestions from code review Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com> --- packages/adapter-utils/src/server-utils.ts | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/packages/adapter-utils/src/server-utils.ts b/packages/adapter-utils/src/server-utils.ts index 8e28fbff..2b9de31f 100644 --- a/packages/adapter-utils/src/server-utils.ts +++ b/packages/adapter-utils/src/server-utils.ts @@ -279,10 +279,15 @@ export async function runChildProcess( // These vars leak in when the Paperclip server itself is started from // within a Claude Code session (e.g. `npx paperclipai run` in a terminal // owned by Claude Code) or when cron inherits a contaminated shell env. - delete rawMerged.CLAUDECODE; - delete rawMerged.CLAUDE_CODE_ENTRYPOINT; - delete rawMerged.CLAUDE_CODE_SESSION; - delete rawMerged.CLAUDE_CODE_PARENT_SESSION; + const CLAUDE_CODE_NESTING_VARS = [ + "CLAUDECODE", + "CLAUDE_CODE_ENTRYPOINT", + "CLAUDE_CODE_SESSION", + "CLAUDE_CODE_PARENT_SESSION", + ] as const; + for (const key of CLAUDE_CODE_NESTING_VARS) { + delete rawMerged[key]; + } const mergedEnv = ensurePathInEnv(rawMerged); void resolveSpawnTarget(command, args, opts.cwd, mergedEnv)