Dev.to AI πŸ€– Ai πŸ‘ 0 πŸ“– 9 min read

Gemini API CLI Official Guide (Part 1): Giving Your AI Agent a Stateless Multimodal CLI Toolbox

Verified environment: 2026-11-14 21:53 (Asia/Taipei, UTC+8) on macOS Apple Silicon (ts-m1), gemini-api 0.4.6 (supplemented by our 2026-11-15 live Paid Tier run documented in Section 7). Built for both international devel

Verified environment: 2026-11-14 21:53 (Asia/Taipei, UTC+8) on macOS Apple Silicon (ts-m1), gemini-api 0.4.6 (supplemented by our 2026-11-15 live Paid Tier run documented in Section 7). Built for both international developers (Dev.to) and the Taiwan / APAC developer community & GDE workshops.

🎬 Video & Bilingual Navigation

1. Introduction & the 2026 CLI Landscape Shift

June 18, 2026 marks a watershed moment for Google's individual developer CLI entry points: gemini-cli consumer access for free personal accounts and Google AI Pro/Ultra (Google One) plans transitioned to Antigravity CLI (agy). That transition applies to specific personal/consumer account scopes and should not be oversimplified as every gemini-cli mode or enterprise/paid API path disappearing overnight. See the official Google blog announcement for the exact scope.

Developers can now adopt a clean two-track architecture:

  • agy (or Codex / Claude Code) as the Agent Brain & Host: handles reasoning, planning, file edits, and long-horizon coding tasks.
  • gemini-api as the Stateless Multimodal CLI Toolbox: exposes image generation, video generation, multi-speaker TTS, music composition, transcription, and server-side Managed Agents over shell primitives. Look at the official repository (google-gemini/gemini-api-cli) to see how it is specifically positioned to equip any shell-capable agent with Gemini models.

Here, stateless means the CLI binary itself does not maintain hidden local chat history between runs; the underlying Interactions API can still persist server-side interactions, resume via --previous-interaction-id, or run background jobs. Mistaking "stateless CLI" for "no server-side state exists" leads to misdesigning multi-turn media pipelines.

2. Installation & Standard Authentication

gemini-api ships as a standalone Go binary. On macOS or Linux, install it using the official installer script:

curl -fsSL https://raw.githubusercontent.com/google-gemini/gemini-api-cli/main/scripts/install.sh | bash
command -v gemini-api
gemini-api --version

On ts-m1 (Darwin / arm64), the installer skipped /usr/local/bin (non-writable) and installed /Users/jimmyliao/.local/bin/gemini-api (v0.4.6; build timestamp 2026-11-11 02:46:39 Asia/Taipei). Ensure $HOME/.local/bin is on your PATH:

export PATH="$HOME/.local/bin:$PATH"

Because latest tracks newer releases over time, pin GEMINI_VERSION in CI per the official CLI installation docs.

For standard authentication, use either an environment variable or interactive configuration (choose one; no need to mix both):

export GEMINI_API_KEY="YOUR_API_KEY"
# OR interactive OS Keychain storage:
gemini-api configure
gemini-api whoami

Note that configure stores secrets in your OS Keychain, whereas --no-keyring / GEMINI_NO_KEYRING=true alters secret resolution and should not be casually enabled without understanding the boundary. In our clean isolation harness, every subshell explicitly unset GEMINI_API_KEY / GEMINI_ACCESS_TOKEN and exported GEMINI_NO_KEYRING=true; gemini-api whoami reported both credentials [unset] and API version v1beta. Crucially, whoami inspects local configuration sourcesβ€”it does not prove remote API entitlement or quota. See experiments/01-cli-introspection/results.md for the full capture.

3. Why Is This CLI Built for AI Agents?

AI agents routinely trip over stale CLI flags, dump raw base64 media into context windows, or hang forever on interactive prompts. gemini-api avoids those traps with machine-discoverable schemas and direct file I/O.

