# Data flow — google-gemini/gemini-cli

> Canonical page: https://codevetter.com/unpack/gemini-cli/data-flow

# Data flow — google-gemini/gemini-cli

Scanned commit d5b3e3accb26000d273abf16e0f1dd83aa5428a9 (2026-09-21). Generated by codevetter codevetter 1.12.0 on 2026-09-22.

Input enters via argv/stdin, is merged with layered settings.json files (system → user → workspace, plus remote admin controls over IPC), then Config becomes the single state owner for the session. A prompt flows through slash-command and @-file processors into Part[] arrays, into GeminiClient.sendMessageStream → Turn → GeminiChat → ContentGenerator → the Gemini/Code Assist/Vertex HTTP stream. Streamed chunks become typed events; ToolCallRequest events are drained into the Scheduler which runs policy checks, user confirmation over the MessageBus, hooks, then the ToolExecutor; tool results are appended as functionResponse parts and recorded into chat history plus the JSONL session file, looping until a Finished/Stopped event. Output exits via coreEvents.Output/TextOutput/StreamJsonFormatter or the Ink UI.
- Settings data flow: loadSettings() reads layered settings.json (system path /etc/gemini-cli or OS equivalents, user ~/.gemini/settings.json, workspace .gemini/settings.json), interpolates env vars (resolveEnvVarsInObject), merges with customDeepMerge per schema mergeStrategy, and validates against the generated settingsSchema. — [packages/cli/src/config/settings.ts#L82-117](https://github.com/google-gemini/gemini-cli/blob/d5b3e3accb26000d273abf16e0f1dd83aa5428a9/packages/cli/src/config/settings.ts#L82-L117) [packages/cli/src/config/settingsSchema.ts](https://github.com/google-gemini/gemini-cli/blob/d5b3e3accb26000d273abf16e0f1dd83aa5428a9/packages/cli/src/config/settingsSchema.ts) [packages/cli/src/utils/envVarResolver.ts](https://github.com/google-gemini/gemini-cli/blob/d5b3e3accb26000d273abf16e0f1dd83aa5428a9/packages/cli/src/utils/envVarResolver.ts) [packages/cli/src/utils/deepMerge.ts](https://github.com/google-gemini/gemini-cli/blob/d5b3e3accb26000d273abf16e0f1dd83aa5428a9/packages/cli/src/utils/deepMerge.ts)
- Remote admin/enterprise controls flow over Node IPC: the parent process forwards {type:'admin-settings'} messages to the child, which calls config.setRemoteAdminSettings; the child pushes 'admin-settings-update' back after refreshAuth fetches CCPA admin settings. — [packages/cli/index.ts#L63-87](https://github.com/google-gemini/gemini-cli/blob/d5b3e3accb26000d273abf16e0f1dd83aa5428a9/packages/cli/index.ts#L63-L87) [packages/cli/src/gemini.tsx#L1057-1088](https://github.com/google-gemini/gemini-cli/blob/d5b3e3accb26000d273abf16e0f1dd83aa5428a9/packages/cli/src/gemini.tsx#L1057-L1088) [packages/cli/src/gemini.tsx#L669-679](https://github.com/google-gemini/gemini-cli/blob/d5b3e3accb26000d273abf16e0f1dd83aa5428a9/packages/cli/src/gemini.tsx#L669-L679)
- Prompt ingress in headless mode: stdin (readStdin) is prepended to --prompt input, SessionStart hook context is wrapped in <hook_context> tags and prepended, then slash commands (isSlashCommand → handleSlashCommand) or @-commands (handleAtCommand) convert text into Part[] before entering the loop. — [packages/cli/src/gemini.tsx#L927-966](https://github.com/google-gemini/gemini-cli/blob/d5b3e3accb26000d273abf16e0f1dd83aa5428a9/packages/cli/src/gemini.tsx#L927-L966) [packages/cli/src/nonInteractiveCli.ts#L262-311](https://github.com/google-gemini/gemini-cli/blob/d5b3e3accb26000d273abf16e0f1dd83aa5428a9/packages/cli/src/nonInteractiveCli.ts#L262-L311) [packages/cli/src/ui/hooks/atCommandProcessor.ts](https://github.com/google-gemini/gemini-cli/blob/d5b3e3accb26000d273abf16e0f1dd83aa5428a9/packages/cli/src/ui/hooks/atCommandProcessor.ts) [packages/cli/src/nonInteractiveCliCommands.ts](https://github.com/google-gemini/gemini-cli/blob/d5b3e3accb26000d273abf16e0f1dd83aa5428a9/packages/cli/src/nonInteractiveCliCommands.ts)
- Per turn, GeminiClient.sendMessageStream resets turn state, runs BeforeAgent hooks (can stop/block/inject additionalContext), then delegates to Turn.run which streams GeminiChat responses; GeminiChat wraps the API call in retryWithBackoff and raises InvalidStreamError for empty/malformed/safety-blocked streams. — [packages/core/src/core/client.ts#L910-970](https://github.com/google-gemini/gemini-cli/blob/d5b3e3accb26000d273abf16e0f1dd83aa5428a9/packages/core/src/core/client.ts#L910-L970) [packages/core/src/core/turn.ts#L270-320](https://github.com/google-gemini/gemini-cli/blob/d5b3e3accb26000d273abf16e0f1dd83aa5428a9/packages/core/src/core/turn.ts#L270-L320) [packages/core/src/core/geminiChat.ts#L311-337](https://github.com/google-gemini/gemini-cli/blob/d5b3e3accb26000d273abf16e0f1dd83aa5428a9/packages/core/src/core/geminiChat.ts#L311-L337) [packages/core/src/core/geminiChat.ts#L1113](https://github.com/google-gemini/gemini-cli/blob/d5b3e3accb26000d273abf16e0f1dd83aa5428a9/packages/core/src/core/geminiChat.ts#L1113) [packages/core/src/core/geminiChat.ts#L1576-1602](https://github.com/google-gemini/gemini-cli/blob/d5b3e3accb26000d273abf16e0f1dd83aa5428a9/packages/core/src/core/geminiChat.ts#L1576-L1602)
- Tool-call data flow: resp.functionCalls become ToolCallRequestInfo via Turn.handlePendingFunctionCall → ToolCallRequest events; the consumer collects them and calls Scheduler.schedule, which runs checkPolicy/policy engine, resolveConfirmation over the MessageBus, BeforeTool hooks (evaluateBeforeToolHook), ToolModificationHandler, then ToolExecutor, producing CompletedToolCall with ToolCallResponseInfo. — [packages/core/src/core/turn.ts#L380-387](https://github.com/google-gemini/gemini-cli/blob/d5b3e3accb26000d273abf16e0f1dd83aa5428a9/packages/core/src/core/turn.ts#L380-L387) [packages/cli/src/nonInteractiveCli.ts#L482-545](https://github.com/google-gemini/gemini-cli/blob/d5b3e3accb26000d273abf16e0f1dd83aa5428a9/packages/cli/src/nonInteractiveCli.ts#L482-L545) [packages/core/src/scheduler/scheduler.ts#L95-130](https://github.com/google-gemini/gemini-cli/blob/d5b3e3accb26000d273abf16e0f1dd83aa5428a9/packages/core/src/scheduler/scheduler.ts#L95-L130) [packages/core/src/scheduler/confirmation.ts](https://github.com/google-gemini/gemini-cli/blob/d5b3e3accb26000d273abf16e0f1dd83aa5428a9/packages/core/src/scheduler/confirmation.ts) [packages/core/src/scheduler/tool-executor.ts](https://github.com/google-gemini/gemini-cli/blob/d5b3e3accb26000d273abf16e0f1dd83aa5428a9/packages/core/src/scheduler/tool-executor.ts)
- Tool responses re-enter the model loop as functionResponse parts appended to currentMessages; recordCompletedToolCalls persists metadata into GeminiChat history and recordToolCallInteractions logs telemetry before the next sendMessageStream iteration, bounded by getMaxSessionTurns(). — [packages/cli/src/nonInteractiveCli.ts#L488-544](https://github.com/google-gemini/gemini-cli/blob/d5b3e3accb26000d273abf16e0f1dd83aa5428a9/packages/cli/src/nonInteractiveCli.ts#L488-L544) [packages/cli/src/nonInteractiveCli.ts#L311-332](https://github.com/google-gemini/gemini-cli/blob/d5b3e3accb26000d273abf16e0f1dd83aa5428a9/packages/cli/src/nonInteractiveCli.ts#L311-L332) [packages/core/src/core/client.ts#L79](https://github.com/google-gemini/gemini-cli/blob/d5b3e3accb26000d273abf16e0f1dd83aa5428a9/packages/core/src/core/client.ts#L79)
- Policy decisions are computed by a tiered TOML rule engine: directories ordered Default → Extension → Workspace → User → Admin map to priority tiers 1-5 with fractional offsets for flags like --allowed-tools, coreTools, and trusted/allowed MCP servers; rules yield PolicyDecision allow/ask_user/deny consumed by the scheduler. — [packages/core/src/policy/config.ts#L66-110](https://github.com/google-gemini/gemini-cli/blob/d5b3e3accb26000d273abf16e0f1dd83aa5428a9/packages/core/src/policy/config.ts#L66-L110) [packages/core/src/policy/policy-engine.ts](https://github.com/google-gemini/gemini-cli/blob/d5b3e3accb26000d273abf16e0f1dd83aa5428a9/packages/core/src/policy/policy-engine.ts) [packages/core/src/policy/toml-loader.ts](https://github.com/google-gemini/gemini-cli/blob/d5b3e3accb26000d273abf16e0f1dd83aa5428a9/packages/core/src/policy/toml-loader.ts) [packages/core/src/scheduler/policy.ts](https://github.com/google-gemini/gemini-cli/blob/d5b3e3accb26000d273abf16e0f1dd83aa5428a9/packages/core/src/scheduler/policy.ts)
- Session persistence is an append-only JSONL transcript: ConversationRecord header line followed by MessageRecord/MetadataUpdateRecord/RewindRecord lines written to ~/.gemini/tmp/<projectHash>/chats/session-*.jsonl by ChatRecordingService, with ENOSPC graceful degradation. — [packages/core/src/services/chatRecordingService.ts#L28-98](https://github.com/google-gemini/gemini-cli/blob/d5b3e3accb26000d273abf16e0f1dd83aa5428a9/packages/core/src/services/chatRecordingService.ts#L28-L98) [packages/cli/src/gemini.tsx#L371-391](https://github.com/google-gemini/gemini-cli/blob/d5b3e3accb26000d273abf16e0f1dd83aa5428a9/packages/cli/src/gemini.tsx#L371-L391)
- The system prompt is assembled by getCoreSystemPrompt(config, userMemory) via a PromptProvider, combining environment context (getDirectoryContextString), GEMINI.md memory, and model-family-specific tool declarations resolved per model in tools/definitions. — [packages/core/src/core/prompts.ts#L23-31](https://github.com/google-gemini/gemini-cli/blob/d5b3e3accb26000d273abf16e0f1dd83aa5428a9/packages/core/src/core/prompts.ts#L23-L31) [packages/core/src/core/client.ts#L1077-1078](https://github.com/google-gemini/gemini-cli/blob/d5b3e3accb26000d273abf16e0f1dd83aa5428a9/packages/core/src/core/client.ts#L1077-L1078) [packages/core/src/utils/environmentContext.ts](https://github.com/google-gemini/gemini-cli/blob/d5b3e3accb26000d273abf16e0f1dd83aa5428a9/packages/core/src/utils/environmentContext.ts) [packages/core/src/tools/definitions/resolver.ts](https://github.com/google-gemini/gemini-cli/blob/d5b3e3accb26000d273abf16e0f1dd83aa5428a9/packages/core/src/tools/definitions/resolver.ts) [packages/core/src/tools/definitions/model-family-sets](https://github.com/google-gemini/gemini-cli/blob/d5b3e3accb26000d273abf16e0f1dd83aa5428a9/packages/core/src/tools/definitions/model-family-sets)
- Context-window management: token counts are estimated per request (calculateRequestTokenCount, tokenLimit) and ChatCompressionService compresses history (emitting ChatCompressed events); LoopDetectionService watches for repetitive turns and yields LoopDetected; ContextManager/AgentHistoryProvider/ToolOutputMaskingService manage what history the model sees. — [packages/core/src/core/client.ts#L97-120](https://github.com/google-gemini/gemini-cli/blob/d5b3e3accb26000d273abf16e0f1dd83aa5428a9/packages/core/src/core/client.ts#L97-L120) [packages/core/src/context/chatCompressionService.ts](https://github.com/google-gemini/gemini-cli/blob/d5b3e3accb26000d273abf16e0f1dd83aa5428a9/packages/core/src/context/chatCompressionService.ts) [packages/core/src/services/loopDetectionService.ts#L133](https://github.com/google-gemini/gemini-cli/blob/d5b3e3accb26000d273abf16e0f1dd83aa5428a9/packages/core/src/services/loopDetectionService.ts#L133) [packages/core/src/core/tokenLimits.ts](https://github.com/google-gemini/gemini-cli/blob/d5b3e3accb26000d273abf16e0f1dd83aa5428a9/packages/core/src/core/tokenLimits.ts)
- Output egress is centralized through patchStdio + coreEvents: initializeOutputListenersAndFlush drains backlogged Output/ConsoleLog/UserFeedback events to stdout/stderr, forcing stdout payloads to stderr when outputFormat is 'json' so machine output stays parseable; ConsolePatcher reroutes console.* into the same bus for the UI. — [packages/cli/src/gemini.tsx#L1006-1055](https://github.com/google-gemini/gemini-cli/blob/d5b3e3accb26000d273abf16e0f1dd83aa5428a9/packages/cli/src/gemini.tsx#L1006-L1055) [packages/cli/src/ui/utils/ConsolePatcher.ts](https://github.com/google-gemini/gemini-cli/blob/d5b3e3accb26000d273abf16e0f1dd83aa5428a9/packages/cli/src/ui/utils/ConsolePatcher.ts) [packages/cli/src/nonInteractiveCli.ts#L85-103](https://github.com/google-gemini/gemini-cli/blob/d5b3e3accb26000d273abf16e0f1dd83aa5428a9/packages/cli/src/nonInteractiveCli.ts#L85-L103)
- IDE context flows in from the vscode-ide-companion over a local connection managed by IdeClient into ideContextStore; GeminiClient diffs lastSentIdeContext vs current (forceFullIdeContext flag) to inject file/selection context into requests. (inferred) — [packages/core/src/ide/ide-client.ts](https://github.com/google-gemini/gemini-cli/blob/d5b3e3accb26000d273abf16e0f1dd83aa5428a9/packages/core/src/ide/ide-client.ts) [packages/core/src/ide/ideContext.ts](https://github.com/google-gemini/gemini-cli/blob/d5b3e3accb26000d273abf16e0f1dd83aa5428a9/packages/core/src/ide/ideContext.ts) [packages/core/src/core/client.ts#L104-105](https://github.com/google-gemini/gemini-cli/blob/d5b3e3accb26000d273abf16e0f1dd83aa5428a9/packages/core/src/core/client.ts#L104-L105) [packages/vscode-ide-companion/src/ide-server.ts](https://github.com/google-gemini/gemini-cli/blob/d5b3e3accb26000d273abf16e0f1dd83aa5428a9/packages/vscode-ide-companion/src/ide-server.ts)

Every claim links to its cited files at the pinned commit. Citations identify source evidence; they do not establish runtime correctness. Independent CodeVetter scan — not reviewed by upstream maintainers.

## Public product links

- [CodeVetter](https://codevetter.com/)
- [Download](https://codevetter.com/download)
- [Documentation](https://codevetter.com/docs/)
- [Source](https://github.com/Codevetter/codevetter)
