Skip to content

fix(compile): use execPath for process.argv[1] in standalone binaries#32990

Merged
bartlomieju merged 4 commits intomainfrom
fix/compile-process-argv-standalone
Mar 26, 2026
Merged

fix(compile): use execPath for process.argv[1] in standalone binaries#32990
bartlomieju merged 4 commits intomainfrom
fix/compile-process-argv-standalone

Conversation

@bartlomieju
Copy link
Copy Markdown
Member

Summary

In compiled (standalone) binaries, process.argv[1] was set to the internal
temp extraction path (e.g. /tmp/deno-compile-foo/path/to/main.ts) instead of
the binary path. This caused npm CLI tools like @google/gemini-cli to see the
temp path as a positional argument, breaking their argument parsing.

For example, running gemini -p "hello" would fail with:

Cannot use both a positional prompt and the --prompt (-p) flag together

because the temp path leaked into process.argv and was parsed as a positional arg
by yargs.

Fix

For standalone binaries (Deno.build.standalone), process.argv[1] now uses
Deno.execPath() (the compiled binary path), matching Node.js SEA behavior
where argv[0] and argv[1] both point to the executable.

Related: #28915 (fixes argv[0], this PR fixes argv[1])

Test plan

  • New spec test compile::standalone_process_argv verifies argv[1] === Deno.execPath() and user args start at argv[2]
  • Manual verification with compiled @google/gemini-cli

🤖 Generated with Claude Code

In compiled (standalone) binaries, `process.argv[1]` was set to the
internal temp extraction path (e.g. `/tmp/deno-compile-foo/main.ts`)
instead of the binary path. This caused npm CLI tools like
`@google/gemini-cli` to see the temp path as a positional argument,
breaking their argument parsing.

For standalone binaries, `process.argv[1]` now uses `Deno.execPath()`
(the compiled binary path), matching Node.js SEA behavior where
`argv[0]` and `argv[1]` both point to the executable.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@kajukitli
Copy link
Copy Markdown
Contributor

looks good overall. one thing i'd want covered before merging: the new spec only exercises the unix path (./main), but this argv behavior should matter on windows too. can we add the matching main.exe case here, like most other tests/specs/compile/* tests do, unless there's a reason this one can't run there?

tests/specs/compile/standalone_process_argv/__test__.jsonc

@kajukitli
Copy link
Copy Markdown
Contributor

re-reviewed. the windows main.exe case is in now, which was the only thing i wanted covered. this looks good to me.

@bartlomieju bartlomieju merged commit 6a66ea5 into main Mar 26, 2026
112 checks passed
@bartlomieju bartlomieju deleted the fix/compile-process-argv-standalone branch March 26, 2026 12:41
bartlomieju added a commit that referenced this pull request Mar 26, 2026
…ry relaunches

When Node.js apps (e.g. @google/gemini-cli) relaunch themselves via
`spawn(process.execPath, [process.argv[1], ...args])`, the standalone
binary would include the exe path as a user argument in `Deno.args` /
`process.argv`. This is because `process.argv[1]` in standalone mode
is the exe path (set by #32990), and the binary's arg parser only
skipped `argv[0]`.

Now the standalone binary detects when the first CLI arg matches the
current exe path and strips it, preventing the path from leaking into
user arguments.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
bartlomieju added a commit that referenced this pull request Mar 26, 2026
…ry relaunches (#33016)

## Summary

Fixes an issue where compiled npm CLI tools that relaunch themselves
(e.g. `@google/gemini-cli`) would have the binary path leak into
`process.argv` as a user argument.

When Node.js apps relaunch themselves they typically do:
```js
spawn(process.execPath, [process.argv[1], ...userArgs])
```

In standalone binaries `process.argv[1]` is the exe path (set by
#32990),
so the child process receives the exe path as its first CLI argument.
The standalone arg parser only skipped `argv[0]`, so the duplicate exe
path ended up in `Deno.args` / `process.argv`, causing yargs-based CLIs
to misinterpret it as a positional argument.

For example, running compiled `gemini` would show the binary path
pre-filled as the initial prompt, because yargs parsed
`/Users/x/.deno/bin/gemini` as a positional arg.

## Fix

In `cli/rt/binary.rs`, detect when the first CLI arg (after skipping
`argv[0]`) matches the current executable path and strip it. This
handles the standard Node.js relaunch pattern without affecting normal
usage.

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
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.

2 participants