Windows: set %ProgramData%/%ALLUSERSPROFILE% so spawned ssh/scp work under Claude Desktop (fixes #10) - #11
Conversation
…der Claude Desktop (AiondaDotCom#10)
…m %SystemDrive% Adds real tests for the issue AiondaDotCom#10 fix. They were needed on two counts: The normalization mutates process.env at import time, and loadServerAs() only restored variables a test had explicitly overridden. So the first Windows-flavoured import leaked ProgramData into every later test, and the second import then took the already-set branch — both branches ended up 'covered' with nothing asserting them. The helper now always saves and restores the variables the module writes at import, and returns a snapshot of them (envAfterImport) because the restore happens before a test can look. Verified by skipping the new block: branch coverage drops to 98.89% with lines 37 and 44 uncovered, so the coverage is now earned rather than incidental. Also derives the last-resort default from %SystemDrive% rather than hardcoding C:. SystemDrive is in the environment Claude Desktop passes through, and a Windows install on another drive would otherwise get a path that does not exist. A trailing separator is tolerated. Nine tests cover: both variables missing, the SystemDrive-derived default, a trailing separator, SystemDrive itself missing, an existing ALLUSERSPROFILE winning over the default, backfilling ALLUSERSPROFILE from ProgramData, leaving both alone when set, staying inert on POSIX, and the key-auth spawn path that inherits the repaired environment. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
Merged — thanks, and thanks for reproducing the bisection independently on your own setup before opening this. Using I verified the failing paths still match Two changes on top before merging. Derive the default from const systemDrive = (process.env.SystemDrive || 'C:').replace(/[\\/]+$/, '');
process.env.ProgramData = process.env.ALLUSERSPROFILE || `${systemDrive}\\ProgramData`;
Tests. Verified rather than assumed: skipping the new test block drops branch coverage to 98.89% with lines 37 and 44 uncovered. The nine new tests cover both variables missing, the CI is green across One note for anyone hitting this before the next release: the manifest |
Fixes #10.
On Windows under Claude Desktop the extension launches with a stripped,
allow-listed environment that omits %ProgramData%/%ALLUSERSPROFILE%. Win32-OpenSSH
resolves %ProgramData% at startup to find its global config (%ProgramData%\ssh)
and exits 255 with no output when it is unset, so every spawned ssh/scp fails even
though the same command works from an interactive shell.
This normalizes the two vars once at module load, Windows only. No behavior change
on macOS/Linux, no transport change, and full ~/.ssh/config handling is preserved
since we still invoke the real ssh. Verified with the bisection from #10 on a
separate box (Windows 11, OpenSSH_for_Windows_9.5p2): empty ProgramData gives
ssh -V exit 255 with no output, setting ProgramData only gives exit 0.