google-gemini/gemini-cli

bug: TUI hangs indefinitely on "Initializing..." — IdeClient.getInstance() blocks BuiltinCommandLoader in bare terminal

Open

#21.477 aberto em 6 de mar. de 2026

Ver no GitHub
 (11 comments) (0 reactions) (1 assignee)TypeScript (13.657 forks)batch import
area/coreeffort/largehelp wantedkind/bugpriority/p1status/bot-triagedstatus/need-retestingstatus/possible-duplicatetype/bug

Métricas do repositório

Stars
 (103.992 stars)
Métricas de merge de PR
 (Mesclagem média 4d 11h) (62 fundiu PRs em 30d)

Description

Description

Gemini CLI v0.32.1 interactive TUI hangs forever on the "Initializing..." spinner when launched from a bare Linux terminal (not inside any IDE). Headless mode (gemini -p "hello") works perfectly.

Root Cause (Diagnosed)

The hang originates in BuiltinCommandLoader.loadCommands() which awaits ideCommand(). This calls IdeClient.getInstance()getIdeProcessInfo()getProcessInfo(pid) which runs ps -o ppid=,command= -p <pid> in a loop, traversing up the process tree looking for a parent IDE.

On certain Linux systems running from a bare terminal, this process traversal never completes — the execAsync('ps ...') call hangs on a specific PID in the ancestor chain.

Because BuiltinCommandLoader never resolves, Promise.allSettled() in CommandService.create() never settles, slashCommands is never set, and the TUI condition (!uiState.slashCommands || !uiState.isConfigInitialized) keeps rendering ConfigInitDisplay ("Initializing...") forever.

Evidence from instrumentation

Added fs.appendFileSync logging to each loader in CommandService.create():

[CMD] loader[0] McpPromptLoader DONE
[CMD] loader[2] FileCommandLoader DONE
# loader[1] BuiltinCommandLoader — NEVER completes

[BUILTIN] isNightly DONE: false
[BUILTIN] ideCommand START
# ideCommand — NEVER completes

config.initialize() completes in ~120ms. The issue is exclusively in the slash command loading phase.

Suggested Fix

Add a timeout to ideCommand() in BuiltinCommandLoader.loadCommands(), or make getIdeProcessInfo() non-blocking with an AbortSignal / timeout. When running from a bare terminal (no IDE detected within N seconds), it should fall back gracefully instead of blocking startup indefinitely.

Example:

// Instead of:
await ideCommand(),

// Use:
await Promise.race([
  ideCommand(),
  new Promise(resolve => setTimeout(() => resolve(noIdeFallbackCommand), 5000))
]),

Workaround

Replace await ideCommand(), in BuiltinCommandLoader.js with a static no-IDE object:

GEMINI_PATH=$(dirname $(readlink -f $(which gemini)))/../lib/node_modules/@google/gemini-cli
sed -i "s|await ideCommand(),|{ name: 'ide', description: 'Manage IDE integration (disabled)', kind: 'built-in', autoExecute: false, action: () => ({ type: 'message', messageType: 'info', content: 'IDE integration is not available.' }) },|" \
  "$GEMINI_PATH/dist/src/services/BuiltinCommandLoader.js"

Environment

  • OS: Ubuntu 24.04+ (Linux 6.17.0-14-generic, x86_64)
  • Gemini CLI: v0.32.1
  • Node.js: v24.14.0
  • Terminal: GNOME Terminal / bare terminal (NOT inside VS Code, Cursor, or any IDE)
  • Shell: bash

Steps to Reproduce

  1. Install Gemini CLI on Ubuntu Linux: npm install -g @google/gemini-cli
  2. Authenticate: gemini -p "hello" (works fine in headless)
  3. Launch interactive TUI from a bare terminal: gemini
  4. Observe: TUI shows logo, briefly flashes "Waiting for auth...", then stays on "Initializing..." forever
  5. Confirm headless works: gemini -p "hello" responds normally

Related Issues

  • #13986 (TUI stuck at Initializing — attributed to MCP, but may also be this bug)
  • #20433 (Initializing hang due to ripgrep — different root cause, same symptom)

Guia do colaborador