Gemini API CLI Official Guide (Part 2): Keyless ADC, OAuth Scope Troubleshooting & User Tier Economics A developer published a second-part guide to the Gemini API CLI (v0.4.6) documenting keyless OAuth via Application Default Credentials, where short-lived bearer tokens are minted from existing identity and paired with an explicit x-goog-user-project header to attribute quota and billing to a designated GCP project. The guide also troubleshoots HTTP 403 OAuth scope errors observed at runtime and clarifies that Google AI Pro/Ultra consumer subscriptions do not make Developer API calls free, since the API bills against a GCP project rather than a Google Account. Source inspection of the release found no native ADC discovery or token auto-refresh, so credentials must be supplied via GEMINI_ACCESS_TOKEN or --access-token and injected through environment variables rather than command-line flags. Verified baseline : 2026-11-14 Asia/Taipei, UTC+8 on macOS Apple Silicon ts-m1 , gemini-api 0.4.6 , plus our 2026-11-15 live execution on gde-jimmyliao-redeem summarized in Section 10. Runtime HTTP 403 scope diagnostics and Paid Tier live execution are observed tool outputs; pricing, quota, and consumer migration boundaries come directly from official Google documentation. 📚 Series Navigation - 📘 Part 1 Dev.to : https://dev.to/jimmyliao/gemini-api-cli-official-guide-part-1-giving-your-ai-agent-a-stateless-multimodal-cli-toolbox-36p3 https://dev.to/jimmyliao/gemini-api-cli-official-guide-part-1-giving-your-ai-agent-a-stateless-multimodal-cli-toolbox-36p3 - 📝 Part 1 Substack : https://memo.jimmyliao.net/p/gemini-api-cli-part-1-agent-api https://memo.jimmyliao.net/p/gemini-api-cli-part-1-agent-api - 🇹🇼 Part 2 Substack, Traditional Chinese : https://memo.jimmyliao.net/p/gemini-api-cli-part-2keyless-adcscope https://memo.jimmyliao.net/p/gemini-api-cli-part-2keyless-adcscope - ▶️ YouTube 16:9 Walkthrough Part 1 : https://youtu.be/Rb5ij419w2Y https://youtu.be/Rb5ij419w2Y - ⚡ YouTube Shorts Part 1 : https://youtube.com/shorts/82-Z Jq-ezQ https://youtube.com/shorts/82-Z Jq-ezQ Part 1 https://dev.to/jimmyliao/gemini-api-cli-official-guide-part-1-giving-your-ai-agent-a-stateless-multimodal-cli-toolbox-36p3 introduced the standalone multimodal CLI. Once AI agents operate across laptops, containers, and CI runners, two architectural questions immediately arise: AIza API keys on disk while attributing every request cleanly to a designated GCP project? Keyless OAuth answers the first question by minting short-lived bearer access tokens from your existing identity and attaching an explicit quota project header. Importantly, keyless does not mean credential-less : local ADC still stores an underlying refresh credential, short-lived bearer tokens remain secrets, and OAuth never bypasses IAM roles, API enablement, or Cloud Billing. A second widespread misconception is "I pay for Google AI Pro / Ultra, so logging in with that Google account makes Gemini API calls free." Your Google Account is an identity; Google One / Antigravity is a consumer subscription pool ; the Developer API generativelanguage.googleapis.com belongs to a GCP project / Cloud Billing pool . Even promotional or GDE credits must be checked per billing account, eligible SKU, and expiration date. Primary evidence lives in experiments/03-part2-keyless-adc/results.md , experiments/04-tier-limits-and-errors/tier-research.md , and gde-feedback/upstream-issues-draft.md . v0.4.6 Implements Keyless OAuth To verify exact release behavior rather than relying on an earlier snapshot, we inspected four source files directly in tag v0.4.6 : | Source File v0.4.6 | Observed Responsibility & Limitation | |---|---| | internal/cli/auth.go | runAuthLoginCmd persists an existing API key or access-token string via config.StoreSecret / config.SaveConfig ; it never launches a browser OAuth flow or acquires refresh credentials. | | internal/config/config.go | SecurityConfig.AccessToken maps to YAML access token across flags, env vars, OS Keychain, and ~/.config/gemini-api/config.yaml not config.json . | | internal/cli/configure.go | runConfigureCmd writes credentials and global parameters including user-project locally. | | internal/client/client.go | BuildGlobalSecurity selects API key or access token; buildGlobalOptions maps user-project to sdk.WithUserProject . No native ADC discovery or token auto-refresh source exists here yet. | GEMINI ACCESS TOKEN / --access-token supplies the bearer credential who is calling , whereas --user-project sets the x-goog-user-project header which GCP project owns quota & billing . Never pass tokens on the command line where process inspection ps can read them—inject via subprocess environment variables instead. General credential precedence follows flag - environment - Keychain - config , and the Go client picks a complete explicit credential over fallback paths. Therefore our wrapper unsets inherited GEMINI API KEY variables before injecting a fresh ADC access token. Merely setting GOOGLE APPLICATION CREDENTIALS does not make v0.4.6 discover or refresh ADC natively. See OAuth quickstart https://aistudio.google.com/docs/oauth and API CLI docs https://aistudio.google.com/docs/cli . ts-m1 : HTTP 403 ACCESS TOKEN SCOPE INSUFFICIENT On ts-m1 , the active gcloud/ADC identity sjliao@gmail.com authorized user , quota project id: leapcore-dev held cloud-platform , sqlservice.login , userinfo.email , email , and openid —but lacked https://www.googleapis.com/auth/generative-language : | Live Call Tested | Process Exit | HTTP / Error Reason | Engineering Conclusion | |---|---|---|---| | models list no project header | 3 | 403 ACCESS TOKEN SCOPE INSUFFICIENT | Default Cloud ADC token lacks generative-language scope | | models list --user-project gdg-kc-465418 | 3 | Same | Switching --user-project cannot fix a token scope gap | | generate with gdg-kc-465418 | 3 | 403 PERMISSION DENIED / same reason | Zero inference response or usage incurred | | Wrapper generate with leapcore-dev | 3 | Same | billingEnabled=true cannot compensate for missing OAuth scope | gcloud auth application-default login --scopes="https://www.googleapis.com/auth/cloud-platform,https://www.googleapis.com/auth/generative-language,https://www.googleapis.com/auth/generative-language.retriever,https://www.googleapis.com/auth/userinfo.email,openid" Note why all of those scopes appear: the official /docs/oauth guide demonstrates cloud-platform + generative-language.retriever , whereas live generate calls explicitly requested https://www.googleapis.com/auth/generative-language . If Google's default gcloud client blocks sensitive scopes for your workspace or account, create a Desktop app OAuth Client in Google Cloud Console configuring your consent screen / test users per OAuth quickstart https://aistudio.google.com/docs/oauth , store client secret.json outside the repo, and pass --client-id-file