Skip to content

fix: use cross-spawn for Windows compatibility#57

Closed
Sundeepg98 wants to merge 1 commit into
jamubc:mainfrom
Sundeepg98:fix/windows-cross-spawn
Closed

fix: use cross-spawn for Windows compatibility#57
Sundeepg98 wants to merge 1 commit into
jamubc:mainfrom
Sundeepg98:fix/windows-cross-spawn

Conversation

@Sundeepg98

Copy link
Copy Markdown

Summary

  • Replace child_process.spawn with cross-spawn in commandExecutor.ts for Windows .cmd file resolution
  • Replace deprecated -p/--prompt flag with positional prompt argument (Gemini CLI v0.18+)
  • Remove now-unnecessary @-symbol quoting workaround

Problem

Issue 1: Windows spawn fails with ENOENT

On Windows, npm installs the Gemini CLI as gemini.cmd (a batch wrapper). Node's spawn() with shell: false cannot execute .cmd files — only cmd.exe can. This causes:

Error: Failed to spawn command: spawn gemini ENOENT

Issue 2: Deprecated -p flag conflicts with positional prompt

Gemini CLI v0.18+ deprecated the -p/--prompt flag. Using it causes:

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

Solution

Why cross-spawn instead of shell: true?

Several existing PRs (#27, #41, #43) fix the Windows issue by setting shell: true. While this works, it has drawbacks:

Approach .cmd resolution Arg escaping Security Dependency
shell: true Yes Manual quoting needed Shell injection surface None
cross-spawn Yes Automatic shell: false preserved 1 package

cross-spawn (40M+ weekly downloads, used by npm itself) is a drop-in replacement for spawn that:

  • Resolves .cmd/.bat files on Windows transparently
  • Properly escapes arguments across all platforms
  • Keeps shell: false, avoiding shell injection risks
  • Works identically to spawn on macOS/Linux

Changes

  1. commandExecutor.ts: Replace import { spawn } from "child_process"import spawn from "cross-spawn" (1 line)
  2. geminiExecutor.ts: Use positional prompt instead of -p flag, remove @-symbol quoting workaround
  3. constants.ts: Remove unused PROMPT: "-p" flag constant
  4. package.json: Add cross-spawn + @types/cross-spawn

Testing

Tested on Windows 11 with Gemini CLI v0.31.0 via Claude Code MCP integration. Verified:

  • ask-gemini returns correct responses
  • Prompts with spaces and special characters work correctly
  • No regressions on the brainstorm and ping tools

Fixes #30, #40, #28, #48. Closes #18.

🤖 Generated with Claude Code

… 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>
@gemini-code-assist

Copy link
Copy Markdown

Summary of Changes

Hello, 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 cross-spawn and adapting to recent Gemini CLI argument changes, it resolves critical issues related to command spawning and deprecated flags, ensuring a smoother and more reliable user experience without introducing shell injection risks.

Highlights

  • Windows Compatibility: Adopted cross-spawn to replace Node.js's native child_process.spawn for improved compatibility and .cmd file resolution on Windows, addressing ENOENT errors.
  • Gemini CLI Argument Handling: Updated the Gemini CLI command execution to use positional prompt arguments, deprecating the -p/--prompt flag as per Gemini CLI v0.18+ changes.
  • Code Simplification: Removed the no-longer-needed @-symbol quoting workaround, simplifying argument preparation for the Gemini CLI.

🧠 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
  • package-lock.json
    • Updated dependencies to include cross-spawn and its type definitions.
    • Removed nodemon and its associated transitive dependencies.
  • package.json
    • Added cross-spawn as a production dependency.
    • Added @types/cross-spawn as a development dependency.
  • src/constants.ts
    • Removed the PROMPT flag constant, reflecting the deprecation of the -p flag in the Gemini CLI.
  • src/utils/commandExecutor.ts
    • Replaced child_process.spawn with cross-spawn for command execution.
    • Added non-null assertion operators to stdout and stderr event listeners.
  • src/utils/geminiExecutor.ts
    • Modified the command argument construction to use positional prompts for the Gemini CLI.
    • Removed the logic for quoting @-symbols in prompts, as it is no longer required.
Activity
  • Sundeepg98 created this pull request to address several reported issues related to Windows compatibility and deprecated CLI flags.
  • The author provided a detailed summary outlining the problem, solution, and testing performed.
Using Gemini Code Assist

The 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 /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

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 .gemini/ folder in the base of the repository. Detailed instructions can be found here.

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

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

security-medium medium

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.

Suggested change
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);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

security-medium medium

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.

Suggested change
fallbackArgs.push(prompt_processed);
fallbackArgs.push("--", prompt_processed);

let lastReportedLength = 0;

childProcess.stdout.on("data", (data) => {
childProcess.stdout!.on("data", (data) => {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

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.

OhkuboSGMS added a commit to OhkuboSGMS/gemini-mcp-tool that referenced this pull request Mar 3, 2026
- Update One-Line Setup to use this fork
- Simplify Configuration section
- Add note about PR jamubc#57 (cross-spawn fix)
@jamubc

jamubc commented Mar 19, 2026

Copy link
Copy Markdown
Owner

Looking into this, Thanks.

@jamubc

jamubc commented May 30, 2026

Copy link
Copy Markdown
Owner

Thanks for this. The project went with stdin + arg quote-hardening (#76/#77) rather than a cross-spawn dependency. Closing as superseded — appreciated.

@jamubc jamubc closed this May 30, 2026
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.

Gemini CLI MCP Tool Integration Issue - Command Spawn Error (ENOENT) [Windows] Error: spawn gemini ENOENT when using ask-gemini tool

2 participants