diff --git a/packages/adapter-utils/src/server-utils.ts b/packages/adapter-utils/src/server-utils.ts index 3d273cd9..2b9de31f 100644 --- a/packages/adapter-utils/src/server-utils.ts +++ b/packages/adapter-utils/src/server-utils.ts @@ -272,7 +272,24 @@ 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. + 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) .then((target) => { const child = spawn(target.command, target.args, {