fix(compile): strip duplicate exe path from argv when standalone binary relaunches#33016
Merged
bartlomieju merged 2 commits intomainfrom Mar 26, 2026
Merged
Conversation
…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
commented
Mar 26, 2026
Member
Author
bartlomieju
left a comment
There was a problem hiding this comment.
The approach is correct — this is essentially what Node.js SEA does to handle the relaunch pattern. Given that #32990 set process.argv[1] = execPath, this is the natural place to strip the duplicate.
Minor style suggestion: the first boolean flag can be simplified by just handling the first element separately:
let current_exe = std::env::current_exe().ok();
let mut args_iter = cli_args.into_iter();
args_iter.next(); // skip argv[0]
// Node.js apps relaunch with spawn(process.execPath, [process.argv[1], ...args]).
// In standalone mode process.argv[1] === execPath (#32990), so the first arg
// after argv[0] is a duplicate of the exe path. Strip it.
if let Some(first) = args_iter.next() {
let is_exe_dup = current_exe
.as_ref()
.is_some_and(|exe| Path::new(&first) == exe.as_path());
if !is_exe_dup {
metadata.argv.push(first.into_string().unwrap());
}
}
for arg in args_iter {
metadata.argv.push(arg.into_string().unwrap());
}One edge case worth noting in a comment: if a user intentionally passes the exe path as the first argument (./myapp ./myapp --foo), it would be silently stripped. In practice this doesn't happen with standalone binaries, but worth acknowledging the tradeoff.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
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.
Summary
Fixes an issue where compiled npm CLI tools that relaunch themselves
(e.g.
@google/gemini-cli) would have the binary path leak intoprocess.argvas a user argument.When Node.js apps relaunch themselves they typically do:
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 exepath ended up in
Deno.args/process.argv, causing yargs-based CLIsto misinterpret it as a positional argument.
For example, running compiled
geminiwould show the binary pathpre-filled as the initial prompt, because yargs parsed
/Users/x/.deno/bin/geminias a positional arg.Fix
In
cli/rt/binary.rs, detect when the first CLI arg (after skippingargv[0]) matches the current executable path and strip it. Thishandles the standard Node.js relaunch pattern without affecting normal
usage.
Test plan
standalone_spawn_selfspec test to verify user argspass through correctly and exe path doesn't leak
standalone_process_argvtest still passes@google/gemini-cli🤖 Generated with Claude Code