CLAUDE_CODE_LOCAL_BINARY env-var override is dead code in Claude Desktop 1.7196.0 (Windows MSIX) — read but never consumed
CLAUDE_CODE_LOCAL_BINARY env-var override is dead code in Claude Desktop 1.7196.0 (Windows MSIX) — read but never consumed
Summary
Claude Desktop's bundled-CC manager (CCD in the logs) defines an initLocalBinary() method and all the downstream plumbing to support a CLAUDE_CODE_LOCAL_BINARY environment-variable override, but the shipped app.asar reads process.env.CLAUDE_CODE_LOCAL_BINARY as a bare expression with the value discarded. initLocalBinary() is never invoked anywhere in the bundle, so this.localBinaryPath stays null forever and every downstream check (getLocalBinaryPath(), getBinaryPathIfReady(), prepare(), etc.) falls through to the manifest-driven flow.
Net effect: the documented escape hatch for pinning Desktop to a specific local claude.exe is non-functional on shipped Desktop builds. Users on stale manifest-pinned versions (e.g., 2.1.138 while npm/PATH is at 2.1.142) cannot override Desktop's bundled-CC selection.
Affected version
- Claude Desktop: 1.7196.0 (Microsoft Store / MSIX,
Claude_pzs8sxrjxfjjc) - Windows 11
- Issue observed continuously across Desktop versions 1.3883.0 -> 1.7196.0 (per
main.loghistory — no[CCD] LOCAL OVERRIDElog lines have ever appeared, despite the code being present)
Evidence
1. Bare env-var expression with no consumer (offset 8770065 in app.asar):
S.info(`[CCD] Initialized with version ${this.requiredVersion}`),
process.env.CLAUDE_CODE_LOCAL_BINARY // <- read, value discarded, no `if`, no assignment
}
async initLocalBinary(A) {
try {
await HA.access(A, jA.constants.X_OK);
this.localBinaryPath = A;
S.warn(`[CCD] LOCAL OVERRIDE: Using local binary at ${A}`);
} catch {
S.error(`[CCD] LOCAL OVERRIDE: Binary not found or not executable at ${A}, falling back to normal flow`);
}
}
2. initLocalBinary is defined but never called. A full scan of app.asar for initLocalBinary returns exactly one occurrence: the definition itself. Every other local-binary reference (localBinaryPath, localBinaryInitPromise, getLocalBinaryPath) is downstream of that method and inert because the method is never invoked.
3. The downstream telemetry exists and is plumbed correctly:
getBinaryPathIfReady()has a branchXe("desktop_ccd_binary_resolved",{resolution:"local_override",resolved_version:...})getRequiredVersion()returns"local"iflocalBinaryPathis setinvalidateHostBinary()short-circuits when local override is active
All of this code is reachable only via initLocalBinary(), which has no caller.
4. Log evidence of total absence across user's history:
- 54
[CCD] Initialized with version ...lines spanning Apr 24 – May 15 - 0
[CCD] LOCAL OVERRIDE: ...lines (neither warn nor error) - Confirms the code path has never been entered
Reproduction
- On Windows with Claude Desktop >= 1.3883.0 installed via Microsoft Store (MSIX).
- Install Claude Code via the standalone Windows installer to
~\.local\bin\claude.exeat a version newer than what Desktop's manifest pins. Verify withclaude --version(PATH) vs.(Get-Item ~\AppData\Roaming\Claude\claude-code\*\claude.exe).VersionInfo.FileVersion. - Set:
setx CLAUDE_CODE_LOCAL_BINARY "C:\Users\<user>\.local\bin\claude.exe" - Verify visible to non-MSIX children:
cmd /c "echo %CLAUDE_CODE_LOCAL_BINARY%"-> prints the path. - Fully quit Claude Desktop from tray -> Quit, relaunch.
- Inspect
~\AppData\Roaming\Claude\logs\main.logfor[CCD] LOCAL OVERRIDE. - Open a new chat, check the foreground CC process:
Get-CimInstance Win32_Process -Filter "Name='claude.exe'" | Select ExecutablePath
Expected: Log contains [CCD] LOCAL OVERRIDE: Using local binary at <path>. Foreground claude.exe resolves to the PATH binary, not the AppData staged version.
Actual: No LOCAL OVERRIDE log lines. Foreground claude.exe resolves to ~\AppData\Roaming\Claude\claude-code\<manifestVersion>\claude.exe.
Impact
- Users cannot pin Desktop's foreground CC to a specific local binary, even though the supported escape hatch is documented in the code and named in telemetry (
resolution: "local_override"). - Drift between Desktop's manifest-pinned CC and the user's npm/PATH-installed CC cannot be reconciled by user action — users must wait for Anthropic's CCD manifest update channel to catch up.
- This was especially acute during the 2.1.141 stream-drop regression (GitHub #59304): users on Desktop 1.7196.0 staying on the older 2.1.138 pin were unaffected by the regression, but users who wanted to pin to a fixed local CC version had no working mechanism to do so.
Suggested fix
Either:
- Restore the wrapping
if/assignment so the env var is actually consumed:
const localBin = process.env.CLAUDE_CODE_LOCAL_BINARY;
if (localBin) {
this.localBinaryInitPromise = this.initLocalBinary(localBin);
}
- Or, if the override was intentionally disabled in shipped builds, remove the dead code and the telemetry branch to avoid future confusion.
Diagnostic hash (for triage)
- Package:
Claude_1.7196.0.0_x64__pzs8sxrjxfjjc app.asarsize: 24,748,161 bytes, mtime 2026-05-12 20:00:11- Match offset of
CLAUDE_CODE_LOCAL_BINARY: 8770034 (and one downstream telemetry hit) - Match offset of
initLocalBinarydefinition: 8770065 - No second occurrence of
initLocalBinaryin the file (i.e., no callers)
This issue has 3 comments on GitHub. Read the full discussion on GitHub ↗