●NANOLITE — Nano Banana 2 Lite is here: Google's fastest and most cost-efficient Gemini Image model, made for running lightweight image generation cheaply●OMNIFLASH — Gemini Omni Flash is in public preview, a natively multimodal model that lets enterprises and developers build custom, dynamic video workflows●AGENTS — Managed Agents expand with background: true for async server-side runs and polling, remote MCP server integration, and refreshing credentials across interactions●MEMORY — The Memory Bank IngestEvents API is generally available, decoupling event ingestion from memory generation so you can stream content continuously●THROUGHPUT — Provisioned Throughput now lets you submit up to seven pending orders for the same model and region●DEPRECATE — Image generation models shut down on August 17, and the Grok 4.1 family on the Gemini Enterprise Agent Platform on August 20●NANOLITE — Nano Banana 2 Lite is here: Google's fastest and most cost-efficient Gemini Image model, made for running lightweight image generation cheaply●OMNIFLASH — Gemini Omni Flash is in public preview, a natively multimodal model that lets enterprises and developers build custom, dynamic video workflows●AGENTS — Managed Agents expand with background: true for async server-side runs and polling, remote MCP server integration, and refreshing credentials across interactions●MEMORY — The Memory Bank IngestEvents API is generally available, decoupling event ingestion from memory generation so you can stream content continuously●THROUGHPUT — Provisioned Throughput now lets you submit up to seven pending orders for the same model and region●DEPRECATE — Image generation models shut down on August 17, and the Grok 4.1 family on the Gemini Enterprise Agent Platform on August 20
Wiring Gemini CLI into Your Shell and CI — Headless Runs and Session Resume
Move past interactive use of Gemini CLI: headless runs, JSON output, session resume, approval modes, and MCP integration. A practical guide to embedding it in shell scripts and CI, with lessons from real use.
Type gemini, press enter, and an interactive screen quietly comes to life. Most of you have probably been here already.
What genuinely helped me, though, was realizing I could call Gemini CLI as a single line inside a shell script. Handing my morning skim of build logs across four sites over to gemini -p visibly shrank the time I spent checking them.
This article focuses on Gemini CLI as a tool rather than a chat window: headless execution, JSON output, session resume, approval modes, and MCP integration. We'll walk through the spots that tend to trip people up when they actually embed it into scripts.
Start with the correct install and auth
Gemini CLI is Google's open-source terminal agent, published on npm as @google/gemini-cli. You'll want Node.js 20 or higher — ideally the 22 LTS.
# Global installnpm install -g @google/gemini-cli# Try it once without a permanent installnpx @google/gemini-cli# Check the versiongemini --version
There are two ways to authenticate. On first launch, gemini prompts you to sign in with a Google account, and you can start on the free tier right away. In environments that can't show an interactive prompt — CI or scripts — passing an API key via an environment variable is the reliable path.
# API key auth (for CI and automation)export GEMINI_API_KEY="YOUR_API_KEY"
Keep the key in .env and always add it to .gitignore. Skip this and you risk pushing your key straight into a public repository.
Gemini CLI's invocations split broadly into "interactive" and "headless." Just being aware of that boundary makes the right choice obvious.
Goal
Command
Behavior
Think through something
gemini
Starts the interactive REPL
Get just the answer
gemini -p "..."
Runs one turn and exits (non-interactive)
Feed standard input
cat file | gemini
Processes piped content
Run, then keep going
gemini -i "..."
Executes, then drops into interactive mode
Machine-process the result
gemini -p "..." -o json
Emits JSON
For automation, the keys are -p (--prompt) and -o (--output-format). -p returns a single turn to stdout without entering the REPL, and adding -o json gives you structured data that tools like jq can handle.
# Pull only the critical errors out of a logcat build.log | gemini -p "List up to 3 fatal errors from this log, each with a guessed cause"# Receive the result as JSON and pass it downstreamgemini -p "Summarize README.md in one sentence" -o json | jq -r '.response'
You pick the model with -m (--model). Aliases are provided: pro for complex reasoning, flash as a speed-and-quality balance, and flash-lite as the fastest for simple tasks. For batch work like triaging many logs, leaning on the flash family tightens both cost and latency.
# Push light classification tasks to the flash familycat access.log | gemini -m flash -p "Group requests by country and show the top 5"
✦
Thank you for reading this far.
Continue Reading
What follows includes implementation code, benchmarks, and practical content we hope you'll find useful. This site runs without ads — server and development costs are supported entirely by members like you. If it's been helpful, we'd be truly grateful for your support.
WHAT YOU'LL LEARN
✦When to use interactive vs headless mode (gemini -p / -o json), and how to decide before wiring it into CI
✦Concrete steps to keep automation safe and reproducible with session resume, GEMINI.md, and approval modes
✦Ready-to-run shell scripts that hand a git pre-push hook and log triage to Gemini CLI
Secure payment via Stripe · Cancel anytime
✦
Unlock This Article
Get full access to the rest of this article. Buy once, read anytime. This site is ad-free — your support goes directly toward keeping it running.
Even after you close an interactive session, you can pick up where you left off. It's a quiet feature that pays off over time.
# Resume the most recent sessiongemini -r "latest"# Resume the latest session with a new instructiongemini -r "latest" "Check whether any type errors remain"# List sessions, then resume by IDgemini --list-sessionsgemini -r "abc123" "Finish this PR"
I lean on -r "latest" when I return in the afternoon to a plan I laid out in the morning. It removes the need to re-explain the premise, so the payoff grows with tasks that span a full day.
Pin project assumptions with GEMINI.md
Place a GEMINI.md at the project root and its contents load as context on every run. Put your coding conventions, directory layout, and operations to avoid there, and you stop re-stating background with each instruction.
# GEMINI.md- This repo is Next.js 16 (App Router) + TypeScript- Write Japanese comments in polite form- Always show a diff before editing anything under src/config/
If you edit GEMINI.md in an external editor, run /memory reload mid-session to re-read it. When you update MCP servers or custom commands, /mcp reload and /commands reload refresh those respectively.
Approval modes and sandboxing — the safety valve for automation
The more you delegate file edits and shell execution to the agent, the more the design question "how much do I auto-allow?" matters. Gemini CLI lets you choose that granularity with --approval-mode.
Mode
Meaning
Good for
default
Asks for confirmation on every change
Hands-on work in an unfamiliar repo
auto_edit
Auto-applies edits, confirms execution
Edit-heavy iterative work
plan
Presents a plan without executing
Reviewing direction before starting
yolo
Auto-approves everything
Throwaway environments and CI (sandbox required)
yolo is powerful, but used carelessly it invites irreversible changes. If you run with auto-approval, pair it with -s (--sandbox) to confine it to an isolated environment. Gemini CLI also has Checkpointing, which automatically snapshots project state before the AI modifies files — so an unexpected edit still leaves you room to rewind.
My split is simple: default when experimenting locally, plan when I want to settle direction first, and --approval-mode=yolo --sandbox only where no human is watching, such as CI.
Wire it into your shell and CI — working scripts
Bundle these pieces together and you get automation that holds up in practice. Here's a git hook that reviews the diff before a push.
#!/bin/bash# .git/hooks/pre-pushset -euo pipefailDIFF="$(git diff origin/main...HEAD)"if [ -z "$DIFF" ]; then exit 0fiREVIEW="$(printf '%s' "$DIFF" | gemini -m flash -p \ "If this diff has a security concern or an obvious bug, cite the lines and note it briefly. If it's clean, reply just OK")"echo "----- Gemini review -----"echo "$REVIEW"echo "-------------------------"# Anything other than OK nudges the human to look (no hard block)if ! printf '%s' "$REVIEW" | grep -q "OK"; then echo "⚠️ There are notes. Please review before pushing."fi
In CI, hold to three things: non-interactive, API-key auth, and JSON output. Below, a failing test log is summarized down to the essentials for the job output.
#!/bin/bash# ci-summarize-failure.shset -euo pipefailnpm test 2>&1 | tee test.log || trueSUMMARY="$(cat test.log | gemini -m flash -o json -p \ "Give up to 3 root causes of the test failures with a fix hint each. Put prose in the JSON response field" \ | jq -r '.response')"echo "::group::Test failure summary"echo "$SUMMARY"echo "::endgroup::"
The point is not to let Gemini's judgment fail the job. It outputs material to help a human decide, while the final pass/fail stays with the test results themselves. Not handing over too much authority is, in my experience, what keeps automation running over the long haul.
Extend its reach with MCP servers and extensions
Gemini CLI supports the Model Context Protocol (MCP), letting you add external tools as hands and feet for the CLI. Configuration is done through subcommands.
# Add a stdio-based MCP servergemini mcp add github npx -y @modelcontextprotocol/server-github# Add an HTTP-based servergemini mcp add api-server http://localhost:3000 --transport http# List registered serversgemini mcp list
With extensions, you can distribute and install several settings and tools together.
gemini extensions install https://github.com/user/my-extensiongemini extensions list
Lessons from actually running it
Running Dolice Labs' several sites as an indie developer, it's easy to decide how much to hand the AI based on what feels nice. But once I embedded it, what actually mattered was the design of the constraints.
Since switching to headless execution, my morning log check has gotten noticeably shorter than the manual version. The numbers shift by environment, but the biggest change is that the task shifted from "reading" to "receiving the key points." On the other side, I once ran yolo without a sandbox and got a scare. Ever since, auto-approval and sandboxing go together, always.
Another realization was how much matching the model to the task pays off. Running light work like classification or summarization on pro inflates both latency and cost; leaning on the flash family alone changed how it felt. When you get stuck on an error, troubleshooting Gemini CLI should help you narrow it down.
Gemini CLI, I've come to feel, shows its real worth less through the comfort of conversation and more when it works quietly as one part in your shell. Start by replacing a single log-triage step with gemini -p, and let it settle into your workflow from there. That slower path is, I think, the surer one.
I'm still in the middle of my own trial and error. Thank you for reading — I'd be glad to keep learning alongside you, hands on the keyboard.
Share
Thank You for Reading
Gemini Lab is ad-free, supported entirely by members like you. We publish practical guides daily with implementation code, benchmarks, and production-ready patterns. If you've found it useful, we'd love to have you on board.