First, probing the documentation page itself via curl -sS -I https://aistudio.google.com/docs/cli returns:

content-type: text/markdown; charset=utf-8
x-llms-txt: /llms.txt
link: </llms.txt>; rel="llms-txt", </llms-full.txt>; rel="llms-full-txt"

On the binary side, four introspection flags govern agent self-discovery:

gemini-api --usage                 # Complete KDL command tree
gemini-api generate --schema       # Request body JSON Schema
gemini-api agent run --schema
gemini-api generate "Test prompt" --dry-run -o json

Caveat from our v0.4.6 introspection: --schema is not uniform across every subcommand. generate, image, video, and agent run succeeded, while analyze, tts, and transcribe returned exit code 2 (unknown flag: --schema). Inspect each subcommand's --help first, and check agent run --schema whenever you need full request body fidelity.

Dry-run redaction was also verified: passing a synthetic dummy --api-key outputs "X-Goog-Api-Key": ["[REDACTED]"]. Note carefully that --dry-run validates local request constructionβ€”it does not verify server model access, billing, or IAM permissions.

While the CLI supports both JSON and TOON structured output, gemini-api v0.4.6 always emits a JSON request envelope under --dry-run:

{"dry_run":true,"request":{"method":"POST","url":"https://generativelanguage.googleapis.com/v1beta/interactions","headers":{"Accept":["text/event-stream"],"Content-Type":["application/json"],"User-Agent":["google-genai-cli/0.4.6 gl-go/go1.26.10"]},"body":{"input":"Test prompt","model":"gemini-3.8-flash","stream":true}}}

Built-in --jq also has a quirk under --dry-run: running generate "Test prompt" --dry-run --jq '.body.model' still prints the full envelope (and flips stream to false). Pipe -o json into external jq instead when filtering dry-run payloads:

gemini-api generate "Test prompt" --dry-run -o json | jq -r '.request.body.model'

Full dummy-key dry-run traces and HTTP header checks are archived in experiments/02-part1-standard-workflows/sample-dry-runs.md.

4. Core Commands & Multimodal Primitives

Using synthetic local fixtures (input.txt 64 bytes, silence.wav 0.1s 16 kHz mono PCM), all six core commands succeeded cleanly under --dry-run (exit code 0):

cd experiments/02-part1-standard-workflows
gemini-api generate "Test prompt" --dry-run --output-format json
gemini-api analyze -i input.txt "Summarize" --dry-run
gemini-api image "Minimalist cloud database icon" --out /tmp/gapi-test.jpg --dry-run
gemini-api tts "Welcome to the Taiwan developer community" --out voice.wav --dry-run
gemini-api transcribe -i silence.wav --out transcript.md --dry-run
gemini-api video "A cloud above Taipei" --out cloud.mp4 --dry-run

Every subcommand targets POST https://generativelanguage.googleapis.com/v1beta/interactions. Understanding how their JSON bodies differ explains how to wire multimodal pipelines:

Command Default Model (v0.4.6) Key Request Payload Observation
generate gemini-3.8-flash input string, stream:true
analyze gemini-3.8-flash user_input.content array containing text/media + prompt, store:false, stream:false
image gemini-nano-banana-2.1 response_format:{"type":"image"}, stream:false
tts gemini-3.8-flash-tts response_format.type:audio, speech_config:[{"voice":"Kore"}], store:false
transcribe gemini-3.5-transcribe audio/wav input, transcription_config.mode.type:verbatim, diarization & word timestamps
video gemini-omni-1.2-flash response_format.type:video, background:true, stream:false

File bytes never bloat agent context on --dry-run: analyze summarizes files as "text":"<bytes:64>" and audio as "data":"<bytes:3244>". Abbreviated TTS request body observed on v0.4.6:

{
  "generation_config": {"speech_config": [{"voice": "Kore"}]},
  "input": [{"content": [{"text": "Welcome to the Taiwan developer community", "type": "text"}], "type": "user_input"}],
  "model": "gemini-3.8-flash-tts",
  "response_format": {"type": "audio"},
  "store": false,
  "stream": false
}

