fix(cli)!: Default to interactive mode for positional arguments (#16329)

Co-authored-by: Allen Hutchison <adh@google.com>
This commit is contained in:
Ishaan Gupta
2026-01-23 05:08:53 +05:30
committed by GitHub
parent a060e6149a
commit beacc4f6fd
3 changed files with 53 additions and 24 deletions
+15 -10
View File
@@ -84,6 +84,7 @@ export interface CliArgs {
outputFormat: string | undefined;
fakeResponses: string | undefined;
recordResponses: string | undefined;
startupMessages?: string[];
rawOutput: boolean | undefined;
acceptRawOutputRisk: boolean | undefined;
isCommand: boolean | undefined;
@@ -93,11 +94,12 @@ export async function parseArguments(
settings: MergedSettings,
): Promise<CliArgs> {
const rawArgv = hideBin(process.argv);
const startupMessages: string[] = [];
const yargsInstance = yargs(rawArgv)
.locale('en')
.scriptName('gemini')
.usage(
'Usage: gemini [options] [command]\n\nGemini CLI - Launch an interactive CLI, use -p/--prompt for non-interactive mode',
'Usage: gemini [options] [command]\n\nGemini CLI - Defaults to interactive mode. Use -p/--prompt for non-interactive (headless) mode.',
)
.option('debug', {
alias: 'd',
@@ -109,7 +111,7 @@ export async function parseArguments(
yargsInstance
.positional('query', {
description:
'Positional prompt. Defaults to one-shot; use -i/--prompt-interactive for interactive.',
'Initial prompt. Runs in interactive mode by default; use -p/--prompt for non-interactive.',
})
.option('model', {
alias: 'm',
@@ -121,7 +123,8 @@ export async function parseArguments(
alias: 'p',
type: 'string',
nargs: 1,
description: 'Prompt. Appended to input on stdin (if any).',
description:
'Run in non-interactive (headless) mode with the given prompt. Appended to input on stdin (if any).',
})
.option('prompt-interactive', {
alias: 'i',
@@ -342,11 +345,12 @@ export async function parseArguments(
? queryArg.join(' ')
: queryArg;
// Route positional args: explicit -i flag -> interactive; else -> one-shot (even for @commands)
// -p/--prompt forces non-interactive mode; positional args default to interactive in TTY
if (q && !result['prompt']) {
const hasExplicitInteractive =
result['promptInteractive'] === '' || !!result['promptInteractive'];
if (hasExplicitInteractive) {
if (process.stdin.isTTY) {
startupMessages.push(
'Positional arguments now default to interactive mode. To run in non-interactive mode, use the --prompt (-p) flag.',
);
result['promptInteractive'] = q;
} else {
result['prompt'] = q;
@@ -355,6 +359,7 @@ export async function parseArguments(
// Keep CliArgs.query as a string for downstream typing
(result as Record<string, unknown>)['query'] = q || undefined;
(result as Record<string, unknown>)['startupMessages'] = startupMessages;
// The import format is now only controlled by settings.memoryImportFormat
// We no longer accept it as a CLI argument
@@ -573,12 +578,12 @@ export async function loadCliConfig(
throw err;
}
// Interactive mode: explicit -i flag or (TTY + no args + no -p flag)
const hasQuery = !!argv.query;
// -p/--prompt forces non-interactive (headless) mode
// -i/--prompt-interactive forces interactive mode with an initial prompt
const interactive =
!!argv.promptInteractive ||
!!argv.experimentalAcp ||
(process.stdin.isTTY && !hasQuery && !argv.prompt && !argv.isCommand);
(process.stdin.isTTY && !argv.query && !argv.prompt && !argv.isCommand);
const allowedTools = argv.allowedTools || settings.tools?.allowed || [];
const allowedToolsSet = new Set(allowedTools);