fix: use cross-spawn for Windows compatibility#57
Conversation
… flag Replace `child_process.spawn` with `cross-spawn` in commandExecutor.ts. On Windows, npm installs Gemini CLI as `gemini.cmd` which `spawn()` with `shell: false` cannot execute, causing ENOENT errors. `cross-spawn` is a drop-in replacement (40M+ weekly downloads, used by npm itself) that transparently handles .cmd resolution and argument escaping on Windows while keeping `shell: false` for security. Also replace the deprecated `-p`/`--prompt` flag with positional prompt argument, fixing the "Cannot use both a positional prompt and --prompt flag" error in Gemini CLI v0.18+. Fixes jamubc#30, jamubc#40, jamubc#28, jamubc#48 Closes jamubc#18 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Summary of ChangesHello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed! This pull request significantly enhances the robustness and cross-platform compatibility of command execution, particularly for Windows users. By switching to Highlights
🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console. Changelog
Activity
Using Gemini Code AssistThe full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips. Invoking Gemini You can request assistance from Gemini at any point by creating a comment using either
Customization To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a Limitations & Feedback Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here. You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension. Footnotes
|
There was a problem hiding this comment.
Code Review
This pull request effectively addresses Windows compatibility issues by replacing child_process.spawn with cross-spawn and modernizes CLI argument handling by adopting positional prompts and removing the deprecated -p flag. However, the transition to positional arguments introduced a potential argument injection vulnerability, as user-controlled prompts without the -- separator could allow attackers to inject command-line flags and manipulate the gemini CLI tool. Additionally, a medium-severity suggestion in src/utils/commandExecutor.ts recommends improving type safety by using a type guard instead of a non-null assertion for better code resilience.
| args.push(CLI.FLAGS.PROMPT, finalPrompt); | ||
|
|
||
| // Use positional prompt instead of deprecated -p flag (removed in Gemini CLI v0.18+) | ||
| args.push(prompt_processed); |
There was a problem hiding this comment.
The executeGeminiCLI function constructs a command-line argument list for the gemini CLI tool. It appends prompt_processed (which is derived from user-supplied input) as a positional argument. If a user provides a prompt that starts with a hyphen (e.g., -h, --version, or more dangerous flags if supported by the CLI), the gemini CLI may interpret it as a command-line flag rather than the intended prompt text. This can lead to unintended behavior, denial of service (by triggering help or version output), or potentially more severe impacts depending on the available flags in the gemini CLI.
To remediate this, use the -- separator to explicitly signal the end of command-line flags before appending the positional prompt argument. This ensures that the prompt is always treated as a positional argument, even if it starts with a hyphen.
| args.push(prompt_processed); | |
| args.push("--", prompt_processed); |
| fallbackArgs.push(CLI.FLAGS.PROMPT, fallbackPrompt); | ||
|
|
||
| // Use positional prompt instead of deprecated -p flag | ||
| fallbackArgs.push(prompt_processed); |
There was a problem hiding this comment.
Similar to the issue on line 95, the fallback execution path also appends the user-controlled prompt_processed as a positional argument without the -- separator, making it vulnerable to argument injection.
| fallbackArgs.push(prompt_processed); | |
| fallbackArgs.push("--", prompt_processed); |
| let lastReportedLength = 0; | ||
|
|
||
| childProcess.stdout.on("data", (data) => { | ||
| childProcess.stdout!.on("data", (data) => { |
There was a problem hiding this comment.
Using the non-null assertion operator (!) is acceptable here since stdio is configured to pipe stdout. However, for increased type safety and to prevent potential runtime errors if spawn options change in the future, consider using a type guard like if (childProcess.stdout) { ... }. This same feedback applies to childProcess.stderr on line 37.
- Update One-Line Setup to use this fork - Simplify Configuration section - Add note about PR jamubc#57 (cross-spawn fix)
|
Looking into this, Thanks. |
Summary
child_process.spawnwithcross-spawnincommandExecutor.tsfor Windows.cmdfile resolution-p/--promptflag with positional prompt argument (Gemini CLI v0.18+)@-symbol quoting workaroundProblem
Issue 1: Windows
spawnfails with ENOENTOn Windows, npm installs the Gemini CLI as
gemini.cmd(a batch wrapper). Node'sspawn()withshell: falsecannot execute.cmdfiles — onlycmd.execan. This causes:Issue 2: Deprecated
-pflag conflicts with positional promptGemini CLI v0.18+ deprecated the
-p/--promptflag. Using it causes:Solution
Why
cross-spawninstead ofshell: true?Several existing PRs (#27, #41, #43) fix the Windows issue by setting
shell: true. While this works, it has drawbacks:.cmdresolutionshell: truecross-spawnshell: falsepreservedcross-spawn(40M+ weekly downloads, used by npm itself) is a drop-in replacement forspawnthat:.cmd/.batfiles on Windows transparentlyshell: false, avoiding shell injection risksspawnon macOS/LinuxChanges
commandExecutor.ts: Replaceimport { spawn } from "child_process"→import spawn from "cross-spawn"(1 line)geminiExecutor.ts: Use positional prompt instead of-pflag, remove@-symbol quoting workaroundconstants.ts: Remove unusedPROMPT: "-p"flag constantpackage.json: Addcross-spawn+@types/cross-spawnTesting
Tested on Windows 11 with Gemini CLI v0.31.0 via Claude Code MCP integration. Verified:
ask-geminireturns correct responsesbrainstormandpingtoolsFixes #30, #40, #28, #48. Closes #18.
🤖 Generated with Claude Code