fix(cli): preserve claude as argv[0] when spawning the native binary - #1710
Open
snyderra wants to merge 1 commit into
Open
fix(cli): preserve claude as argv[0] when spawning the native binary#1710snyderra wants to merge 1 commit into
claude as argv[0] when spawning the native binary#1710snyderra wants to merge 1 commit into
Conversation
`findGlobalClaudeCliPath()` realpaths every candidate it returns, so on a native install `runClaudeCli()` spawns `~/.local/share/claude/versions/<version>` and argv[0] becomes a bare version number like `2.1.238`. Tools that identify the running agent from argv[0] -- terminal workspace managers that label panes by the agent they detect, status lines, plain `pgrep claude` -- then see no claude at all, just an unrecognized process under a couple of `node` wrappers. Launching Claude Code directly keeps argv[0] as `claude`, so this shows up as "happy hides my agent". Pass `argv0: 'claude'` to the spawn. cross-spawn forwards options straight to `child_process.spawn` on POSIX, where argv0 is honored. Skipped on Windows, where cross-spawn may route the call through cmd.exe and overriding argv[0] would misreport the command actually being run. The existing `HAPPY_CLAUDE_PATH` escape hatch can work around this today (by pointing at a regular file named `claude` that execs the real binary), but only because that path is not itself a symlink -- which is not obvious, and should not be required to be visible to a process-based detector. Generated with [Claude Code](https://claude.ai/code) via [Happy](https://happy.engineering) Co-Authored-By: Claude <noreply@anthropic.com> Co-Authored-By: Happy <yesreply@happy.engineering>
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
Running Claude Code through happy makes it invisible to anything that identifies the running agent from
argv[0].findGlobalClaudeCliPath()callsresolvePathSafe()(i.e.fs.realpathSync) on every candidate, so on a native install the~/.local/bin/claudesymlink collapses to~/.local/share/claude/versions/<version>.runClaudeCli()then spawns that path, andargv[0]becomes a bare version number.Same machine, same Claude Code version, as seen by a terminal workspace manager that labels panes by the agent it detects in them:
So the pane shows up as an unrecognized process under a couple of
nodewrappers. This also breaks plainpgrep claudeand status-line integrations that key on the process name. Nothing about the session is actually different -- only the label the OS reports.Fix
Pass
argv0: 'claude'to the spawn inrunClaudeCli(). cross-spawn forwards options straight through tochild_process.spawnon POSIX, whereargv0is honored, so this is a one-option change with no behavioral effect on the child beyond the reported name.Skipped on Windows: cross-spawn may route the call through
cmd.exe, and overridingargv[0]there would misreport the command actually being run.Verification
Before/after, spawning a stand-in binary that reports its own
process.argv0:Confirmed on a real session too --
happy claudein a fresh pane goes from undetected toagent: claude, status: idle, and the agent's state (working / idle / blocked) tracks correctly from there.Tests
Added a regression test to
packages/happy-cli/scripts/claude_version_utils.test.tsthat stands in for the native binary with a symlink tonode(a shell script cannot be used here -- the kernel discardsargv[0]for#!scripts) and asserts the spawned process seesclaude. It fails onmainwith the version path and passes with this change.vitest run --project unit scripts/claude_version_utils.test.ts-> 51 passed.Note on the existing workaround
HAPPY_CLAUDE_PATHcan work around this today, but only if it points at a regular file namedclaudethat execs the real binary -- a symlink gets realpath'd away again byresolvePathSafe(). That is non-obvious enough that it probably should not be the requirement for being visible to a process-based detector.🤖 Generated with Claude Code