Repository navigation
fix(server): Claude probes no longer spawn in the packaged server's home cwd - #19174
akushonkamen wants to merge 1 commit into
Conversation
…ome cwd Packaged desktop builds deliberately start the Node server with cwd = $HOME (DesktopEnvironment's backendCwd). The Claude driver's instance-level auxiliary spawns — the SDK capability probe and the 'claude --version' health check — inherited that directory: the driver handed its startup cwd to the probe, and runClaudeCommand passed no cwd to ChildProcess.make at all. Third-party 'claude' shims that treat their cwd as the project boundary (container runtimes, mount-scoped sandboxes, governance shims) then fail the probe, which runs first and marks the provider Unavailable before any bound project is reached. The driver now passes the server's stateDir — the app's own user-data directory, present in dev, packaged, and WSL alike, and never a project — as the explicit spawn cwd, and runClaudeCommand threads that cwd into ChildProcess.make instead of silently inheriting. This is the narrow option-B fix from the issue: backendCwd (fix A) and the cross-driver env/cwd consolidation are untouched, and the per-workspace probe path (snapshotForCwd) keeps receiving the real workspace cwd. Model: GLM-5.3-Flash (Z.ai) · Harness: ZCode CLI
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
ApprovabilityVerdict: Approved at Macroscope's review found this PR approvable — This is a focused server bug fix that confines Claude's auxiliary probes to the app state directory instead of the packaged server's home cwd. The changed production paths are limited and covered by targeted tests, while workspace execution remains unchanged. You can add or adjust custom eligibility rules. Learn more. |
|
Note 🤖 Claude Opus 5.5 responding on behalf of Theo Closing because this PR states that GLM wrote code in it:
We do not accept code written by GLM, Kimi, MiniMax, Mistral, Gemini, or alpha models, or by Muse models other than Muse Wonder Full. See Models we do not accept. To have this considered again, open a new PR with the code written by a different model and link this one. |
Fixes #2867.
The problem
Packaged desktop builds deliberately start the Node server with
cwd = $HOME(apps/desktop/src/app/DesktopEnvironment.ts:220,backendCwd: input.isPackaged ? homeDirectory : appRoot). The Claude driver's instance-level auxiliary spawns inherited that directory:ClaudeDriverhanded its startupcwd(fromServerConfig) straight toprobeClaudeCapabilities, so the SDK capability probe spawns the CLI at the server's cwd —/Users/yp1017in every installed build.runClaudeCommand(theclaude --versionhealth check) passed nocwdtoChildProcess.make, so it silently inherited the server's process cwd.Third-party
claudeshims that treat their cwd as the project boundary (containerized runtimes, mount-scoped sandboxes, governance shims) fail on/Users/yp1017— and the probe runs first, marks the provider Unavailable, so the user never reaches the (correctly workspace-bound) session path. This is the probe-side half of the issue; the WSL variant from the third comment lands on the same call sites.The fix (narrow — option B from the issue body)
ClaudeDrivernow passes the server'sstateDir(the app's own user-data directory — already available fromServerConfig, exists in dev/packaged/WSL alike, never a project) as the explicit cwd for the instance-level capability probe, its cache key, andcheckClaudeProviderStatus.runClaudeCommandaccepts an optionalcwdand threads it intoChildProcess.make;checkClaudeProviderStatusforwards itscwdto it.Deliberately out of scope:
backendCwd = homeDirectory(fix A) and the cross-driver env/cwd consolidation @rafazaya outlined — both are maintainer decisions this PR does not preempt. The per-workspace path (snapshotForCwd→probeClaudeWorkspaceSnapshot) already receives the real workspace cwd and is untouched. No environment propagation is changed anywhere.Evidence
Runtime repro (pre-fix). With the server process sitting in a simulated packaged cwd, driving the real
probeClaudeCapabilitieswith a shimclaudeexecutable that logsprocess.cwd()shows the subprocess running at that exact directory in both spawn branches (driver-passed cwd and pure inheritance):Focused tests (this PR). At the driver level, the mock CLI now records the cwd it was spawned at (
T3_FIXTURE_RECORD_CWD, opt-in): before the fix it records the server's startup cwd; after, the state dir:vp test run apps/server/src/provider/ProviderInstanceRegistry.test.ts— red pre-fix → 9 passed post-fix (new live test: both auxiliary spawns land in the state dir).vp test run apps/server/src/provider/ProviderRegistry.test.ts— red pre-fix → 63 passed post-fix (new test: the version probe spawn carries the explicit cwd).vp test run apps/server/src/provider/ClaudeCapabilitiesProbe.test.ts— 6 passed (unchanged probe options contract).tsc-rs --noEmit(apps/server): clean.vp linton changed files: 0 warnings, 0 errors.Not checked locally: a full packaged desktop build (the packaged
backendCwdvalue is verified statically and the server-side behavior is covered by the tests above).Trade-off note
In dev builds the instance-level probe's project-scoped setting discovery moves from the repo root to the state dir; user-scope discovery (
~/.claude,CLAUDE_CONFIG_DIR) and per-workspace discovery viasnapshotForCwdare unchanged, so thread-level skills/commands are unaffected.Model: GLM-5.3-Flash (Z.ai) · Harness: ZCode CLI