Skip to content

Conversation

maruthi-raj
Copy link

Fix: Prevent stdin consumption when explicit prompts provided via CLI args

Only read stdin when no explicit prompt provided via CLI arguments.

TLDR

Fixes the "banishing trailing input" issue where using -p option in shell loops caused subsequent input to disappear. The CLI now only reads from stdin when no explicit prompt is provided via command-line arguments (-p, -i, or positional args), preventing it from consuming piped input that should be available to subsequent commands in loops.

Dive Deeper

Problem: When running Gemini CLI with the -p option inside shell loops that process piped input, the CLI was consuming stdin even though a prompt was explicitly provided via command-line arguments. This caused trailing input to "disappear" because the CLI consumed it unnecessarily.

Example of the bug:

$ echo -e "1\n2" | while read n; do echo "n=$n"; gemini -p "Hi." ; done
n=1
Loaded cached credentials.
Hello! How can I help you today?
# Missing: n=2 (because gemini consumed the remaining stdin)

Solution: Added logic to check for explicit prompts before attempting to read from stdin:

CLI now only reads stdin when !process.stdin.isTTY AND no explicit prompt is provided
Covers both main execution path and sandbox/non-interactive paths
Preserves normal piped input functionality when no CLI args are provided

## Reviewer Test Plan

To validate this fix works:
1. Test the original bug scenario:
echo -e "1\n2\n3" | while read n; do echo "n=$n"; gemini -p "Say hi briefly"; done
Expected: Should see n=1, n=2, n=3 with gemini responses between them
2. Test normal piped input still works:
echo "What is 2+2?" | gemini
Expected: Should process the piped question normally
3. Test other explicit prompt methods:
echo -e "1\n2" | while read n; do echo "n=$n"; gemini "Say hi to $n"; done
Expected: Should work with positional arguments too
4. Test interactive mode unaffected:
gemini -i
Expected: Should start interactive mode normally

## Testing Matrix
npm run ||| ❓
npx ||| ❓
Docker ||| ❓
Podman || - | -
Seatbelt || - | -



## Linked issues / bugs
Fixes #10556 

Only read stdin when no explicit prompt provided via CLI arguments.
@maruthi-raj maruthi-raj requested a review from a team as a code owner October 6, 2025 18:14
Copy link

google-cla bot commented Oct 6, 2025

Thanks for your pull request! It looks like this may be your first contribution to a Google open source project. Before we can look at your pull request, you'll need to sign a Contributor License Agreement (CLA).

View this failed invocation of the CLA check for more information.

For the most up to date status, view the checks section at the bottom of the pull request.

Copy link
Contributor

Summary of Changes

Hello @maruthi-raj, 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 resolves a critical bug in the gemini command-line interface where it would inadvertently consume piped stdin even when a user had supplied a prompt directly via command-line flags or positional arguments. This behavior caused issues in shell scripting, particularly within loops, where subsequent commands would find their expected stdin to be empty. The fix ensures that stdin is only read when truly necessary, preserving the flow of data in piped operations.

Highlights

  • Problem Addressed: Fixed an issue where the gemini CLI would consume stdin even when an explicit prompt was provided via command-line arguments (e.g., -p, -i, or positional args), leading to "banished trailing input" in shell loops.
  • Solution Implemented: Modified the CLI's main function to conditionally read from stdin. It now only reads stdin if process.stdin.isTTY is false (meaning input is piped) AND no explicit prompt has been provided through CLI arguments.
  • Test Coverage: Added a comprehensive new test suite (stdin handling for banishing trailing input) to gemini.test.tsx to validate the correct behavior of stdin consumption under various conditions (with/without explicit prompts, TTY vs. piped input).
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.

Copy link
Contributor

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

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 correctly addresses an issue where the CLI would consume stdin when used with prompt flags inside a shell loop. The approach of checking for an explicit prompt before reading from stdin is sound. However, the implementation has a subtle bug: it doesn't correctly handle cases where an empty prompt is provided (e.g., -p ""). In these scenarios, the CLI incorrectly determines that no prompt was given and consumes stdin. I've provided two high-severity comments with suggestions to fix this logic in both places it appears.

Comment on lines 300 to 304
const hasExplicitPrompt = !!(
argv.prompt ||
argv.promptInteractive ||
argv.query
);
Copy link
Contributor

Choose a reason for hiding this comment

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

high

This check for an explicit prompt is not quite correct. If a user provides an empty prompt (e.g., gemini -p ""), argv.prompt will be "", which is falsy. This will cause hasExplicitPrompt to be false, and the CLI will incorrectly attempt to read from stdin. The check should verify the argument was provided, regardless of its value.

Additionally, checking argv.query is redundant because parseArguments ensures that if argv.query is present, either argv.prompt or argv.promptInteractive will also be set.

      const hasExplicitPrompt = 
        argv.prompt !== undefined || argv.promptInteractive !== undefined;

Comment on lines 431 to 436
if (!process.stdin.isTTY && !input) {
const stdinData = await readStdin();
if (stdinData) {
input = `${stdinData}\n\n${input}`;
input = stdinData;
}
}
Copy link
Contributor

Choose a reason for hiding this comment

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

high

This check using !input has a bug. If a user provides an empty prompt like gemini -p "", config.getQuestion() will return "", making !input true and causing the CLI to incorrectly consume stdin. To fix this, we should explicitly check argv for the presence of prompt-related arguments, similar to the logic in the sandboxing path.

    const hasExplicitPrompt =
      argv.prompt !== undefined || argv.promptInteractive !== undefined;
    if (!process.stdin.isTTY && !hasExplicitPrompt) {
      const stdinData = await readStdin();
      if (stdinData) {
        input = stdinData;
      }
    }

@maruthi-raj maruthi-raj changed the title fix: banish trailing input when using -p in loops (#10556) fix(cli): Banish trailing input when using -p in loops (#10556) Oct 7, 2025
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.

1 participant