Skip to content

refactor(claude-code): harden CLI discovery and async-spawn the agent #2930

Merged
abose merged 4 commits into
mainfrom
ai
May 20, 2026
Merged

refactor(claude-code): harden CLI discovery and async-spawn the agent #2930
abose merged 4 commits into
mainfrom
ai

Conversation

@abose
Copy link
Copy Markdown
Member

@abose abose commented May 20, 2026

Path discovery walks a fallback chain instead of returning the first
hit blindly: native installer binaries first (existence check only —
no shim chain to break), then PATH/known-location candidates each
validated with claude --version, so broken installs (orphan npm
shims whose cli.js was deleted) get skipped rather than handed to
the SDK. Windows prefers .exe over .cmd/.bat when both resolve and
drops extensionless POSIX scripts it can't execute.

Fixes the nvm path bug — previously hardcoded process.version (the
node Phoenix ships, not the user's selected nvm version). Now reads
$NVM_DIR / ~/.nvm/alias/default and enumerates installed versions
newest-first.

auth status and --version spawn async via new _spawnClaude. spawnSync
had been blocking the Node event loop for up to 10 s on the auth
check, freezing the integrated terminal and file watchers during
every panel mount. Windows .cmd shim handling preserved (shell:true
plus manual quoting per GHSA-fm6v-wmjp-5rxq hardening).

Paths-with-spaces audit: dropped shell concatenation from auth-status
invocation, replaced `test -x` probe with fs.accessSync, fixed
quoting around the resolved binary.

Discovery results cached — positive indefinitely (self-healed via
{ force: true } on spawn-level failure in checkAvailability),
negative for 15 s so a fresh install during a session is detected.
Concurrent callers share one in-flight walk via a deduped promise.
New checkAvailability({ refresh: true }) lets active poll loops
bypass the negative cache while caching stays effective for boot
and entitlement-event checks.Path discovery walks a fallback chain instead of returning the first
hit blindly: native installer binaries first (existence check only —
no shim chain to break), then PATH/known-location candidates each
validated with claude --version, so broken installs (orphan npm
shims whose cli.js was deleted) get skipped rather than handed to
the SDK. Windows prefers .exe over .cmd/.bat when both resolve and
drops extensionless POSIX scripts it can't execute.

Fixes the nvm path bug — previously hardcoded process.version (the
node Phoenix ships, not the user's selected nvm version). Now reads
$NVM_DIR / ~/.nvm/alias/default and enumerates installed versions
newest-first.

auth status and --version spawn async via new _spawnClaude. spawnSync
had been blocking the Node event loop for up to 10 s on the auth
check, freezing the integrated terminal and file watchers during
every panel mount. Windows .cmd shim handling preserved (shell:true
plus manual quoting per GHSA-fm6v-wmjp-5rxq hardening).

Paths-with-spaces audit: dropped shell concatenation from auth-status
invocation, replaced `test -x` probe with fs.accessSync, fixed
quoting around the resolved binary.

Discovery results cached — positive indefinitely (self-healed via
{ force: true } on spawn-level failure in checkAvailability),
negative for 15 s so a fresh install during a session is detected.
Concurrent callers share one in-flight walk via a deduped promise.
New checkAvailability({ refresh: true }) lets active poll loops
bypass the negative cache while caching stays effective for boot
and entitlement-event checks.Path discovery walks a fallback chain instead of returning the first
hit blindly: native installer binaries first (existence check only —
no shim chain to break), then PATH/known-location candidates each
validated with claude --version, so broken installs (orphan npm
shims whose cli.js was deleted) get skipped rather than handed to
the SDK. Windows prefers .exe over .cmd/.bat when both resolve and
drops extensionless POSIX scripts it can't execute.

Fixes the nvm path bug — previously hardcoded process.version (the
node Phoenix ships, not the user's selected nvm version). Now reads
$NVM_DIR / ~/.nvm/alias/default and enumerates installed versions
newest-first.

auth status and --version spawn async via new _spawnClaude. spawnSync
had been blocking the Node event loop for up to 10 s on the auth
check, freezing the integrated terminal and file watchers during
every panel mount. Windows .cmd shim handling preserved (shell:true
plus manual quoting per GHSA-fm6v-wmjp-5rxq hardening).

Paths-with-spaces audit: dropped shell concatenation from auth-status
invocation, replaced `test -x` probe with fs.accessSync, fixed
quoting around the resolved binary.

Discovery results cached — positive indefinitely (self-healed via
{ force: true } on spawn-level failure in checkAvailability),
negative for 15 s so a fresh install during a session is detected.
Concurrent callers share one in-flight walk via a deduped promise.
New checkAvailability({ refresh: true }) lets active poll loops
bypass the negative cache while caching stays effective for boot
and entitlement-event checks.

abose added 4 commits May 20, 2026 14:21
Path discovery walks a fallback chain instead of returning the first
hit blindly: native installer binaries first (existence check only —
no shim chain to break), then PATH/known-location candidates each
validated with `claude --version`, so broken installs (orphan npm
shims whose cli.js was deleted) get skipped rather than handed to
the SDK. Windows prefers .exe over .cmd/.bat when both resolve and
drops extensionless POSIX scripts it can't execute.

Fixes the nvm path bug — previously hardcoded process.version (the
node Phoenix ships, not the user's selected nvm version). Now reads
\$NVM_DIR / ~/.nvm/alias/default and enumerates installed versions
newest-first.

auth status and --version spawn async via new _spawnClaude. spawnSync
had been blocking the Node event loop for up to 10 s on the auth
check, freezing the integrated terminal and file watchers during
every panel mount. Windows .cmd shim handling preserved (shell:true
plus manual quoting per CVE-2024-27980 hardening).

Paths-with-spaces audit: dropped shell concatenation from auth-status
invocation, replaced \`test -x\` probe with fs.accessSync, fixed
quoting around the resolved binary.

Discovery results cached — positive indefinitely (self-healed via
{ force: true } on spawn-level failure in checkAvailability),
negative for 15 s so a fresh install during a session is detected.
Concurrent callers share one in-flight walk via a deduped promise.
New checkAvailability({ refresh: true }) lets active poll loops
bypass the negative cache while caching stays effective for boot
and entitlement-event checks.
@sonarqubecloud
Copy link
Copy Markdown

@abose abose merged commit c91b244 into main May 20, 2026
10 of 21 checks passed
@abose abose deleted the ai branch May 20, 2026 09:36
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant