Jesse A. Green / notebook

Gemini CLI Administration & Architecture Guide

Generated May 2026 from google-gemini/gemini-cli at a809bc7

AI-generated documentation. The library is checked by sampling (three repositories so far); this guide was not individually reviewed. Verify against the project before relying on it.

Gemini CLI is a TypeScript monorepo that implements an AI-powered coding agent for the terminal. It connects to the Gemini family of models via the Google GenAI SDK, wraps model interactions in a tool-calling agent loop, and presents results through a React/Ink terminal UI. The project spans seven packages — a CLI frontend, a core engine, an SDK for programmatic use, an A2A protocol server, a devtools inspector, a VS Code companion extension, and a shared test utilities library.

This guide covers the architecture, configuration internals, deployment, security model, extension system, and operational concerns for administrators, platform engineers, and contributors.


Architecture Overview

Monorepo Structure

google-gemini/gemini-cli/
├── packages/
│   ├── cli/           # Terminal UI (React/Ink), slash commands, config
│   ├── core/          # Agent loop, model client, tools, hooks, sandbox
│   ├── sdk/           # Programmatic agent API (@google/gemini-cli-sdk)
│   ├── a2a-server/    # Agent-to-Agent protocol server (Express + SSE)
│   ├── devtools/      # Chrome DevTools-style inspector
│   ├── vscode-ide-companion/  # VS Code extension for IDE integration
│   └── test-utils/    # Shared test harness, fixtures, mock MCP servers
├── docs/              # User-facing documentation (markdown)
├── schemas/           # JSON Schema for settings.json
├── scripts/           # Build, release, and utility scripts
├── evals/             # Component evaluation tests
├── integration-tests/ # Cross-package integration tests
├── memory-tests/      # Memory leak and regression tests
├── perf-tests/        # Performance benchmarks
└── sea/               # Single Executable Application packaging

Package Dependency Graph

cli → core
sdk → core
a2a-server → core
devtools → core (events)
vscode-ide-companion → (standalone)
test-utils → core

The core package is the foundation. It owns the agent loop, model communication, tool registry, hook system, sandbox management, and configuration. All other packages depend on it.

Runtime Architecture

User Input
    │
    ▼
┌─────────────────────────────────┐
│  CLI (packages/cli)              │
│  React/Ink TUI                   │
│  ├── CommandService              │
│  ├── SlashCommandResolver        │
│  ├── ExtensionManager            │
│  └── LoadedSettings              │
└──────────────┬──────────────────┘
               │
               ▼
┌─────────────────────────────────┐
│  Core (packages/core)            │
│  ├── Config                      │
│  ├── GeminiChat (agent loop)     │
│  │   ├── GeminiClient            │
│  │   ├── BaseLlmClient           │
│  │   └── ContentGenerator        │
│  ├── Scheduler                   │
│  │   ├── Policy Engine           │
│  │   ├── Confirmation Bus        │
│  │   └── Tool Modifier           │
│  ├── HookSystem                  │
│  ├── Tool Registry               │
│  ├── Sandbox Manager             │
│  └── Services                    │
│       ├── ShellExecutionService  │
│       ├── FileDiscoveryService   │
│       ├── GitService             │
│       ├── ModelConfigService     │
│       └── ChatRecordingService   │
└──────────────┬──────────────────┘
               │
               ▼
┌─────────────────────────────────┐
│  Google GenAI SDK                │
│  Gemini API / Vertex AI          │
└─────────────────────────────────┘

Key Architectural Decisions

  1. React/Ink for TUI: The terminal UI uses React with the Ink renderer, enabling component-based rendering with state management, effects, and context
  2. Event-driven tool execution: Tools execute through a Scheduler that manages confirmation, policy checks, hooks, and state transitions via an EventEmitter-based message bus
  3. Layered configuration: Four config scopes (System, SystemDefaults, User, Workspace) merge via deep-merge with more-specific scopes winning
  4. Model routing via strategies: A CompositeStrategy chains multiple routing strategies (ApprovalMode, Classifier, Override, Default, Fallback) to select the optimal model per request
  5. File-based session persistence: Conversations are stored as JSON files in the project's temp directory, enabling resume, replay, and recording

Component Inventory

packages/core

The engine. Contains all model communication, tool execution, and agent orchestration logic.

Component File Purpose
Config config/config.ts Central configuration object. Holds session, model, sandbox, auth, and path settings
GeminiChat core/geminiChat.ts Main agent loop. Orchestrates model calls, tool execution, and conversation flow
GeminiClient core/client.ts Manages chat sessions with the Gemini API. Handles initialization, history, streaming
BaseLlmClient core/baseLlmClient.ts Low-level LLM communication. Handles retries, content generation, JSON generation, embeddings
ContentGenerator core/contentGenerator.ts Creates the GenAI client with auth, proxy, and base URL configuration
Turn core/turn.ts Represents a single model turn with content parts, tool calls, and metadata
Scheduler scheduler/scheduler.ts Manages parallel tool execution, confirmation flow, and state transitions
SchedulerStateManager scheduler/state-manager.ts Tracks tool call states through their lifecycle
HookSystem hooks/hookSystem.ts Fires lifecycle events and aggregates hook results
HookRegistry hooks/hookRegistry.ts Stores and retrieves hook configurations
HookRunner hooks/hookRunner.ts Executes hook commands as child processes
HookAggregator hooks/hookAggregator.ts Merges results from multiple hooks for the same event
Logger core/logger.ts Manages conversation logs, checkpoints, and session persistence
ModelConfigService services/modelConfigService.ts Resolves model aliases, applies config overrides, manages model definitions
ShellExecutionService services/shellExecutionService.ts Executes shell commands with sandbox wrapping and output capture
FileDiscoveryService services/fileDiscoveryService.ts Finds files using ripgrep for fast codebase search
GitService services/gitService.ts Git operations: status, diff, log, commit
WorktreeService services/worktreeService.ts Manages git worktrees for isolated execution
ChatRecordingService services/chatRecordingService.ts Records and replays conversations for testing
LoopDetectionService services/loopDetectionService.ts Detects and breaks infinite agent loops
ExecutionLifecycleService services/executionLifecycleService.ts Manages execution phases: initialize, run, finalize
SandboxedFileSystemService services/sandboxedFileSystemService.ts File operations with sandbox path validation
LocalSandboxManager services/sandboxManager.ts Manages Docker/Podman sandbox containers
NoopSandboxManager services/sandboxManager.ts Pass-through sandbox for unsandboxed execution
FolderTrustDiscoveryService services/FolderTrustDiscoveryService.ts Scans workspace for configurations before trust is granted
PolicyEngine policy/policy-engine.ts Evaluates tool calls against policy rules
CoreEventEmitter utils/events.ts Typed event bus for internal communication
SimpleExtensionLoader utils/extensionLoader.ts Loads and initializes extensions from manifests
SchemaValidator utils/schemaValidator.ts JSON Schema validation for settings and configs
CacheService utils/cache.ts TTL-based cache with Map or WeakMap storage backends
FileExclusions utils/ignorePatterns.ts Manages .gitignore and custom file exclusion patterns
WorkspaceContext utils/workspaceContext.ts Resolves and validates workspace directories

Note

The Config class at packages/core/src/config/config.ts is the single most important class in the system. It initializes from ConfigParameters, manages auth, model selection, sandbox configuration, tool registry, MCP servers, hook system, and policy engine. Nearly every service receives a Config instance.

packages/cli

The terminal frontend. Owns the React/Ink UI, slash commands, settings loading, and extension management.

Component File Purpose
App.tsx ui/App.tsx Root React component
LoadedSettings config/settings.ts Loads and merges settings across all scopes
ExtensionManager config/extension-manager.ts Installs, loads, validates, and manages extensions
ExtensionRegistryClient config/extensionRegistryClient.ts Queries the extension registry
LoadedTrustedFolders config/trustedFolders.ts Manages folder trust decisions
CommandService services/CommandService.ts Registers and dispatches slash commands
SlashCommandResolver services/SlashCommandResolver.ts Resolves slash command names to handlers, with conflict detection
BuiltinCommandLoader services/BuiltinCommandLoader.ts Loads built-in slash commands
FileCommandLoader services/FileCommandLoader.ts Loads TOML-based custom commands from .gemini/commands/
SkillCommandLoader services/SkillCommandLoader.ts Loads skill-based commands
McpPromptLoader services/McpPromptLoader.ts Loads prompts from MCP servers as slash commands
ActivityLogger utils/activityLogger.ts Logs session activity events
SessionSelector utils/sessionUtils.ts Lists, selects, and deletes sessions
PersistentState utils/persistentState.ts Manages persistent UI state across sessions

Important

The ExtensionManager at packages/cli/src/config/extension-manager.ts is a critical class. It extends ExtensionLoader, handles installation from npm/local paths, validates manifests, and manages enable/disable state. It enforces that extensions are loaded exactly once per session to prevent resource leaks.

packages/sdk

Programmatic API for building custom agents on top of the Gemini CLI engine.

Component File Purpose
GeminiCliAgent agent.ts Creates and resumes agent sessions
GeminiCliSession session.ts Manages a single conversation session with streaming
SdkTool tool.ts Base class for custom tools
SdkToolInvocation tool.ts Represents a single tool invocation with parameters
ModelVisibleError tool.ts Error class for errors the model should see
SdkAgentFilesystem fs.ts Sandbox-aware file system operations
SdkAgentShell shell.ts Shell command execution for SDK agents

packages/a2a-server

Agent-to-Agent protocol server. Enables Gemini CLI to act as a backend agent accessible via HTTP/SSE.

Component File Purpose
app.ts http/app.ts Express app with A2A routes
server.ts http/server.ts HTTP server lifecycle
CommandRegistry commands/command-registry.ts A2A command registration
InitCommand commands/init.ts Initializes agent context
MemoryCommand commands/memory.ts Memory operations (show, add, refresh, list)
RestoreCommand commands/restore.ts Checkpoint restore
ExtensionsCommand commands/extensions.ts Extension management via A2A

Events are streamed to clients via Server-Sent Events using the CoderAgentEvent enum:

  • TextContentEvent: Text output from the model
  • ToolCallConfirmationEvent: Tool requiring approval
  • ToolCallUpdateEvent: Tool execution status
  • StateChangeEvent: Task state transitions
  • ThoughtEvent: Model thinking/reasoning
  • CitationEvent: Source citations

packages/devtools

Chrome DevTools-style inspector for debugging Gemini CLI sessions.

Component File Purpose
DevTools src/index.ts EventEmitter-based devtools server
App.tsx client/src/App.tsx React client for the inspector UI

packages/vscode-ide-companion

VS Code extension that bridges the IDE with Gemini CLI.

Component File Purpose
IDEServer src/ide-server.ts Local HTTP server for MCP transport
DiffManager src/diff-manager.ts Manages file diffs for review
OpenFilesManager src/open-files-manager.ts Tracks open files in the editor

The IDE server exposes MCP endpoints (POST /mcp, GET /mcp) with CORS protection that only allows connections from localhost/127.0.0.1.


System Requirements

Runtime Requirements

Requirement Version Notes
Node.js >= 20.0.0 Required. Checked at startup
npm >= 10 Ships with Node 20
Git Any recent Required for worktrees, checkpointing, git tools
Docker or Podman Optional Required for container-based sandboxing

Build Requirements

Tool Version Notes
Node.js >= 20 Monorepo uses npm workspaces
TypeScript 5.x Strict mode enabled
Vitest Latest Test runner
React 18+ For Ink-based TUI

Platform Support

Platform Sandbox Options
macOS Docker, Podman, sandbox-exec (seatbelt profiles)
Linux Docker, Podman
Windows Docker, native Windows sandbox

Configuration Reference

Settings Schema

The complete settings schema is defined at schemas/settings.schema.json. Below is the authoritative reference for all configuration categories.

Tip

Reference the JSON schema URL in your settings file for IDE autocompletion: "$schema": "https://raw.githubusercontent.com/google-gemini/gemini-cli/main/schemas/settings.schema.json"

Settings Scope Hierarchy

System Settings (GEMINI_CLI_SYSTEM_SETTINGS_PATH)
    ↓ overrides
System Defaults (GEMINI_CLI_SYSTEM_DEFAULTS_PATH)
    ↓ overrides
User Settings (~/.gemini/settings.json)
    ↓ overrides
Workspace Settings (.gemini/settings.json)

Warning

Admin policy paths (adminPolicyPaths) set at the System scope cannot be overridden by workspace settings. This is the mechanism for enforcing organization-wide security policies.

General Settings

Key Type Default Description
general.vimMode boolean false Enable Vim keybindings
general.preferredEditor string - Editor for /editor command
general.defaultApprovalMode enum "default" default, auto_edit, plan
general.devtools boolean false Enable DevTools inspector
general.enableAutoUpdate boolean true Auto-update checks
general.enableAutoUpdateNotification boolean true Update notifications
general.enableNotifications boolean false Terminal notifications
general.notificationMethod enum "auto" auto, osc9, osc777, bell
general.checkpointing.enabled boolean false Git checkpoint snapshots
general.plan.enabled boolean true Enable Plan Mode
general.plan.directory string - Plan artifacts directory
general.plan.modelRouting boolean true Auto Pro/Flash switching
general.retryFetchErrors boolean true Retry on fetch failures
general.maxAttempts number 10 Max model request retries (cap: 10)
general.topicUpdateNarration boolean true Structured progress reporting
general.debugKeystrokeLogging boolean false Log keystrokes
general.sessionRetention.enabled boolean true Auto session cleanup
general.sessionRetention.maxAge string "30d" Max session age
general.sessionRetention.maxCount number - Max sessions to keep
general.sessionRetention.minRetention string "1d" Minimum retention

Model Settings

Key Type Default Description
model.name string - Model name override
model.maxSessionTurns number -1 Max turns per session (-1 = unlimited)
model.compressionThreshold number 0.5 Context compression trigger (0.0-1.0)
model.disableLoopDetection boolean false Disable loop detection
model.skipNextSpeakerCheck boolean true Skip speaker check
model.summarizeToolOutput object - Per-tool output summarization config

Model Configuration System

The modelConfigs setting controls model aliases, overrides, definitions, ID resolutions, and fallback chains.

Key model aliases:

Alias Base Model Purpose
chat-base - Base chat config (temperature: 1, topP: 0.95, thinking enabled)
chat-base-2.5 chat-base Gemini 2.5 thinking budget: 8192
chat-base-3 chat-base Gemini 3 thinking level: HIGH
classifier gemini-2.5-flash-lite Task complexity classification
prompt-completion gemini-2.5-flash-lite Prompt autocomplete
web-search gemini-3-flash-preview Google Search integration
web-fetch gemini-3-flash-preview URL content fetching
loop-detection gemini-3-flash-preview Infinite loop detection
summarizer-default gemini-2.5-flash-lite Context summarization

Model families and tiers:

Model ID Tier Family Preview Thinking
gemini-3.1-pro-preview Pro gemini-3 Yes Yes
gemini-3-pro-preview Pro gemini-3 Yes Yes
gemini-3-flash-preview Flash gemini-3 Yes No
gemini-3.1-flash-lite-preview Flash-Lite gemini-3 Yes No
gemini-2.5-pro Pro gemini-2.5 No No
gemini-2.5-flash Flash gemini-2.5 No No
gemini-2.5-flash-lite Flash-Lite gemini-2.5 No No

Fallback chains:

The system defines three fallback chains (preview, default, lite) that determine retry behavior when a model is unavailable:

  • Preview chain: gemini-3-pro-preview → gemini-3-flash-preview
  • Default chain: gemini-2.5-pro → gemini-2.5-flash
  • Lite chain: gemini-2.5-flash-lite → gemini-2.5-flash → gemini-2.5-pro

UI Settings

Key Type Default Description
ui.theme string - UI theme name
ui.autoThemeSwitching boolean true Auto light/dark switching
ui.terminalBackgroundPollingInterval number 60 Background color poll interval (seconds)
ui.customThemes object {} Custom theme definitions
ui.hideBanner boolean false Hide startup banner
ui.hideFooter boolean false Hide status footer
ui.hideContextSummary boolean false Hide context info above input
ui.hideWindowTitle boolean false Hide window title
ui.showLineNumbers boolean true Line numbers in chat
ui.showCitations boolean false Show model citations
ui.showModelInfoInChat boolean false Show model name per turn
ui.showUserIdentity boolean true Show signed-in user
ui.showMemoryUsage boolean false Display memory stats
ui.showShortcutsHint boolean true Show "? for shortcuts"
ui.compactToolOutput boolean true Compact file/directory output
ui.dynamicWindowTitle boolean true Status icons in title
ui.showStatusInTitle boolean false Thoughts in title
ui.inlineThinkingMode enum "off" off or full
ui.useAlternateBuffer boolean false Alternate screen buffer
ui.incrementalRendering boolean true Reduce flicker (needs alt buffer)
ui.useBackgroundColor boolean true Background colors
ui.renderProcess boolean true Ink render process
ui.terminalBuffer boolean false New terminal buffer architecture
ui.showSpinner boolean true Operation spinner
ui.loadingPhrases enum "off" tips, witty, all, off
ui.errorVerbosity enum "low" low or full
ui.escapePastedAtSymbols boolean false Escape pasted @ symbols
ui.hideTips boolean false Hide tips
ui.showCompatibilityWarnings boolean true Terminal warnings
ui.showHomeDirectoryWarning boolean true Home dir warning
ui.collapseDrawerDuringApproval boolean true Collapse drawer on approval
ui.footer.items string[] - Footer item IDs
ui.footer.showLabels boolean true Footer labels
ui.footer.hideCWD boolean false Hide working directory
ui.footer.hideSandboxStatus boolean false Hide sandbox status
ui.footer.hideModelInfo boolean false Hide model info
ui.footer.hideContextPercentage boolean true Hide context %
ui.accessibility.screenReader boolean false Screen reader mode

Output Settings

Key Type Default Description
output.format enum "text" text or json

Privacy Settings

Key Type Default Description
privacy.usageStatisticsEnabled boolean true Usage statistics collection

Billing Settings

Key Type Default Description
billing.overageStrategy enum "ask" ask, always, never

IDE Settings

Key Type Default Description
ide.enabled boolean false Enable IDE integration
ide.hasSeenNudge boolean false IDE nudge shown

Security Settings

Key Type Default Description
security.auth.selectedType string - Current auth method
security.folderTrust.enabled boolean true Folder trust system

Tools Settings

Key Type Default Description
tools.allowed string[] - Auto-approved tool names
tools.sandbox boolean true Enable tool sandboxing

Advanced Settings

Key Type Default Description
policyPaths string[] [] Additional policy file paths
adminPolicyPaths string[] [] Admin policy paths (cannot be overridden)
mcpServers object {} MCP server configurations
hooks object - Hook event configurations
telemetry object - Telemetry (OTLP) configuration

MCP Server Configuration

Each MCP server entry under mcpServers:

{
  "mcpServers": {
    "server-name": {
      "command": "node",
      "args": ["./server.js"],
      "env": { "KEY": "value" },
      "timeout": 30000,
      "trust": true
    }
  }
}

The MCPServerConfig class at packages/core/src/config/config.ts:465 manages server lifecycle, connection state, and tool discovery.

Environment Variables Reference

Variable Purpose Required For
GEMINI_API_KEY Gemini API key USE_GEMINI auth
GOOGLE_CLOUD_PROJECT GCP project ID USE_VERTEX_AI auth
GOOGLE_CLOUD_LOCATION GCP region USE_VERTEX_AI auth
GOOGLE_API_KEY Google API key Vertex express mode
GOOGLE_GENAI_USE_VERTEXAI Force Vertex AI mode Vertex AI
GEMINI_MODEL Override model name -
GEMINI_SANDBOX Sandbox mode Sandboxing
GEMINI_SANDBOX_IMAGE Custom sandbox Docker image Docker sandbox
GEMINI_SANDBOX_PROXY_COMMAND Proxy setup for sandbox Corporate proxy
SANDBOX_FLAGS Additional sandbox flags -
SANDBOX_MOUNTS Additional sandbox mounts -
BUILD_SANDBOX Build sandbox image Dev
GEMINI_CONFIG_DIR Override config directory -
GEMINI_CLI_HOME Override CLI home directory -
GEMINI_CLI_SYSTEM_SETTINGS_PATH System settings file path Enterprise deployment
GEMINI_CLI_SYSTEM_DEFAULTS_PATH System defaults file path Enterprise deployment
GEMINI_CLI_CUSTOM_HEADERS Custom HTTP headers Proxy/middleware
GEMINI_DEBUG_LOG_FILE Debug log file path Debugging
DEBUG Enable debug logging Debugging
DEBUG_MODE Debug mode flag Debugging
MCP_DEBUG MCP protocol debug logging MCP debugging
HTTPS_PROXY HTTPS proxy URL Corporate network
HTTP_PROXY HTTP proxy URL Corporate network
NO_PROXY Proxy bypass list Corporate network
GOOGLE_VERTEX_BASE_URL Custom Vertex AI endpoint Custom infrastructure
GOOGLE_GEMINI_BASE_URL Custom Gemini API endpoint Custom infrastructure
GEMINI_CLI_IDE_WORKSPACE_PATH IDE workspace path IDE integration
GEMINI_CLI_IDE_SERVER_PORT IDE companion server port IDE integration
VSCODE_PID VS Code process ID IDE detection
GEMINI_FOLDER_TRUST Override folder trust CI/CD
GEMINI_YOLO_MODE Force YOLO mode CI/CD
CHECKPOINTING Enable checkpointing -
OTEL_EXPORTER_OTLP_ENDPOINT OpenTelemetry endpoint Observability

Security Architecture

Authentication

Four authentication types, defined in AuthType enum:

Type Constant Mechanism
Google OAuth LOGIN_WITH_GOOGLE Browser-based OAuth2 flow
Gemini API Key USE_GEMINI GEMINI_API_KEY env var
Vertex AI USE_VERTEX_AI GCP project + location or GOOGLE_API_KEY
Application Default Credentials COMPUTE_ADC gcloud auth application-default

API keys are stored in the OS keychain via HybridTokenStorage (service name: gemini-cli-api-key). The storage uses a TTL cache (30 seconds) to minimize keychain access.

Folder Trust System

Before loading any workspace configuration, Gemini CLI scans the .gemini/ directory via FolderTrustDiscoveryService:

