diff --git a/server/src/session.ts b/server/src/session.ts index 8086ecf..2adddc6 100644 --- a/server/src/session.ts +++ b/server/src/session.ts @@ -80,6 +80,13 @@ function maskEnv(env: Record): Record): Record { + return { + ...extraEnv, + CLAUDE_CODE_SYNC_PLUGIN_INSTALL: "1", + } +} + function pushIterable() { const queue: T[] = [] let resolver: ((v: IteratorResult) => void) | null = null @@ -412,7 +419,7 @@ class LoopSession { } } - const extraEnv = await buildLoopEnv({ + const loopEnv = await buildLoopEnv({ loopId, driver, vault: meta.config?.vault, @@ -441,7 +448,7 @@ class LoopSession { knowledgeRw: meta.config?.knowledge_rw, mountAllLoops: meta.config?.mount_all_loops, repo: meta.repo, - extraEnv, + extraEnv: loopEnv, ephemeralPorts: loopEphemeralPorts(meta), }, { onProgress: (msg) => { @@ -451,6 +458,7 @@ class LoopSession { }) if (building) setLoopPhase(loopId, "ready") updateLoopStatus(loopId, "Ready") + const sdkSpawnEnv = buildHeadlessSdkSpawnEnv(loopEnv) // Tell the container lifecycle scheduler that this loop has an active // SDK source. Released in destroy() via markInactive(loopId, "sdk"). markActive(loopId, "sdk") @@ -468,7 +476,7 @@ class LoopSession { cwd: V_LOOP_WORKDIR(loopId), env: { ...process.env, - ...extraEnv, + ...sdkSpawnEnv, }, model: activeModel?.id ?? "", thinking: { type: "adaptive" }, @@ -642,7 +650,7 @@ class LoopSession { loopId, command, args, - env: extraEnv, + env: sdkSpawnEnv, workdir: V_LOOP_WORKDIR(loopId), interactive: true, }) diff --git a/server/test/session-headless-env.test.ts b/server/test/session-headless-env.test.ts new file mode 100644 index 0000000..8c02144 --- /dev/null +++ b/server/test/session-headless-env.test.ts @@ -0,0 +1,20 @@ +import { test, expect, describe } from "bun:test" + +process.env.LOOPAT_HOME ??= `/tmp/loopat-session-env-test-${process.pid}` + +const { buildHeadlessSdkSpawnEnv } = await import("../src/session") + +describe("headless SDK spawn env", () => { + test("enables Claude Code marketplace plugin sync for SDK query spawns", () => { + const env = buildHeadlessSdkSpawnEnv({ + ANTHROPIC_API_KEY: "sk-test", + ANTHROPIC_BASE_URL: "https://anthropic.example.com/api/anthropic", + CLAUDE_CONFIG_DIR: "/loopat/loop/test/.claude", + CLAUDE_CODE_SYNC_PLUGIN_INSTALL: "0", + }) + + expect(env.ANTHROPIC_API_KEY).toBe("sk-test") + expect(env.CLAUDE_CONFIG_DIR).toBe("/loopat/loop/test/.claude") + expect(env.CLAUDE_CODE_SYNC_PLUGIN_INSTALL).toBe("1") + }) +})