Output handling flags such as --out remain client-side and stay out of the HTTP body. Per --help, tts outputs 24 kHz mono PCM WAV (adjusting .mp3 targets back to .wav), transcribe supports md, text, json, and srt, and video waits on background completion unless --async is passed.

4.1 End-to-End Scenario (Part 1 Perspective): 6-Step 9:16 AI Reels Pipeline

Our running scenarioβ€”"Understand in 15 Seconds Why AI Agents Need a Multimodal CLI Toolbox"β€”chains these primitives into a version-controlled pipeline:

  1. Storyboard: generate --stdin creates the 3-scene 9:16 breakdown.
  2. Visual Keyframes: image --aspect-ratio 9:16 --image-size 1K generates Scene 1, followed by image -i scene1-keyframe.jpg to preserve character and visual style into Scene 2 (--previous-interaction-id can also continue live server interactions).
  3. Video Motion: video --aspect-ratio 9:16 --resolution 720p -i turns the approved Scene 1 keyframe into motion (background:true).
  4. Dual-Speaker Voiceover: tts --multi-speaker "Host=Kore,CoHost=Puck".
  5. BGM & Subtitles: music + transcribe --format srt.
  6. Safe-Zone & Alignment QA: analyze inspects the 9:16 composition against storyboard.json.

See examples/reels-storyboard-pipeline/run-reels-pipeline.sh and the verbatim trace examples/reels-storyboard-pipeline/dry-run-trace.md.

Runnable Part 1 Example (sample-part1-reels-primitives.sh)