Discovered items:

  • Custom commands (.gemini/commands/*.toml)
  • Skills (.gemini/skills/*/SKILL.md)
  • Agents (.gemini/agents/*.md)
  • MCP servers (from settings.json)
  • Hooks (from settings.json)
  • Settings (non-mcpServer, non-hook keys)

Security warnings are raised for:

  • tools.allowed — auto-approving tools
  • security.folderTrust.enabled = false — disabling trust
  • tools.sandbox = false — disabling sandboxing
  • Custom agents present

Users must explicitly trust a folder before its configurations take effect.

Sandbox System

Caution

Running without a sandbox (empty GEMINI_SANDBOX) means shell commands execute directly on the host. Use sandboxing in any environment where you're working with untrusted code or running in YOLO mode.

Sandbox implementations:

Class Mode Description
LocalSandboxManager docker/podman Container-based isolation
NoopSandboxManager none Direct host execution

Safe command allowlist (packages/core/src/sandbox/utils/commandSafety.ts):

The sandbox evaluates commands before execution. Known read-only commands bypass confirmation:

  • Always safe: cat, cd, cut, echo, grep, head, id, ls, pwd, stat, tail, tr, uname, wc, which, whoami
  • Conditionally safe: base64 (no -o/--output), find (no -exec/-delete), rg (no --pre/--hostname-bin), git (read-only subcommands only: status, log, diff, show, branch without write flags), sed (only -n {N}p patterns)

Commands are parsed with shell-quote to handle pipes, &&, ||, and bash -c wrappers.

Policy Engine

The policy engine evaluates tool calls against rules to determine approval:

Tool Call → Policy Engine → PolicyDecision
                              ├── ALLOW  (auto-approve)
                              ├── DENY   (block)
                              └── ASK    (prompt user)

Approval modes (ApprovalMode enum):

Mode Behavior
DEFAULT All tool calls require approval
AUTO_EDIT Edit tools auto-approved, shell commands ask
YOLO All tools auto-approved
PLAN Read-only mode, write tools denied

Admin policies take precedence over workspace policies via the MODES_BY_PERMISSIVENESS ordering.

Data Sanitization

The agent-sanitization-utils.ts module sanitizes sensitive data before it enters logs or telemetry:

  • PEM block redaction: Iterative parser (not regex) to avoid ReDoS
  • Key-value pair redaction: Matches password=, api_key:, --token patterns
  • Space-separated keyword redaction: Handles password mySecretValue patterns
  • File path redaction: Redacts paths to .key, .pem, .p12, .pfx files

Sensitive key patterns include: password, apikey, token, secret, credential, auth, access_token, refresh_token, session_id, cookie, private_key, client_secret.

Important

The sanitization uses an iterative approach for PEM blocks specifically to prevent Regular Expression Denial of Service (ReDoS) attacks. The test suite includes a ReDoS attack string that must process in under 50ms.

Custom Base URL Validation

When using GOOGLE_VERTEX_BASE_URL or GOOGLE_GEMINI_BASE_URL:

  • URLs must be valid (parsed with URL constructor)
  • Non-localhost URLs must use HTTPS
  • Invalid or HTTP URLs throw Error at startup

Model Routing

Strategy Chain

The CompositeStrategy chains routing strategies in priority order:

  1. OverrideStrategy — Honors explicit model overrides (via --model flag or context.requestedModel)
  2. ApprovalModeStrategy — Routes based on Plan/Act mode:
    • PLAN mode → Pro model (high-quality planning)
    • Approved plan exists → Flash model (efficient implementation)
  3. ClassifierStrategy — Uses LLM classifier to route between Pro and Flash:
    • Evaluates task complexity (steps, ambiguity, strategic planning, debugging depth)
    • 4+ steps → complex → Pro
    • Single step, clear intent → simple → Flash
  4. DefaultStrategy — Returns the configured default model
  5. FallbackStrategy — Last resort when other strategies fail

Model ID Resolution

Models go through a resolution pipeline based on context:

User-facing model ID
    → modelIdResolutions (preview access, custom tools, Gemini 3.1)
        → Final API model ID

Example: auto resolves to gemini-3-pro-preview by default, but falls back to gemini-2.5-pro if the user doesn't have preview access.

Classifier Model

The classifier runs on gemini-2.5-flash-lite with a 512-token thinking budget and generates a JSON response:

{
  "reasoning": "Simple single-file edit task",
  "model_choice": "flash"
}

Hook System Internals

Architecture

Event Trigger
    │
    ▼
HookSystem.fire*Event()
    │
    ▼
HookPlanner.plan()
    │ (selects matching hooks)
    ▼
HookRunner.executeHook()
    │ (spawns child process)
    ▼
HookAggregator.aggregateResults()
    │ (merges all hook outputs)
    ▼
HookEventHandler.handle*()
    │ (applies decisions)
    ▼
Result

Hook Events

Event Input Output Capabilities
BeforeTool Tool name, args, MCP context block, allow, modify args, stop, add context
AfterTool Tool name, result add context
BeforeModel LLM request (model, config, contents) modify request, block
AfterModel Model response add context
BeforeToolSelection - control tool calling mode (NONE, ANY, AUTO)

Aggregation Rules

When multiple hooks fire for the same event:

  • Block decisions use OR logic: If any hook returns "decision": "block", the tool is blocked
  • Continue=false takes precedence: If any hook returns "continue": false, execution stops
  • Reasons are concatenated: All hook reasons are joined with newlines
  • BeforeToolSelection merges: NONE mode takes precedence over ANY, which takes precedence over AUTO. Allowed function names are unioned
  • BeforeModel uses field replacement: Later hooks override earlier hooks' fields (last writer wins)
  • AdditionalContext is concatenated: All hooks' additional context is joined

Hook Execution

Hooks execute as child processes via HookRunner:

  • Default timeout: 30,000ms (configurable per hook)
  • Hook receives input via stdin as JSON
  • Hook returns output via stdout as JSON
  • Timeout is treated as failure
  • Hook errors are aggregated but don't automatically block (unless the hook returned "decision": "block" before failing)

Trusted Hooks

The TrustedHooksManager tracks which hooks have been approved by the user. Untrusted hooks trigger a confirmation prompt before first execution.


Extension System Internals

Extension Manifest Schema

gemini-extension.json:

{
  "name": "extension-name",
  "version": "1.0.0",
  "description": "What this extension does",
  "mcpServers": {},
  "skills": {},
  "commands": {},
  "hooks": {},
  "policies": {},
  "themes": {}
}

Extension Lifecycle

  1. Discovery: ExtensionManager scans enabled extensions
  2. Validation: Manifest validated against schema
  3. Loading: Components registered (MCP servers, commands, skills, etc.)
  4. Initialization: MCP servers started, hooks registered
  5. Runtime: Extension components active in the session
  6. Shutdown: MCP servers stopped, resources cleaned up

Note

Extensions are loaded exactly once per session. Calling loadExtensions() a second time throws "Extensions already loaded, only load extensions once." This prevents resource leaks from duplicate MCP server processes.

Extension Installation Types

Type Source Storage
npm gemini extensions install <package> ~/.gemini/extensions/
Local link gemini extensions link <path> Symlink to local directory
Workspace .gemini/ directory Project-local

Extension Registry

The ExtensionRegistryClient queries a remote registry for available extensions. It supports ordering by relevance, downloads, or name.

Admin Controls

Administrators can restrict extension features via system settings:

  • Disable MCP servers globally
  • Disable extensions
  • Disable skills
  • Restrict which extensions can be installed

These restrictions are checked before executing deferred commands in the CLI's argument parser.


Scheduler and Tool Execution

Tool Call Lifecycle

Model proposes tool call
    │
    ▼
Scheduler receives tool call
    │
    ▼
Policy Engine evaluates
    │
    ├── ALLOW → Execute directly
    ├── DENY → Return error to model
    └── ASK → Enter confirmation flow
              │
              ▼
         BeforeTool hooks fire
              │
              ├── Block → Return error
              ├── Modify args → Rebuild invocation
              └── Allow → Continue
                    │
                    ▼
              User confirmation (if needed)
                    │
                    ├── Approve → Execute
                    ├── Reject → Return rejection
                    └── Edit → Modify args, re-confirm
                          │
                          ▼
                    Tool executes
                          │
                          ▼
                    AfterTool hooks fire
                          │
                          ▼
                    Result returned to model

State Transitions

Tool calls progress through states managed by SchedulerStateManager:

PENDING → VALIDATING → WAITING → EXECUTING → COMPLETED
                  ↘                      ↗
                   → REJECTED / ERROR →

Parallel Execution

The Scheduler supports parallel tool execution. Multiple tool calls from a single model turn execute concurrently, with the state manager tracking each independently.

Tool Modification

The ToolModificationHandler allows users to edit tool arguments during the confirmation flow. This is particularly useful for file edit tools where the user wants to adjust the proposed changes.


Session Management Internals

Session Storage

Sessions are stored as JSON files in the project's temporary directory:

~/.gemini/projects/<project-hash>/chats/<session-id>.json

The Storage class manages the project-specific temp directory, and ChatRecordingService handles read/write operations.

Session File Format

Sessions are stored as ConversationRecord objects containing:

  • sessionId: UUID
  • messages: Array of conversation turns
  • metadata: Model, timestamp, session state

Checkpointing

When enabled, Logger creates git-based checkpoints:

  1. Creates a checkpoint tag at the current commit
  2. Stores conversation state alongside
  3. performRestore() can restore both:
    • Conversation history: Reloads the chat state
    • Git state: Resets the working tree to the checkpoint

Session Retention

The sessionRetention settings control automatic cleanup:

  • Sessions older than maxAge are deleted
  • If maxCount is set, only the most recent N sessions are kept
  • minRetention provides a safety floor (cannot delete sessions newer than this)

Telemetry and Observability

Built-in Telemetry

Gemini CLI collects usage statistics via Clearcut logging (Google's telemetry pipeline):

  • URL: https://play.googleapis.com/log
  • Controlled by: privacy.usageStatisticsEnabled
  • Events: model usage, error rates, feature adoption

OpenTelemetry Support

Configure OTLP export for enterprise observability:

{
  "telemetry": {
    "endpoint": "https://your-otel-collector:4318"
  }
}

Environment variable: OTEL_EXPORTER_OTLP_ENDPOINT

Debug Logging

The DebugLogger class provides structured debug output:

DEBUG=* gemini           # All debug output
DEBUG=hooks gemini       # Only hook debug output
GEMINI_DEBUG_LOG_FILE=/tmp/debug.log gemini  # Write to file

DevTools Inspector

Enable the Chrome DevTools-style inspector:

{
  "general": {
    "devtools": true
  }
}

The DevTools class (extends EventEmitter) broadcasts events that the inspector client consumes via WebSocket.


Performance

Context Compression

When conversation context approaches the model's limit, Gemini CLI triggers compression:

  • Threshold: model.compressionThreshold (default: 0.5)
  • Method: A summarization model (from chat-compression-* aliases) condenses earlier conversation
  • Model selection: Follows the current model family (Gemini 3 uses chat-compression-3-pro, 2.5 uses chat-compression-2.5-pro)

Tool Output Summarization

Large tool outputs can be summarized before adding to context:

{
  "model": {
    "summarizeToolOutput": {
      "run_shell_command": {
        "tokenBudget": 2000
      }
    }
  }
}

Currently only run_shell_command supports summarization.

Loop Detection

LoopDetectionService monitors for infinite loops:

  1. Detects repeated identical tool calls
  2. Uses a lightweight LLM call to confirm the loop
  3. Optionally double-checks with a Pro model
  4. Injects a corrective message to break the loop

Disable with model.disableLoopDetection: true.

File Discovery

File search uses ripgrep (bundled) via FileDiscoveryService. If ripgrep download fails at startup, falls back to slower Node.js-based search.

Retry Strategy

retryWithBackoff() in packages/core/src/utils/retry.ts:

  • Exponential backoff with jitter
  • Configurable maxAttempts (default: 10, enforced max: 10)
  • Respects shouldRetryOnContent for content validation
  • Handles quota errors with specific retry logic:
    • RetryableQuotaError: Retry with backoff
    • TerminalQuotaError: Stop retrying
    • ModelNotFoundError: Try fallback chain

Deployment Patterns

Individual Developer Setup

npm install -g @google/gemini-cli
gemini  # Sign in with Google

Team Deployment with Shared Config

  1. Create system-level settings:
export GEMINI_CLI_SYSTEM_SETTINGS_PATH=/opt/gemini/system-settings.json
{
  "general": {
    "defaultApprovalMode": "default"
  },
  "adminPolicyPaths": ["/opt/gemini/policies/"],
  "model": {
    "name": "gemini-2.5-pro"
  }
}
  1. Distribute via configuration management (Puppet, Chef, Ansible)

CI/CD Integration

export GEMINI_API_KEY="$CI_GEMINI_KEY"
export GEMINI_SANDBOX=docker
export GEMINI_FOLDER_TRUST=true
gemini --yolo -p "Run the full test suite and report results" --output-format json

Enterprise Deployment with Vertex AI

export GOOGLE_CLOUD_PROJECT="enterprise-project"
export GOOGLE_CLOUD_LOCATION="us-central1"
export GEMINI_CLI_SYSTEM_SETTINGS_PATH="/etc/gemini/settings.json"

System settings enforce:

{
  "adminPolicyPaths": ["/etc/gemini/admin-policies/"],
  "security": {
    "folderTrust": { "enabled": true }
  }
}

Custom Endpoint Deployment

For private Gemini API endpoints or proxy setups:

export GOOGLE_VERTEX_BASE_URL="https://my-proxy.internal/vertex"
# or
export GOOGLE_GEMINI_BASE_URL="https://my-proxy.internal/gemini"
export GEMINI_CLI_CUSTOM_HEADERS="X-Custom-Auth=token123"

Warning

Custom base URLs must use HTTPS unless they point to localhost. HTTP URLs are rejected at startup with a clear error message.


Operations

Health Monitoring

Monitor Gemini CLI health through:

  1. Debug logs: GEMINI_DEBUG_LOG_FILE for persistent logging
  2. Telemetry: OTLP export for metrics and traces
  3. DevTools: Real-time inspection of agent behavior
  4. Session recording: --record-responses for reproducible debugging

Error Hierarchy

The codebase defines a structured error hierarchy:

Error
├── FatalError (non-recoverable, exits the session)
│   ├── FatalAuthenticationError
│   ├── FatalInputError
│   ├── FatalSandboxError
│   ├── FatalConfigError
│   ├── FatalTurnLimitedError
│   ├── FatalToolExecutionError
│   └── FatalCancellationError
├── ForbiddenError (403)
│   └── AccountSuspendedError
├── UnauthorizedError (401)
├── BadRequestError (400)
├── CanceledError (user cancellation)
├── ChangeAuthRequestedError (auth method switch)
├── FetchError (network failures)
├── PrivateIpError (blocked private IP access)
├── InvalidStreamError (malformed model stream)
├── AgentExecutionStoppedError (hook stop)
├── AgentExecutionBlockedError (policy block)
├── TerminalQuotaError (unrecoverable quota limit)
├── RetryableQuotaError (temporary quota limit)
├── ValidationRequiredError (requires user action)
├── ModelNotFoundError (invalid model)
└── ShellParserInitializationError

Quota Error Handling

Error Type Behavior
RetryableQuotaError Retry with backoff (per-minute limits)
TerminalQuotaError Stop retrying (daily limits). Offer AI credits if available
ValidationRequiredError Prompt user for action (e.g., billing setup)

Common Operational Issues

Problem: MCP server processes orphaned after crash

MCP servers are child processes. If the CLI crashes, they may persist. Kill orphaned processes:

ps aux | grep "mcp-server" | grep -v grep | awk '{print $2}' | xargs kill

Problem: Settings changes not taking effect

Settings are loaded at startup. Most changes require restart. Check "Requires restart: yes" in the schema documentation.

Problem: Extension conflicts

The SlashCommandConflictHandler detects when multiple extensions register the same command name. It logs warnings and uses priority-based resolution.

Problem: Hook execution slowing down sessions

Profile hooks with DEBUG=hooks gemini. Hooks run sequentially per event. Slow hooks directly impact response time.


Troubleshooting (Admin)

Debug Mode

# Full debug output
DEBUG=* gemini

# Specific subsystems
DEBUG=hooks,mcp,sandbox gemini

# Write to file
GEMINI_DEBUG_LOG_FILE=/var/log/gemini-debug.log gemini

Session Forensics

# List all sessions for a project
gemini --list-sessions

# Session files are at:
ls ~/.gemini/projects/*/chats/

Config Debugging

Check effective merged settings:

/about

This shows: CLI version, OS, sandbox mode, model, auth type, GCP project, IDE client, user email, and tier.

Extension Debugging

# Validate extension manifest
gemini extensions validate

# List with status
gemini extensions list

# Check MCP server connections
/mcp list

Network Debugging

For proxy and connectivity issues:

# Test basic connectivity
curl -v https://generativelanguage.googleapis.com/

# Check proxy config
echo $HTTPS_PROXY $HTTP_PROXY $NO_PROXY

# MCP-specific debug
MCP_DEBUG=true gemini

Model Response Debugging

Record and replay model responses for reproducible debugging:

# Record a session
gemini --record-responses /tmp/session-recording.json -p "reproduce the bug"

# Replay the recording
gemini --fake-responses /tmp/session-recording.json -p "reproduce the bug"

Developer Internals

Build System

The project uses npm workspaces with TypeScript:

# Install all dependencies
npm install

# Build all packages
npm run build

# Run tests
npm test

# Run specific package tests
npm test -w packages/core

Testing Architecture

Test Type Location Runner
Unit tests packages/*/src/**/*.test.ts Vitest
Integration tests integration-tests/ Vitest
Component evals evals/ Custom harness
Memory tests memory-tests/ Custom harness with heap snapshots
Performance tests perf-tests/ Custom harness with timing
SEA tests sea/ Custom launcher tests

Key Test Utilities

Class Purpose
TestRig Full integration test harness with CLI subprocess management
InteractiveRun Manages an interactive CLI session in tests
TestMcpServerBuilder Builds mock MCP servers for testing
MemoryTestHarness Heap snapshot comparison for memory leak detection
PerfTestHarness Timing and performance regression testing
ComponentRig Lightweight component-level test harness

SEA (Single Executable Application)

The sea/ directory packages Gemini CLI as a standalone binary:

  • Uses Node.js SEA (Single Executable Application) feature
  • Bundles all dependencies into a single executable
  • Tests verify filesystem operations, rename handling, and permission checks

Release Process

Release scripts live in scripts/releasing/:

Script Purpose
release.ts Main release orchestrator
Options --commit, --pullRequestNumber, --channel, --cli-package-name, --dry-run

Code Quality Patterns

  • Strict TypeScript: All packages use strict: true
  • Error boundaries: FatalError hierarchy for non-recoverable errors
  • Debug logging: debugLogger throughout for structured diagnostics
  • Schema validation: SchemaValidator for all external input
  • Sanitization: Agent sanitization utils for all sensitive data
  • Cache management: CacheService with TTL and configurable storage backends

Integration Points

SDK Integration

Build custom agents programmatically:

import { GeminiCliAgent } from '@google/gemini-cli-sdk';

const agent = new GeminiCliAgent({
  instructions: 'You are a code review assistant.',
  model: 'gemini-2.5-pro',
  tools: [myCustomTool],
  skills: [mySkill],
});

const session = agent.session();
const stream = session.sendStream('Review the latest PR');

for await (const event of stream) {
  if (event.type === 'content') {
    process.stdout.write(event.value);
  }
}

SDK classes:

Class Purpose
GeminiCliAgent Creates sessions, manages configuration
GeminiCliSession Sends messages, streams responses
SdkTool Base class for custom tools
SdkToolInvocation Tool invocation with parameter access
ModelVisibleError Errors surfaced to the model
SdkAgentFilesystem Sandboxed file operations
SdkAgentShell Shell command execution

Session resume:

const session = await agent.resumeSession(previousSessionId);

A2A Protocol Integration

Expose Gemini CLI as an A2A-compatible agent server:

import { createApp } from '@google/gemini-cli-a2a-server';

const app = createApp(config);
app.listen(3000);

Events stream via SSE using CoderAgentEvent types.

VS Code Integration

The VS Code companion extension:

  1. Starts a local HTTP server on GEMINI_CLI_IDE_SERVER_PORT
  2. Exposes MCP endpoints for tool communication
  3. Manages file diffs via DiffManager and DiffContentProvider
  4. Tracks open files via OpenFilesManager
  5. CORS restricts access to localhost origins only

Enable IDE mode:

{
  "ide": {
    "enabled": true
  }
}

MCP Protocol

Gemini CLI acts as an MCP client, connecting to external tool servers:

  • Transport: stdio (command-based servers) or HTTP (SSE-based servers)
  • Discovery: Tools and prompts are discovered from connected servers
  • Lifecycle: Servers start with the session and stop on exit
  • Token storage: MCP OAuth tokens stored via HybridTokenStorage
  • Debug: MCP_DEBUG=true for protocol-level logging

Known Issues and Open Feature Requests

Based on the project's GitHub issue tracker:

Known Bugs (Resolved)

  • #25622: Gemini Error — general error handling (closed)
  • #25584: Shift+Tab not working on Windows for Plan/Act toggle (closed)
  • #24880: 403 API Error after Google sign-in — commonly a quota/access issue (closed, 31 comments)
  • #25323: RipGrep download failure should not slow startup (closed)
  • #18503: Letter 'm' printed at startup — terminal escape code issue (closed)
  • #20603: Cannot find module 'color-convert' in Colab (closed)
  • #20894: Maximum update depth exceeded — React rendering loop (closed)

Open Feature Requests

  • #15269: Missing subagent hook events
  • #15267: Test and refine hook migration tooling
  • #15263: Granular extension hook control
  • #15167: UI for BeforeTool hooks within tool confirmation
  • #15018: Admin rules that can be overridden
  • #14964: Subagent optimization flow within /agents UI
  • #11802: OTLP headers for telemetry
  • #11303: Change --yolo to be a policy shortcut

Open UX/Security Issues

  • #15268: Interactive hook configuration GUI
  • #15266: Hook execution confirmation UX
  • #15258: Natural language hook building
  • #15179: Recursive subagent delegation
  • #15014: Screen reader text repetition on Windows
  • #14724: Hooks SessionStart "compress" vs "compact" incompatibility
  • #14540: Complete CI/CD security review

Quick Reference

File Layout

~/.gemini/                      # User config directory
├── settings.json               # User settings
├── GEMINI.md                   # Global memory
├── extensions/                 # Installed extensions
└── projects/                   # Project-specific data
    └── <hash>/
        └── chats/              # Session files

.gemini/                        # Workspace config (in project root)
├── settings.json               # Workspace settings
├── commands/                   # Custom TOML commands
├── skills/                     # Custom skills (SKILL.md)
├── agents/                     # Custom agents (.md)
└── policies/                   # Policy files

Config Precedence (highest wins)

  1. CLI flags (--model, --yolo, etc.)
  2. Workspace settings (.gemini/settings.json)
  3. User settings (~/.gemini/settings.json)
  4. System settings (GEMINI_CLI_SYSTEM_SETTINGS_PATH)
  5. System defaults (GEMINI_CLI_SYSTEM_DEFAULTS_PATH)
  6. Built-in defaults

Key Source Files

Purpose Path
CLI entry point packages/cli/index.ts
Core entry point packages/core/src/index.ts
Settings schema schemas/settings.schema.json
Config class packages/core/src/config/config.ts
Agent loop packages/core/src/core/geminiChat.ts
Scheduler packages/core/src/scheduler/scheduler.ts
Hook system packages/core/src/hooks/hookSystem.ts
Model routing packages/core/src/routing/strategies/
Sandbox safety packages/core/src/sandbox/utils/commandSafety.ts
Extension manager packages/cli/src/config/extension-manager.ts
Settings loader packages/cli/src/config/settings.ts
SDK agent packages/sdk/src/agent.ts
A2A server packages/a2a-server/src/index.ts