google-gemini/gemini-cli

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

Open

#21,477 opened on Mar 6, 2026

View on 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

Repository metrics

Stars
 (103,992 stars)
PR merge metrics
 (Avg merge 4d 11h) (62 merged PRs in 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)

Contributor guide