fix: detect Claude/Codex when launched from GUI (stripped PATH)#263
Merged
vakovalskii merged 2 commits intoJul 21, 2026
Merged
Conversation
macOS/Linux GUI launches (Finder/Dock/Spotlight) inherit a minimal PATH (/usr/bin:/bin:/usr/sbin:/sbin) that omits user bin dirs such as ~/.local/bin and ~/.npm-global/bin where CLIs like claude and codex are installed. agents-detect.js resolves those agents purely via which() on process.env.PATH, so a GUI-launched app detected only agents shipping as a .app bundle (Cursor) and missed Claude Code / Codex — even though their history is present and the terminal-launched CLI detects them fine. Add src/shell-path.js: on startup, when PATH lacks any user-home dir, probe the login shell (SHELL -ilc) for its PATH and merge in the missing dirs. No-op (no shell spawn) when already launched from a terminal. Fixes both detection and in-process agent launching, generically for all agents.
Code review + security review of the shell-path module: - HIGH: add test/shell-path.test.js (15 cases) — gate logic, merge/dedup, control-char filtering, idempotency, win32 skip, opt-out, capture failure. - MEDIUM: pass killSignal:SIGKILL so a shell ignoring SIGTERM can't outlive the 4s timeout and hang startup. - MEDIUM: add CODBASH_NO_PATH_REPAIR=1 opt-out (login shell / rc files no longer run unconditionally with no escape hatch). - MEDIUM: log login-shell probe failures (was silently swallowed) and the bin/cli.js catch now logs, matching the repo-refresh convention. - MEDIUM: replace the startsWith($HOME) gate with hasUserBinPaths — a lone unrelated ~/Library entry no longer false-negatives and suppresses repair. - LOW: block TAB (\x09) and DEL (\x7f) too (full \x00-\x1f,\x7f), keeping non-ASCII/Unicode dirs valid. - LOW: unbundle -ilc into -i -l -c for shell-getopt portability. - LOW: validate $SHELL is absolute before exec; document the zsh fallback. - LOW: trim existing PATH entries before dedup to avoid whitespace dupes. - LOW: document the intentional append-after-system precedence + assert it in a test; note case-insensitive-FS dupes are an accepted no-op. - CODBASH_DEBUG=1 logs skip/augment decisions for field diagnosis.
Owner
|
Thanks for the thorough PR — the diagnosis is spot on: the desktop app spawns the server child inheriting the stripped GUI PATH ( |
Merged
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
When the desktop app is launched from Finder/Dock/Spotlight on macOS, the process inherits a minimal PATH (
/usr/bin:/bin:/usr/sbin:/sbin) that omits user bin dirs like~/.local/bin,~/.npm-global/bin, nvm/fnm shims, and Homebrew — where CLIs such asclaudeandcodexare installed.src/agents-detect.jsresolvesclaude/codexpurely viawhich()overprocess.env.PATH. So a GUI launch detects only agents that ship as a.appbundle (Cursor viaappBundle) and misses Claude Code and Codex entirely — even though their history is present and the terminal-launched CLI (codbash run) detects all of them.Reproduced on a real machine:
Fix
New
src/shell-path.js: at startup, whenprocess.env.PATHcontains no bin/shims directory under the user's home (the tell-tale of a Finder-stripped PATH), probe the user's login shell ($SHELL -i -l -c) for its real PATH and merge in the missing directories. Wired intobin/cli.jsbefore any command runs.CODBASH_NO_PATH_REPAIR=1skips the probe entirely.CODBASH_DEBUG=1logs decisions.killSignal: SIGKILL) so a slow/SIGTERM-ignoring rc file can't wedge startup.Acceptance criteria
claude/codexin~/.local/bin&~/.npm-global/bin→ both detected after startup.$SHELL/ hung rc / no sentinel) → error logged, existing PATH preserved, startup continues.CODBASH_NO_PATH_REPAIR=1andwin32short-circuit before any spawn.Test plan
test/shell-path.test.js— 15 cases (gate logic incl. false-negative guard, merge/dedup, control-char + TAB/DEL filtering, whitespace dedup, precedence assertion, idempotency, win32 skip, opt-out, capture-failure, empty capture, process.env mutation)node --test test/*.test.js)agents-detectunderPATH=/usr/bin:/bin:/usr/sbin:/sbingoescursor→claude, codex, cursornode -csyntax check on all touched filesReview notes
Went through a code review and a security review. No injection vector (fixed printf script, args array, no
shell:true); the probe mirrors the same trust surface as opening a terminal (a compromised rc file already runs on any terminal open) and is now opt-out-able. All MEDIUM/LOW findings from both reviews are fixed in the second commit.