gemini-api-cli
Call the Gemini API from the shell with gemini-api. Use for media generation (images, TTS, music, video), file and YouTube analysis, audio/video transcription, Deep Research, and sandboxed agents.
Try your first task
A source-grounded starter task has not been verified for this skill yet.
SKILL.md
name: gemini-api-clidescription: Call the Gemini API from the shell with gemini-api. Use for media generation (images, TTS, music, video), file and YouTube analysis, audio/video transcription, Deep Research, and sandboxed agents.The gemini-api CLI exposes every Gemini API resource as a shell subcommand. Compared to curl: media and transcription commands decode output to disk and print only the file path, -i attaches local files or files/<id> URIs, --jq extracts fields in-process (raw strings by default, no external jq), --dry-run previews redacted HTTP requests offline, and list endpoints auto-paginate with --all (cap pages with --max-pages N; --page-size sets server page size).
CLI vs SDK
CLI for shell work, SDK for application code. Use gemini-api from terminals, scripts, and CI jobs to generate media files, analyze local PDFs or recordings, run Deep Research, and manage agent sandboxes (gemini-api is a stateless Gemini API client, distinct from the interactive @google/gemini-cli coding agent). Use the Google GenAI SDKs (gemini-api-dev, gemini-live-api-dev) when calls live inside application source or need bidirectional Live API WebSockets.
Install and auth
# macOS / Linux (set GEMINI_VERSION=<tag> to pin a release)
curl -fsSL https://raw.githubusercontent.com/google-gemini/gemini-api-cli/main/scripts/install.sh | bash
Credentials resolve in order (first match wins): --api-key / --access-token flags, GEMINI_API_KEY / GEMINI_ACCESS_TOKEN env vars, the OS keychain, then ~/.config/gemini-api/config.yaml.
- Env var (agents and CI):
export GEMINI_API_KEY="..." - Workstation key:
gemini-api configure --api-key "..."saves to the OS keychain. Pass--no-keyringorGEMINI_NO_KEYRING=1on headless Linux to useconfig.yaml;gemini-api auth logoutclears stored keys. - Active auth check:
gemini-api whoami(add-o jsonfor JSON) prints masked credentials and the winning source.
The #1 auth trap: an exported
GEMINI_API_KEYoverrides credentials stored in the keychain orconfig.yaml, billing whichever project that env var belongs to. Checkgemini-api whoamito see which source won, or runenv -u GEMINI_API_KEY gemini-api ...to ignore the env var.
Command structure
gemini-api <intent> [prompt] [flags] # task commands with model and modality presets
gemini-api <resource> <action> [flags] # REST resource groups
Run gemini-api --help to list commands, or <subcommand> --help for flags and examples (--usage dumps a 45 KB KDL spec, so stick to --help to save context).
| Command | Key flags / actions | Default model & behavior |
|---|---|---|
generate [prompt] | -m, -i, --stdin, --system, --previous-interaction-id, --stream=false, --body | gemini-3.8-flash; streams text deltas to stdout |
image [prompt] | -m, -i, --aspect-ratio, --image-size (512..4K), --previous-interaction-id, --out, --body | gemini-nano-banana-2.1; writes image, prints path |
tts [text] | -m, -f, --stdin, -v/--voice (default Kore), --multi-speaker, --language, --out | gemini-3.8-flash-tts; writes 24 kHz WAV, prints path (unstored) |
music [prompt] | -m, -f, --stdin, --out, --body | lyria-3.5; writes audio track, prints path |
video [prompt] | -m, -i, --aspect-ratio, --resolution (360p..4k), --previous-interaction-id, --async, --resume, --out, --body | gemini-omni-1.1-flash; polls until done, writes MP4, prints path (upscale via --body) |
analyze [question] | -i (required, repeatable), --stdin, --system, -m | gemini-3.8-flash; answers over PDFs, media, CSV/text, YouTube URLs (unstored) |
transcribe | -m, -i (required, repeatable), --format (md, text, json, srt), --no-speakers, --no-timestamps, --out | gemini-3.5-transcribe (audio; 30m speaker/timestamp cap) or gemini-3.8-flash (video); writes --out (or ./transcript-*), prints path (unstored) |
agent | run, status, cancel, delete-interaction; create, list, get, delete | Runs models or managed agents; manages custom agent definitions |
files | upload [--wait], list, get, generated-files-list, register, delete | Uploads reusable files/<id> URIs (48h TTL; up to 2 GB, 50 MB PDFs) |
models | (bare), list [--all], get <id> | Bare models prints an offline catalog; list and get query the live API |
environments | create, list, get, delete, files (list, upload, download), connect, poll, serve | Remote sandboxes and workspace snapshots (credentials, webhooks, triggers for agent infra) |
Model selection: use gemini-3.8-flash (default), gemini-4-argon (hard reasoning and coding), or gemini-3.5-flash-lite (high throughput); for images, gemini-nano-banana-2.1, gemini-3.1-flash-lite-image, or gemini-3-pro-image. Avoid deprecated gemini-2.5-*, gemini-2.0-*, and gemini-1.5-* models.
Global flags
| Flag | Purpose |
|---|---|
-o, --output-format | pretty (default), json, toon, yaml, table |
-q, --jq | Filter JSON output with a built-in jq expression (--raw-output is true by default) |
--agent-mode | Compact TOON on stdout and structured JSON errors on stderr |
--no-interactive | Disable prompts, TUI forms, and explore |
--dry-run | Validate inputs and preview redacted HTTP requests offline (human preview on stderr; -o json or --jq writes JSON to stdout) |
-d, --debug | Log HTTP request and response details to stderr |
Exit codes: 0 ok, 1 runtime or API error (video polling, image/music, tts, transcribe, and analyze also exit 1 on failed/incomplete runs; generate, agent run, and agent status exit 0 and report state in .status), 2 usage or validation error, 3 auth error. See gemini-api --help-global for --server-url and auth flags; pagination flags (--all/-a, --max-pages, --page-size, --page-token) live on <resource> list --help.
Output
Media (image, tts, music, video) and transcribe write files locally and print only the file path on stdout (--out on media commands rewrites the file extension to match the returned MIME type, e.g. .png for default image unless --body '{"response_format": {"mime_type": "image/jpeg"}}' is passed). Adding -o json still writes the file and prints metadata: {kind, path, size_bytes, mime_type, response_id, status} on image/music/video, {model, path, mime_type, size_bytes, sample_rate, channels} on tts, and {model, format, results: [{input, path, size_bytes, model, mime_type}]} on transcribe.
Streaming and JSON shape: generate and agent run stream plain reply text by default, so -o json alone emits {"data": ...} NDJSON SSE events. Pass --stream=false -o json for one JSON object {id, status, steps, usage} (bare --stream=false prints aligned key: value metadata; --background on agent run disables streaming, and --jq disables streaming unless -o or GEMINI_OUTPUT_FORMAT is set, so omit -o json or add --stream=false when filtering a full response with --jq). Reply text lives under .steps[] model_output (see agent status below) rather than .candidates[]. On paginated list commands, --jq runs per page envelope (.models[]?.name, .agents[]?.id).
Input
-i/--inputattaches media and documents ongenerate,image,video,analyze,transcribe, andagent run(repeatable). Accepts local paths up to ~14 MB (20 MB base64 cap),files/<id>URIs, or YouTube URLs (not supported ontranscribe). Upload larger or reused files once withgemini-api files upload <path> --wait.-f/--filereads prompt text from a file onttsandmusic. Piped text needs--stdin: when piping plain text intogenerate,image,music, orvideo, pass--stdinor piped input gets parsed as a JSON--body;analyzeandttsignore piped stdin unless--stdinis set (agent runhas no--stdin, so piped stdin is always JSON--body).--bodypasses raw Gemini API JSON inline, from@file.json, or via@-(merges with flags; exits 2 on duplicate keys). Use it forresponse_formatschemas,tools(google_search,code_execution,url_context, function declarations),generation_config,environment, orstore.- Don't dump
--schemaraw: it prints ~92 KB of minified JSON and exits before--jqruns. Pipe it tojq:gemini-api generate --schema | jq '."$defs".ModelInteraction.properties | keys'
Media, analysis, and transcription
HERO=$(gemini-api image "Isometric cloud database icon" --aspect-ratio 16:9 --image-size 2K \
--body '{"response_format": {"mime_type": "image/jpeg"}}' --out ./hero.jpg)
gemini-api image "Add warm sunset lighting" -i "$HERO" \
--body '{"response_format": {"mime_type": "image/jpeg"}}' --out ./hero-sunset.jpg
gemini-api tts "Alice: Ready to ship? Bob: Checks are green." \
--multi-speaker "Alice=Kore,Bob=Puck" --out ./dialogue.wav
VID_ID=$(gemini-api video "Aerial coastal cliffs at sunrise" --aspect-ratio 16:9 --resolution 1080p --async)
gemini-api video --resume "$VID_ID" --out ./cliffs.mp4
FILE_URI=$(gemini-api files upload ./call.mp4 --wait) # prints files/<id>
gemini-api analyze -i "$FILE_URI" "List action items with owners and timestamps."
gemini-api transcribe -i "$FILE_URI" --format srt --out ./call.srt
Managed agents and sandboxes
deep-research-preview-04-2026anddeep-research-max-preview-04-2026: run with--backgroundand pollagent status.antigravity-preview-09-2026(Linux sandbox with Bash, Python, Node, file ops, and web search): pass"environment": "remote"(new sandbox),"environment": "<env_id>"(existing sandbox), or"environment": {"type": "remote", ...}in--body(top-levelenvironment_idis output-only and exits 2).
ID boundary: agent status, agent cancel, and agent delete-interaction take a run ID (v1_...). agent create, agent get, agent list, and agent delete manage custom agents only (built-in agent IDs are listed in gemini-api agent run --help and live gemini-api models list, not the offline gemini-api models catalog; cap agent list and environments list with --page-size 10).
RUN_ID=$(gemini-api agent run "Compare WebRTC SFU architectures with primary sources." \
--agent deep-research-preview-04-2026 --background --jq '.id')
gemini-api agent status "$RUN_ID" --jq '.status' # queued | in_progress | requires_action | requires_continuation | completed | failed | cancelled | incomplete | budget_exceeded (exits 0)
gemini-api agent status "$RUN_ID" \
--jq '[.steps[]? | select(.type=="model_output") | .content[]? | select(.type=="text") | .text] | join("")'
ENV_ID=$(gemini-api agent run "Benchmark radix sort vs timsort in Python and write results.csv." \
--agent antigravity-preview-09-2026 --body '{"environment": "remote"}' --jq '.environment_id')
gemini-api environments files list -e "$ENV_ID" -r
gemini-api environments files download "$ENV_ID" results.csv --out ./results.csv
gemini-api agent create --id code-reviewer --base-agent antigravity-preview-09-2026 \
--system-instruction "Review diffs for race conditions and auth bugs."
Multi-turn and structured output
Calls store state server-side by default (store is true), so multi-turn chains only need --previous-interaction-id (system_instruction, tools, and generation_config apply per turn; setting store to false disables previous_interaction_id and background):
TURN1=$(gemini-api generate "Propose 2 indexing strategies for time-series logs." --jq '.id')
gemini-api generate "Compare them for write-heavy workloads." --previous-interaction-id "$TURN1"
Combine --stdin with --body for schema-constrained JSON output:
cat build.log | gemini-api generate "Extract unique compiler errors." --stdin --body '{
"response_format": {
"type": "text", "mime_type": "application/json",
"schema": {"type": "object", "properties": {"errors": {"type": "array", "items": {"type": "string"}}}, "required": ["errors"]}
},
"store": false
}'
Full CLI reference: aistudio.google.com/docs/cli.md; docs index: llms.txt.