The Cartographer · 11 min mission
Gemini CLI Settings & Configuration
Master the seven-layer settings.json precedence model and never wonder which config is winning again.
On this page
Gemini CLI's effective configuration is the result of merging several sources in a fixed order. This guide gives you the seven-layer precedence model, the exact settings.json paths and keys, .env loading rules, and the flags that override files per session — so you can set any option and predict which layer wins.
Precedence: seven layers, lowest to highest
Configuration merges in a fixed order. For any key, the highest-numbered layer that sets it wins; unset keys fall through to the layer below.
| # | Layer | Source |
|---|---|---|
| 1 | Default values | Hardcoded defaults baked into the app |
| 2 | System defaults file | system-defaults.json — system-wide base, meant to be overridden |
| 3 | User settings file | ~/.gemini/settings.json |
| 4 | Project settings file | .gemini/settings.json in the project root |
| 5 | System settings file | System-wide settings.json — enterprise override; beats project |
| 6 | Environment variables | Including values loaded from .env files |
| 7 | Command-line arguments | Per-session; highest precedence |
| Layer | Linux | macOS | Windows | Path override |
|---|---|---|---|---|
| System defaults (layer 2) | /etc/gemini-cli/system-defaults.json | /Library/Application Support/GeminiCli/system-defaults.json | C:\ProgramData\gemini-cli\system-defaults.json | GEMINI_CLI_SYSTEM_DEFAULTS_PATH |
| System override (layer 5) | /etc/gemini-cli/settings.json | /Library/Application Support/GeminiCli/settings.json | C:\ProgramData\gemini-cli\settings.json | GEMINI_CLI_SYSTEM_SETTINGS_PATH |
A representative settings.json
Personal preferences go in the user file (~/.gemini/settings.json); team conventions go in the committed project file (.gemini/settings.json). Every key sits inside its category object, and string values can interpolate environment variables.
{
"ui": {
"theme": "Tokyo Night",
"autoThemeSwitching": true,
"hideTips": false
},
"general": {
"preferredEditor": "vscode",
"vimMode": false,
"defaultApprovalMode": "default"
},
"model": {
"maxSessionTurns": -1,
"compressionThreshold": 0.5
},
"tools": {
"allowed": ["run_shell_command(git)", "run_shell_command(npm test)"],
"useRipgrep": true
},
"privacy": {
"usageStatisticsEnabled": false
},
"mcpServers": {
"github": {
"httpUrl": "https://api.example.com/mcp",
"headers": { "Authorization": "Bearer ${GITHUB_TOKEN}" },
"timeout": 30000
}
}
}Build your settings.json
Gemini CLI settings builder
Pick a model, set how much autonomy to grant, choose a theme, and wire in an MCP server — the .gemini/settings.json on the right rewrites itself as you click. Every key uses the real nested schema, so the file drops straight into your project or home directory.
Model
Written as model.name — the Gemini model used for conversations.
Deepest reasoning.
Approval mode
general.defaultApprovalMode decides how much Gemini does before asking you.
Prompt before each tool runs.
Sandbox
tools.sandbox isolates tool execution. true uses the default; name a runtime to force it.
No sandbox.
Theme
ui.theme sets the terminal color scheme. Pick any built-in theme.
Dark
Light
MCP server
Add one server under mcpServers. stdio launches a local process; HTTP connects to a streamable endpoint.
{ "model": { "name": "gemini-2.5-pro" }, "general": { "defaultApprovalMode": "default" }, "tools": { "sandbox": false }, "ui": { "theme": "Default" }, "mcpServers": { "context7": { "command": "npx", "args": [ "-y", "@upstash/context7-mcp" ] } }}.env auto-loading
Layer 6 includes variables auto-loaded from .env. Search order: (1) .env in the current working directory; (2) if none, walk up through parent directories until an .env is found or you hit the project root (a .git directory) or your home directory; (3) finally fall back to ~/.env. Each extension can also carry its own .env, loaded automatically.
| Key | Type | Default | What it does |
|---|---|---|---|
advanced.excludedEnvVars | array | ["DEBUG", "DEBUG_MODE"] | Variable names stripped from project .env files |
advanced.ignoreLocalEnv | boolean | false | When true, ignores generic project .env files entirely |
Themes
Set the theme via ui.theme or the interactive /theme command. Gemini CLI ships ten dark themes (ANSI, Atom One, Ayu, Default, Dracula, GitHub, Holiday, Shades Of Purple, Solarized Dark, Tokyo Night) and seven light themes (ANSI Light, Ayu Light, Default Light, GitHub Light, Google Code, Solarized Light, Xcode). ui.autoThemeSwitching (default true) flips light/dark by terminal background color, polling every ui.terminalBackgroundPollingInterval seconds (default 60).
Define custom themes under ui.customThemes with hex (#FF0000) or CSS color names (coral). You can load a theme from a file by setting ui.theme to a path — but the file must reside inside your home directory or it is refused with a warning.
OpenTelemetry vs. usage statistics
telemetry.* (opt-IN, off)
A full OpenTelemetry pipeline you switch on.
telemetry.enabled (default false), telemetry.target ("local" | "gcp", default "local"), telemetry.otlpEndpoint (default http://localhost:4317), telemetry.otlpProtocol ("grpc" | "http", default "grpc"), telemetry.logPrompts, telemetry.outfile, telemetry.traces (default false).
Every key has a GEMINI_TELEMETRY_* env override. Captures detailed traces — tool outputs, file reads — when enabled. Built for your debugging.
privacy.usageStatisticsEnabled (opt-OUT, on)
Anonymous product analytics, on by default.
Collected: tool-call names / success / duration, the model used per request, request duration and success, and CLI config like enabled tools and approval mode.
Never collected: PII, prompt or response content, file content, or tool arguments and return data.
One boolean: privacy.usageStatisticsEnabled: false to opt out.
High-value config keys by category
All keys nest under their category object. Types and defaults below are verified against the JSON Schema.
| Key | Type | Default | What it controls |
|---|---|---|---|
general.preferredEditor | enum | undefined | Editor for diffs/edits — vscode, cursor, zed, vim, neovim, and more |
general.defaultApprovalMode | enum | "default" | default / auto_edit / plan — YOLO is not here |
general.maxAttempts | number | 10 | Retry attempts per turn; cannot exceed 10 |
model.name | string | undefined | Gemini model for conversations; unset uses the CLI default |
model.maxSessionTurns | number | -1 | Turn cap for a session; -1 means unlimited |
model.compressionThreshold | number | 0.5 | Context-usage fraction that triggers history compression |
tools.allowed | array | [] | Tool calls that bypass the confirmation dialog, e.g. run_shell_command(git) |
tools.sandbox | string/bool | undefined | docker / podman / lxc / windows-native / a profile path |
context.fileName | string/array | GEMINI.md | Context filename(s) loaded into memory when unset |
security.folderTrust.enabled | boolean | true | Whether folders must be trusted before tools run in them |
security.disableYoloMode | boolean | false | Hard-blocks --yolo / --approval-mode=yolo when true |
Knowledge check
Your project `.gemini/settings.json` sets `model.name` to `gemini-2.5-flash`, your `~/.gemini/settings.json` sets it to `gemini-2.5-pro`, and the machine has a system override `settings.json` setting it to `gemini-3-pro-preview`. With no flags or env vars, which model does Gemini CLI use?
Set up config you can reason about
Wire the JSON Schema into your editor
Point your editor at
schemas/settings.schema.json(in-repo) or the hosted copy. Autocomplete and validation for every nested key kills the "I wrote a flat key and nothing happened" class of bug.Put personal taste in the user file
Theme,
general.preferredEditor,general.vimMode,privacy.usageStatisticsEnabled— anything that follows you across projects goes in~/.gemini/settings.json.Put team conventions in the committed project file
Allowed tools (
tools.allowed),model.name,tools.sandbox,context.fileName— anything the whole repo should share goes in.gemini/settings.jsonand gets committed.Keep secrets in .env, referenced by interpolation
Store tokens in
.env(or.gemini/.envfor debug flags), then reference them fromsettings.jsonwith${VAR_NAME}so nothing sensitive lands in a committed file.Override per session with flags, not edits
For a one-off — a different model, plan mode, an extra directory — use a CLI flag. It beats every file for that session and leaves your files untouched.
Reach the end and this star joins your charted sky.