Configuring Gemini CLI
Gemini CLI is Google’s official open-source CLI agent for Gemini models. The big draw is the generous personal-Google free tier, which makes it a cheap default for academic groups already on Google Workspace.
Install and authenticate
Section titled “Install and authenticate”npm install -g @google/gemini-cliOther paths: brew install gemini-cli, npx @google/gemini-cli, port install gemini-cli. Requires Node.js 20 or newer.
Four authentication methods, settable per session via /auth:
| Method | Env vars | Notes |
|---|---|---|
| Sign in with Google (OAuth) | none | Browser flow. Use this for the personal free tier. |
| Gemini API key | GEMINI_API_KEY |
From AI Studio. No GCP project needed. |
| Vertex AI (ADC) | GOOGLE_CLOUD_PROJECT, GOOGLE_CLOUD_LOCATION |
Run gcloud auth application-default login first. |
| Vertex AI (service account) | GOOGLE_APPLICATION_CREDENTIALS, GOOGLE_CLOUD_PROJECT, GOOGLE_CLOUD_LOCATION |
Role: “Vertex AI User”. |
If GOOGLE_API_KEY or GEMINI_API_KEY are set, they override OAuth. Unset them when switching to ADC.
Model selection
Section titled “Model selection”Default is Gemini 2.5 Pro with automatic fallback to 2.5 Flash on rate limit.
gemini -m gemini-2.5-flash # one-off{ "model": { "name": "gemini-2.5-pro" } }Or via env: GEMINI_MODEL=gemini-2.5-pro. In-session: /model.
Common identifiers: gemini-2.5-pro, gemini-2.5-flash, gemini-2.5-flash-lite. Verify against /model because Google rotates suffixes.
Project memory: GEMINI.md
Section titled “Project memory: GEMINI.md”Loading order, concatenated and sent every prompt:
~/.gemini/GEMINI.md(global)- Project-root
GEMINI.mdand ancestor directories up to a trusted root - Just-in-time
GEMINI.mdfiles in any directory tools touch
Imports use @<path> inside any GEMINI.md. Only .md files import successfully; other extensions warn and skip. Default max import depth is 5.
# Project guidelines
@./docs/style-guide.md@../shared/python-conventions.md
## Conventions
- Reference: GRCh38, GENCODE v45.- Single-cell: follow single-cell-best-practices.org.- Pipelines: prefer nf-core when an option exists.- Use `uv add`, never `pip install`.Override the filename in settings.json:
{ "context": { "fileName": ["AGENTS.md", "CONTEXT.md", "GEMINI.md"] } }The /memory slash command shows what is currently loaded and refreshes after edits.
Config file: settings.json
Section titled “Config file: settings.json”Locations, in increasing precedence:
- Built-in defaults
- System defaults (Linux:
/etc/gemini-cli/system-defaults.json) - User:
~/.gemini/settings.json(Windows:%AppData%\.gemini\settings.json) - Project:
<repo>/.gemini/settings.json - System overrides
- Environment variables (including
.env) - CLI flags
.env lookup order: cwd, then ancestor directories until .git or $HOME, then ~/.env. Files at <project>/.gemini/.env are never excluded; project-root .env files have DEBUG/DEBUG_MODE filtered out by default.
Env var interpolation inside JSON: $VAR, ${VAR}, ${VAR:-default}.
A representative ~/.gemini/settings.json:
{ "general": { "vimMode": false, "preferredEditor": "code" }, "ui": { "theme": "GitHub", "hideBanner": true }, "model": { "name": "gemini-2.5-pro" }, "tools": { "sandbox": "docker" }, "context": { "fileName": ["GEMINI.md", "AGENTS.md"] }, "mcpServers": { "fs": { "command": "npx", "args": ["-y", "@modelcontextprotocol/server-filesystem", "/data"] } }}Sandbox and approvals
Section titled “Sandbox and approvals”Approval modes, set with --approval-mode:
default: prompt before each tool call.auto_edit: auto-approvereplaceandwrite_file; still prompt for shell.yolo: approve everything. Flag-only (--yolo); cannot be set insettings.json.
Sandbox (independent of approval mode but auto-enabled with --yolo):
| Method | Where it works |
|---|---|
sandbox-exec |
macOS Seatbelt |
docker / podman |
All platforms |
| Windows Native Sandbox | Windows |
runsc (gVisor) |
Linux |
lxc / lxd |
Linux |
Enable via -s flag, env GEMINI_SANDBOX=docker, or settings.json:
{ "tools": { "sandbox": "docker" } }Default container image: ghcr.io/google/gemini-cli:latest.
The Policy engine covers finer-grained allow/deny rules and is worth reading once.
Custom commands
Section titled “Custom commands”Custom slash commands are TOML files:
| Path | Invocation |
|---|---|
~/.gemini/commands/<name>.toml |
/<name> |
<repo>/.gemini/commands/<name>.toml |
/<name> (overrides user) |
commands/git/commit.toml |
/git:commit |
Schema: prompt (required), description (optional). Inside the prompt:
{{args}}— raw user args (shell-escaped inside!{...})!{cmd}— runs shell, injects stdout (prompts for confirmation)@{path}— injects file contents or directory listing
description = "Refactor the current context into a pure function."prompt = """Analyze the code in context. Refactor it into a pure function.Return the new code block plus a short note on what changed."""Extensions bundle commands plus MCP server configs plus GEMINI.md plus excludeTools allowlists. Useful for sharing whole toolkits with a team.
MCP servers
Section titled “MCP servers”Configured under mcpServers in settings.json. Three transports:
{ "mcpServers": { "pythonTools": { "command": "python", "args": ["-m", "my_mcp_server"], "cwd": "./mcp-servers/python", "env": { "DB_URL": "$DB_CONNECTION_STRING" }, "timeout": 15000, "trust": false }, "remoteHttp": { "httpUrl": "http://localhost:3000/mcp", "timeout": 5000 }, "remoteSse": { "url": "https://api.example.com/sse", "headers": { "Authorization": "Bearer $TOKEN" } } }}Programmatic add:
gemini mcp add my-server python server.py -e API_KEY=123gemini mcp add http-server https://api.example.com/mcp -t http -H "Authorization: Bearer abc"fastmcp install gemini-cli (FastMCP 2.12.3+) auto-wires Python MCP servers.
Headless mode
Section titled “Headless mode”gemini -p "summarise CHANGELOG.md" --output-format json --yoloUseful flags:
-p,--prompt: single-shot query, no REPL.--output-format json|stream-json: JSON hasresponse,stats, optionalerror.stream-jsonemits newline-delimited events.--yolo: auto-approve tools (combine with sandbox in CI).-m: model override.--include-directories ../lib,../docs: extra workspace roots.
Exit codes: 0 success, 1 general error, 42 input error, 53 turn limit exceeded.
Free tier vs paid
Section titled “Free tier vs paid”The numbers below are 2026 snapshots. Google reduced free quotas 50–80% in December 2025 and continues to adjust them. Always check the live limits at aistudio.google.com/rate-limit.
Personal Google login (Gemini Code Assist for individuals): around 1,000 model requests per user per day. Mix of 2.5 Pro and Flash, with Pro throttled hard after the first ~10–15 prompts and the CLI silently falling back to Flash.
Free Gemini API key (AI Studio):
- 2.5 Pro: ~5 requests/minute, ~100 requests/day
- 2.5 Flash: ~10 RPM, ~250 RPD
- 2.5 Flash-Lite: ~15 RPM, ~1000 RPD
Limits are per project, not per key.
Vertex AI: pay-as-you-go from the start (Express Mode offers a 90-day trial). Setting GOOGLE_CLOUD_PROJECT and authenticating via ADC or a service account routes traffic through Vertex billing.
What triggers payment: moving from OAuth login or GEMINI_API_KEY to a Vertex auth method, or attaching billing to a Cloud project the key references.
Bioinformatics-flavoured config
Section titled “Bioinformatics-flavoured config”A workstation ~/.gemini/settings.json aimed at bioinformatics:
{ "model": { "name": "gemini-2.5-pro" }, "tools": { "sandbox": "podman" }, "context": { "fileName": ["GEMINI.md", "AGENTS.md", "CLAUDE.md"] }, "mcpServers": { "refs": { "command": "npx", "args": ["-y", "@modelcontextprotocol/server-filesystem", "/data/refs"] } }, "ui": { "hideBanner": true }}Listing CLAUDE.md last in context.fileName gives Gemini a fallback when a project was originally set up for Claude Code.
Gotchas
Section titled “Gotchas”- Vertex AI API-key support is documented but does not always work; ADC or a service account is more reliable.
auto_editandyolointeraction has had regressions; verify on your installed version.- Free tier numbers will rot fast. Always link readers to the live AI Studio dashboard.
contextFileNameschema changed from string to array; older guides are wrong.mcpServerslocation has historically lived insettings.json; extensions can now bundle them, so ownership may shift.