Fix Claude binary path corruption from shell integration escape sequences#20
Open
brndnsvr wants to merge 1 commit intolcoutodemos:mainfrom
Open
Fix Claude binary path corruption from shell integration escape sequences#20brndnsvr wants to merge 1 commit intolcoutodemos:mainfrom
brndnsvr wants to merge 1 commit intolcoutodemos:mainfrom
Conversation
The binary discovery fallback uses interactive shell (-i flag) to locate claude/whisper binaries via whence/which. Interactive shells source .zshrc which loads shell integrations (iTerm2, VS Code, Warp) that emit OSC escape sequences to stdout, contaminating paths. The same issue affects cli-env.ts PATH construction. This silently breaks subprocess spawning for anyone with terminal shell integration enabled — the app renders but Claude processes never start. Changes: - Add ~/.local/bin/claude to candidates list - Drop -i flag from shell fallbacks, add timeout: 3000 - Extract shared stripShellEscapes() and extractAbsoluteShellPath() helpers in cli-env.ts; use across all binary finders - Fix whisper binary lookup in index.ts (same escape contamination)
302f784 to
8f1e8c6
Compare
There was a problem hiding this comment.
Pull request overview
Fixes a macOS-specific subprocess discovery failure where execSync output from login shells can be polluted by terminal shell-integration OSC/ANSI escape sequences, causing invalid binary paths (notably for Claude CLI and whisper) and silent spawn failures.
Changes:
- Adds
~/.local/bin(and~/.local/bin/claude) to binary/path discovery to cover common modern installs. - Switches shell fallbacks from interactive login shells to non-interactive login shells and adds timeouts to avoid hangs.
- Introduces shared sanitization/parsing helpers (
stripShellEscapes,extractAbsoluteShellPath) to clean shell output before using it as a path.
Reviewed changes
Copilot reviewed 5 out of 5 changed files in this pull request and generated no comments.
Show a summary per file
| File | Description |
|---|---|
| src/main/cli-env.ts | Builds a more robust CLI PATH and adds helpers to strip escape sequences and safely extract absolute paths from shell output. |
| src/main/process-manager.ts | Updates Claude binary discovery to prefer ~/.local/bin/claude, removes interactive shell usage, and sanitizes shell-resolved paths. |
| src/main/index.ts | Fixes whisper binary lookup by using getCliEnv(), adding timeouts, and sanitizing shell output before treating it as a path. |
| src/main/claude/run-manager.ts | Aligns Claude binary discovery with non-interactive login shells, timeouts, and sanitized path extraction. |
| src/main/claude/pty-run-manager.ts | Same Claude binary discovery hardening for the PTY transport path. |
Comments suppressed due to low confidence (1)
src/main/process-manager.ts:45
- The NVM candidate
join(homedir(), '.nvm/versions/node', '**', 'bin/claude')is effectively dead: it’s used withtest -x "${c}", but**won’t expand because it’s quoted (and/bin/shdoesn’t support globstar by default). Either replace this with an explicit directory scan (iterate~/.nvm/versions/node/*/bin/claudevia fs) or drop the candidate and rely on the shell fallback.
join(homedir(), '.npm-global/bin/claude'),
join(homedir(), '.nvm/versions/node', '**', 'bin/claude'),
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
|
I was wondering why my recent commands were printing garbage. thx! |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
Clui CC silently fails to spawn Claude CLI subprocesses when the user has terminal shell integration enabled (iTerm2, VS Code terminal, Ghostty, etc.) and/or has Claude CLI installed at
~/.local/bin/claude.The app launches, the UI renders, but prompts never produce responses. There are no user-visible error messages — the debug log reveals the issue:
The resolved binary path is contaminated with OSC escape sequences, so
spawn()fails silently.Root Cause
The binary discovery fallback in
run-manager.ts,pty-run-manager.ts, andprocess-manager.tsuses an interactive shell (-iflag):Interactive shells source
.zshrc, which loads shell integrations that emit escape sequences to stdout. These get concatenated with the actual binary path, producing a garbage string.The same issue affects
cli-env.tsPATH construction (/bin/zsh -ilc "echo $PATH") and whisper binary lookup inindex.ts.Who This Affects
This hits anyone with either or both of:
A terminal emulator with shell integration — these inject OSC escape sequences into shell stdout, contaminating any path resolved via
execSyncwith a login shell:Claude CLI installed at
~/.local/bin/claude— common with newer Node/npm setups. This path wasn't in the hardcoded candidates list, forcing the shell fallback path where contamination occurs.Terminal.app and Alacritty are not affected — they don't inject shell integration sequences.
Changes
cli-env.ts:~/.local/binto the hardcoded PATH entries-i(interactive) flag from shell fallback commandsstripShellEscapes()helper to clean residual escape sequences from shell outputextractAbsoluteShellPath()— shared helper that strips escapes and validates the result is an absolute pathrun-manager.ts,pty-run-manager.ts,process-manager.ts:~/.local/bin/claudeto the candidates list (checked first via directtest -x)-iflag, addtimeout: 3000to shell fallbacksextractAbsoluteShellPath()instead of inline.trim()index.ts:env: getCliEnv()andtimeout: 3000to whisper shell commandsTest plan
~/.local/bin/claudenpm run buildpasses cleanly