Run directly from the workspace root (examples/part1-multimodal-cli/sample-part1-reels-primitives.sh); synthetic fixtures/* validate MIME handling without incurring API charges:

bash <<'PART_SAMPLE'
(
set +x
set -euo pipefail
cd examples/part1-multimodal-cli
unset GEMINI_API_KEY GEMINI_ACCESS_TOKEN GEMINI_ENVIRONMENT_KEY GEMINI_USER_PROJECT
export GEMINI_NO_KEYRING=true
R=../reels-storyboard-pipeline
echo 'Step: offline schema discovery' >&2
gemini-api video --schema --dry-run </dev/null
echo 'Step: storyboard, keyframes, and style continuity (synthetic MIME fixtures)' >&2
gemini-api generate --stream=false --stdin 'Generate a 3-scene storyboard from the brief:' --dry-run < "$R/storyboard-brief.txt"
gemini-api image 'Taipei tech Reels keyframe' --aspect-ratio 9:16 --image-size 1K --output-mime-type image/jpeg --out /tmp/part1-scene1.jpg --dry-run </dev/null
gemini-api image 'Continue Scene 1 style' -i "$R/fixtures/scene1-keyframe.png" --aspect-ratio 9:16 --image-size 1K --output-mime-type image/jpeg --out /tmp/part1-scene2.jpg --dry-run </dev/null
echo 'Step: video, dual-speaker voiceover, music, and captions' >&2
gemini-api video 'Slow camera push on keyframe' --aspect-ratio 9:16 --resolution 720p -i "$R/fixtures/scene1-keyframe.png" --out /tmp/part1-scene1.mp4 --dry-run </dev/null
gemini-api tts --multi-speaker "Host=Kore,CoHost=Puck" -f "$R/dialogue.txt" --out /tmp/part1-voice.wav --dry-run </dev/null
gemini-api music 'Tech short background music' --out /tmp/part1-music.wav --dry-run </dev/null
gemini-api transcribe --format srt -i "$R/fixtures/voiceover-sample.wav" --out /tmp/part1-captions.srt --dry-run </dev/null
echo 'Step: keyframe & storyboard QA' >&2
gemini-api analyze -i "$R/fixtures/scene1-keyframe.png" -i "$R/storyboard.json" 'Check Reels safe-zone and storyboard alignment' --dry-run </dev/null
)
PART_SAMPLE

5. Managed Agents & Self-Hosted Agent Substrate Outlook

Beyond direct model primitives, gemini-api can launch server-managed Interactions API agents:

gemini-api agent run "Compare WebRTC SFU architectures" \
  --agent deep-research-preview-04-2026 \
  --background --stream=false --dry-run

Inspecting the upstream source snapshot (2030ff1) under internal/sdk/models/interactions/ reveals several typed agent configurations alongside Deep Research:

  • AntigravityAgentConfig (type:"antigravity", model, max_total_tokens)
  • CodeMenderAgentConfig (type:"code-mender", FIND/FIX request & session controls)
  • DynamicAgentConfig (type:"dynamic")

Important boundary: SDK type definitions do not guarantee account entitlement, nor does logging into agy locally automatically authorize API Managed Agents.

Similarly, the Self-Hosted Environments docs and Agent Substrate example (ate-gemini) outline running tool execution on your own Kubernetes/gVisor compute using either environments connect (single worker) or environments poll + environments serve (short-lived lease tokens so sandboxes never hold project API keys). Remember the security division: ate-gemini validates component mTLS, while multi-tenant user authentication and ACL enforcement remain your application's responsibility.

6. Preview of Part 2: Keyless OAuth (ADC) & User Tier Boundaries

Want to stop distributing plaintext GEMINI_API_KEY secrets across laptops and containers? In Part 2, we inspect the Keyless OAuth path (GEMINI_ACCESS_TOKEN + --user-project), troubleshoot ACCESS_TOKEN_SCOPE_INSUFFICIENT, ship a safe wrapper (bin/gapi-adc), and map Free Tier, Paid Tier 1–3, and Google AI Pro/Ultra boundaries.

7. Live Verification Addendum (2026-11-15): Full Β§4.1 Reels Run & Cost Ledger

Following the --dry-run validation above, we executed all 8 Β§4.1 multimodal steps live against project gde-jimmyliao-redeem (Paid Tier) inside tmux (2026-11-15 00:20:54 β†’ 00:24:23 Asia/Taipei) and assembled the final 9:16 video with burned-in bilingual subtitles using local ffmpeg 8.1:

  • Zero fallbacks triggered: gemini-3.8-flash (storyboard & QA), gemini-nano-banana-2.1 (Scene 1 & Scene 2 768Γ—1376 keyframes with crisp Traditional Chinese + English labels), gemini-omni-1.2-flash (5.03s 720p video at $0.3527), gemini-3.8-flash-tts (9.44s dual-speaker voiceover), lyria-3.5 (159.48s track), and gemini-3.5-transcribe all succeeded on the first call (Exit 0).
  • Measured calls & cost: 8 paid calls + 4 read-only $0 agent status polls, consuming 44,934 tokens (4,506 input + 35,407 output + 5,021 thought) for a calculated total of $0.54853125 USD (~$0.5485). Keyframe-first gating saved ~$0.705 USD by skipping redundant video renders on Scenes 2 & 3.
  • Two practical quirks caught live: gemini-api music --out bgm.wav wrote audio/mpeg (MP3, "extension_mismatch": true) instead of uncompressed WAV, and gemini-3.5-transcribe converted spoken Mandarin into Simplified Chinese and misheard "ε…ˆι©—ι¦–εΉ€" (verify keyframes first) as "ε…ˆιͺŒζ‰‹ι’ˆ"β€”reinforcing why subtitle review matters before publishing.

Full per-call formulas and verified deliverables are in experiments/06-live-execution-and-cost-log/cost-and-call-ledger.md and examples/reels-storyboard-pipeline/output/final-reel.mp4.

πŸ“° Read the original article on Dev.to AI

Originally published by Dev.to AI. Aggregated on AIWithGhost for educational purposes β€” full credit and traffic to the original publisher.