Skip to content

[Bug]: Antigravity usage is a copy of the Gemini quota — wrong pools, and refresh breaks entirely without a local Gemini CLI install #9122

Closed

Description

@liuyifeng92

Version: Orca 1.4.143 (macOS arm64)

What happens: In the main process, the Antigravity rate-limit entry is literally const antigravity = { ...gemini, provider: "antigravity" } — there is no independent Antigravity fetch.

This causes two problems:

  1. Wrong data even when it works. fetchGeminiRateLimits calls cloudcode-pa.googleapis.com/v1internal:retrieveUserQuota with ideType: "GEMINI_CLI", so the segment shows Gemini CLI model buckets. Actual Antigravity plans have their own pools ("Gemini Models" and "Claude and GPT") with independent reset times.

  2. Refresh hard-depends on a local Gemini CLI install. When ~/.gemini/oauth_creds.json expires, tryRefreshTokenFromBundle → extractOAuthClientCredentials regex-extracts OAUTH_CLIENT_ID/SECRET from an installed @google/gemini-cli package (resolved via which gemini plus fallback paths). Antigravity users have no reason to have Gemini CLI installed, so the Antigravity segment shows "Token refresh failed" forever. Verified locally: the refresh token itself was still valid (a manual refresh returned HTTP 200); only the client-credential extraction failed.

Steps to reproduce:

  1. Use Antigravity CLI (agy) without @google/gemini-cli installed anywhere on the machine.
  2. Enable the Antigravity usage item in the Orca status bar (with Gemini CLI OAuth enabled in settings).
  3. Wait until the access token in ~/.gemini/oauth_creds.json expires.
  4. Every refresh now fails with "Token refresh failed", while other tools (e.g. CodexBar via agy) report Antigravity quota fine.

Suggested fix: Fetch Antigravity usage independently, using the Antigravity CLI's own credentials (~/.gemini/antigravity-cli/) or by shelling out to agy — CodexBar takes this approach and reliably reports both Antigravity pools. At minimum, decouple the Antigravity segment from the Gemini CLI binary requirement and surface a clearer error than "Token refresh failed".

Related: #7809 covers the status-bar visibility contract for this segment; this issue is about the data source itself.

Made with Orca 🐋

Activity

  1. MumuTW commented on Jul 21, 2026

    @MumuTW
    Contributor

    Reverse-engineered breakdown & root cause snippet

    Inspecting the main bundle (app.asar) confirms the exact logic handling readGeminiCredentials():

    const OAUTH_CREDS_PATH = path.join(os.homedir(), ".gemini", "oauth_creds.json");
    
    async function readGeminiCredentials() {
      try {
        const raw = await fs.readFile(OAUTH_CREDS_PATH, "utf-8");
        const parsed = JSON.parse(raw);
        if (parsed && typeof parsed === "object" && "access_token" in parsed 
            && typeof parsed.access_token === "string" 
            && "refresh_token" in parsed 
            && typeof parsed.refresh_token === "string" 
            && "expiry_date" in parsed 
            && typeof parsed.expiry_date === "number") {
          return parsed;
        }
        return null;
      } catch (err) {
        if (err && typeof err === "object" && "code" in err && err.code === "ENOENT") {
          return null;
        }
        throw err;
      }
    }

    When readGeminiCredentials() encounters ENOENT (since modern agy uses ~/.gemini/antigravity-cli/), it returns null, causing the main fetch loop to return:

    {
      provider: "gemini",
      session: null,
      weekly: null,
      updatedAt: Date.now(),
      error: "Gemini CLI credentials not found",
      status: "unavailable"
    }

    Updating readGeminiCredentials() to iterate over a list of candidate credential paths (such as ~/.gemini/antigravity-cli/auth.json alongside ~/.gemini/oauth_creds.json) would immediately prevent this ENOENT failure mode for Antigravity CLI users without requiring a legacy @google/gemini-cli installation.

  2. 8 remaining items

  3. yamogoon commented on Aug 12, 2026

    @yamogoon

    Still reproduces on macOS arm64 with Orca 1.4.180 and Antigravity CLI 1.1.12. agy is detected and works, and its state exists under ~/.gemini/antigravity-cli, but both Gemini and Antigravity status-bar entries show “Usage unavailable”.

    geminiCliOAuthEnabled is enabled, but Orca looks for ~/.gemini/oauth_creds.json; this machine has no such file because Gemini CLI 0.46.0 is configured for gemini-api-key. Google officially stopped serving individual/AI Pro/AI Ultra/free-tier accounts through Gemini CLI on June 18, 2026 and moved them to Antigravity CLI: google-gemini/gemini-cli#28017

    Removing Gemini CLI would not change the Antigravity result: Orca 1.4.180 still mirrors the Gemini fetch and does not read Antigravity’s native quota source. This now affects the normal supported migration path, rather than only machines with an expired or missing legacy credential.

  4. isairz commented on Aug 18, 2026

    @isairz

    Addressed in #11536: Antigravity usage is now fetched independently from the active local Agy LanguageServer, without relying on Gemini CLI OAuth. The status bar reports all four Agy quota buckets (Gemini and Claude/GPT, 5h and weekly), and the deprecated Gemini usage path is migrated to Agy.

  5. nerdy2quant commented on Aug 22, 2026

    @nerdy2quant

    Additional official confirmation: this is now a permanent product dependency problem, not merely a missing-credential fallback.

    Google announced that Gemini CLI would stop serving requests on June 18, 2026 for Google AI Pro / Ultra users and users of Gemini Code Assist for individuals, and directed those users to Antigravity CLI. The current Gemini CLI authentication documentation also carries an explicit banner that unpaid-tier and Google One users are being replaced by Antigravity CLI.

    That means geminiCliOAuthEnabled cannot remain a prerequisite for Antigravity usage on the normal consumer migration path. Antigravity quota discovery needs to use Agy's own local source, while Gemini CLI usage should be removed or clearly marked unavailable for affected plans.

    Official sources:

    The independent Agy LanguageServer approach in #11536 matches that transition and avoids coupling Antigravity quota visibility to a retired consumer Gemini CLI OAuth flow.

  6. nerdy2quant commented on Aug 22, 2026

    @nerdy2quant

    Product/UI request: after the consumer Gemini CLI transition, the Usage UI should present a single Antigravity provider with the Agy icon and Agy-native quota data. It should not render a separate Gemini CLI provider row or duplicate the same percentage under both Gemini and Antigravity.

    The Antigravity detail view can still name the native model-family buckets (for example, Gemini Models and Claude/GPT models), but those are quota buckets within Antigravity—not evidence that the retired Gemini CLI product has a separate live usage source or shares its quota.

    This would make the migration path unambiguous and prevent users from interpreting two identical rows as two independently tracked providers. The provider-removal and direct Agy quota design in #11536 appears to implement this direction.

  7. AmethystLiang commented on Aug 26, 2026

    @AmethystLiang
    Contributor

    Will get this resolved soon!

  8. isairz commented on Aug 27, 2026

    @isairz

    Thanks @AmethystLiang! I’ve refreshed #11536 against current main. It implements the direct host-local Agy LanguageServer approach discussed here, including all four quota buckets, migration away from the deprecated Gemini usage path, and live UI/full-suite validation. I’d appreciate your consideration and am happy to adapt it to the maintainers’ preferred direction.

  9. wekinu commented on Aug 27, 2026

    @wekinu

    Still reproduces on Windows — Google AI Pro (personal), post–Gemini CLI EOL

    Environment

    • Orca 1.4.188 (Windows x64)
    • Antigravity CLI agy 1.1.22 signed in as a personal Gmail with Google AI Pro
    • @google/gemini-cli 0.57.0 is installed; ~/.gemini/oauth_creds.json exists from a Gemini CLI OAuth attempt

    Status bar

    • Gemini: Refresh failed / Gemini project ID not found
    • Antigravity: Antigravity usage is not available. Orca reads it from the shared Google Code Assist quota, which could not be read right now.

    What we verified against Google’s API (same machine, live token from oauth_creds.json)

    POST https://cloudcode-pa.googleapis.com/v1internal:loadCodeAssist with ideType: "GEMINI_CLI" returns HTTP 200 but no cloudaicompanionProject. Response shape:

    • allowedTiers: standard-tier (userDefinedCloudaicompanionProject: true)
    • ineligibleTiers: free-tier with reasonCode: UNSUPPORTED_CLIENT and message directing individuals to Antigravity (https://antigravity.google)

    So Orca’s Gemini path correctly fails at project-ID resolution, and Antigravity then mirrors that failure (no independent Agy fetch yet). Re-auth / running one prompt does not fix the meter.

    Agent side works

    • agy interactive session shows the Pro account (e.g. signed in as Google AI Pro) and is usable for coding.
    • Only the Orca usage segments are broken for this consumer migration path.

    Ask
    Please prioritize merging the independent Agy LanguageServer quota path (#11536) — after Google’s June 18, 2026 cutover, personal AI Pro users cannot get a Code Assist project ID from the Gemini CLI client, so mirroring Gemini quota permanently shows “unavailable / refresh failed” even when Antigravity itself is healthy.

    Made with Orca 🐋

  10. Tauri-EPO commented on Sep 8, 2026

    @Tauri-EPO
    Contributor

    Windows data point (Orca 1.4.198, agy 1.1.27, Google AI Pro, 2026-09-08), posted in full on #16710: #16710 (comment)

    • agy stores its token in Windows Credential Manager (gemini:antigravity), not in a file under ~/.gemini/antigravity-cli.
    • With that token, retrieveUserQuotaSummary returns the real four Antigravity buckets (200).
    • The Gemini CLI token gets 403 on the same call, even with ideType: ANTIGRAVITY.
    • The local language server answers RetrieveUserQuotaSummary with 500 "You are not logged into Antigravity" while the same process completes turns normally.
  11. PabloGmez2K commented on Sep 16, 2026

    @PabloGmez2K

    Windows reproduction with current Gemini CLI credential storage

    I can reproduce a related failure on Windows with current CLI versions.

    Environment

    • Windows
    • Orca: 1.4.204
    • Antigravity CLI: 1.2.4
    • Gemini CLI: 0.60.0
    • Antigravity and Gemini CLI are both successfully authenticated with the same Google AI Pro account.

    What works

    Antigravity CLI works normally.

    Observed:

    Antigravity CLI 1.2.4
    Google AI Pro

    Gemini CLI also works normally after using "Sign in with Google".

    Observed:

    gemini --version
    0.60.0

    Both CLIs can successfully run prompts.

    What Orca shows

    Gemini usage:

    Usage unavailable
    Gemini CLI credentials not found

    Antigravity usage:

    Usage unavailable
    Antigravity usage is not available. Orca can only show shared Google Code Assist quota while a Gemini CLI sign-in is connected.

    The "Use Gemini CLI credentials" option is enabled in Orca settings.

    Important finding

    Orca expects the legacy credential file at:

    C:\Users<user>.gemini\oauth_creds.json

    But with Gemini CLI 0.60.0 that file does not exist.

    PowerShell check:

    Test-Path "$HOME.gemini\oauth_creds.json"

    Result:

    False

    The ~/.gemini directory exists, and Gemini CLI is authenticated and usable, but there is no oauth_creds.json file.

    I also confirmed that the following environment variables are not set:

    GEMINI_FORCE_ENCRYPTED_FILE_STORAGE
    GEMINI_FORCE_FILE_STORAGE

    This appears consistent with current Gemini CLI using its newer keychain / hybrid credential storage instead of the legacy OAuth JSON file.

    So this is not a missing-login problem: Gemini CLI is successfully authenticated, but Orca cannot discover the credentials used by the current CLI.

    Expected behavior

    1. Orca should support the current Gemini CLI credential storage instead of requiring the legacy oauth_creds.json file.
    2. Antigravity usage should preferably be fetched independently from agy / Antigravity credentials rather than depending on Gemini CLI usage mirroring.
    3. If Orca cannot read the current credential backend, the UI should report that specific incompatibility instead of saying "Gemini CLI credentials not found".

    I did not copy, modify, expose, or manually recreate any OAuth credentials while testing this.

  12. added a commit that references this issue on Sep 16, 2026
    47aaf44
  13. antoniomonteirojr commented on Sep 28, 2026

    @antoniomonteirojr

    Still reproduces on 1.4.215 (macOS arm64). Gemini CLI OAuth is now dead upstream for individual accounts, and the agy CLI runtime quota RPC works with a CSRF token that none of the open PRs can find

    Environment: Orca 1.4.215 (commit 3eb1adec), macOS arm64, agy 1.2.12 (Antigravity CLI, standalone; the Antigravity desktop app is not running), @google/gemini-cli 0.61.0 (Homebrew), personal Google account, geminiCliOAuthEnabled: true.

    Symptom: the Gemini status bar item shows an error and the Antigravity item shows "Antigravity usage is not available…". Both fail for the same reason, even though agy is running and signed in within an Orca pane.


    1. Why the Gemini path fails now: Google rejects the Gemini CLI client for individual accounts

    The bundle still does exactly what this issue describes (antigravity = { ...gemini, provider: 'antigravity' } when status is ok, otherwise the Ora/kra "not available" strings). Upstream of that, the Gemini fetch fails at the first step. With a valid, unexpired ~/.gemini/oauth_creds.json access token:

    POST https://cloudcode-pa.googleapis.com/v1internal:loadCodeAssist
    {"metadata":{"ideType":"GEMINI_CLI","pluginType":"GEMINI"}}
    

    returns no currentTier and no cloudaicompanionProject, only:

    {
      "allowedTiers": [{ "id": "standard-tier", "userDefinedCloudaicompanionProject": true, "isDefault": true, ... }],
      "ineligibleTiers": [{
        "reasonCode": "UNSUPPORTED_CLIENT",
        "reasonMessage": "This client is no longer supported for Gemini Code Assist for individuals. To continue using Gemini, please migrate to the Antigravity suite of products: https://antigravity.google",
        "tierId": "free-tier",
        "tierName": "Gemini Code Assist for individuals"
      }]
    }

    So N4() throws "Gemini project ID not found in API response". The OpenCode refresh split fallback does not apply, mea() returns status: 'error', and Ara() turns that into the Antigravity "could not be read right now" message.

    What I tried, all with the same UNSUPPORTED_CLIENT result:

    Token Host ideType
    Gemini CLI (oauth_creds.json) cloudcode-pa GEMINI_CLI, IDE_UNSPECIFIED (what gemini-cli 0.61 sends now), ANTIGRAVITY, JETSKI
    agy's live token (macOS keychain, svce=gemini, acct=antigravity, stored as go-keyring-base64:) cloudcode-pa and daily-cloudcode-pa ANTIGRAVITY

    With either token, retrieveUserQuota returns 403 SUBSCRIPTION_REQUIRED ("You do not have a valid license of this product… (#3501)") and fetchAvailableModels returns 403 The caller does not have permission. The server gates on the OAuth client, not on ideType.

    Takeaways for the fix:

    • For personal accounts the Gemini provider can no longer succeed. It should probably detect ineligibleTiers[].reasonCode === 'UNSUPPORTED_CLIENT' and report unavailable with a clear message ("Gemini CLI is no longer supported for individual Google accounts; usage is shown under Antigravity"), not a generic error.
    • Replaying agy's keychain token against the REST API (the approach in feat(rate-limits): fetch Antigravity usage from the CLI keychain session #21999) does not work for this account either. agy itself only talks to daily-cloudcode-pa.googleapis.com (streamGenerateContent, loadCodeAssist, fetchAvailableModels, generateContent in its log), and it clearly sends something that the plain REST replay does not.

    2. The runtime quota RPC works for the agy CLI, but it needs a CSRF token

    This confirms the RPC that @lalagogo2012 described earlier in this thread, with one important difference: on agy 1.2.12 the CSRF token is now mandatory.

    agy (no desktop app, no language_server_macos process) listens on two adjacent loopback ports (lsof -nP -a -p <agy pid> -iTCP -sTCP:LISTEN). Test matrix against /exa.language_server_pb.LanguageServerService/RetrieveUserQuotaSummary, POST, content-type: application/json, body {}:

    Port Scheme With x-codeium-csrf-token Without
    first (N) https (self-signed) 200 401 missing CSRF token
    first (N) http 400 400
    second (N+1) https connection fails connection fails
    second (N+1) http 200 401 missing CSRF token

    A wrong token returns {"code":"unauthenticated","message":"invalid CSRF token"}. So:

    • The first port is TLS and the second is plain HTTP. Both serve the same RPC, and both require the CSRF token.
    • The earlier comment's finding ("only the first port completes the TLS handshake; no CSRF required") matches the TLS part. The CSRF requirement is new, or depends on the build.

    Response (the percentages are just what this account showed at the time):

    {"response":{"groups":[
      {"displayName":"Gemini Models","description":"Models within this group: Gemini Flash, Gemini Pro","buckets":[
        {"bucketId":"gemini-weekly","displayName":"Weekly Limit Remaining","window":"weekly","remainingFraction":0.96,"resetTime":"<RFC3339>","description":"…it will fully refresh in 1 day, 21 hours."},
        {"bucketId":"gemini-5h","displayName":"Five Hour Limit Remaining","window":"5h","remainingFraction":0.87,"resetTime":"<RFC3339>"}]},
      {"displayName":"Claude and GPT models","description":"Models within this group: Claude Opus, Claude Sonnet, GPT-OSS","buckets":[
        {"bucketId":"3p-weekly","window":"weekly","remainingFraction":0.79,"resetTime":"<RFC3339>"},
        {"bucketId":"3p-5h","window":"5h","remainingFraction":1,"resetTime":"<RFC3339>"}]}],
      "description":"Within each group, models share a weekly limit and a 5-hour limit. Quota is consumed proportionally to the cost of the tokens…"}}

    This has exactly the two independent pools this issue asks for. description is optional on buckets (missing on 3p-5h here), so parsers should not require it.

    The same token also authorizes GetUserStatus (returns userStatus.{planStatus,userTier,cascadeModelConfigData,email,name,…}), which could label the account or tier in the tooltip.

    3. Where the CSRF token lives for the CLI (and why the open PRs miss it)

    • Not in agy's argv (agy --dangerously-skip-permissions, nothing else), and not in agy's own environment. I checked ps eww on the agy pid: zero ANTIGRAVITY_* variables.
    • Not on disk. A grep of the whole ~/.gemini tree and the temp dirs found no match.
    • It is in the environment of every child process agy spawns (tools and stdio MCP servers). A child of the agy pid had:
      ANTIGRAVITY_AGENT  ANTIGRAVITY_AGENTAPI_EXE  ANTIGRAVITY_APP_DATA_DIR
      ANTIGRAVITY_CONVERSATION_ID  ANTIGRAVITY_CSRF_TOKEN  ANTIGRAVITY_LS_ADDRESS
      ANTIGRAVITY_LS_VERSION  ANTIGRAVITY_PROJECT_ID  ANTIGRAVITY_SOURCE_METADATA
      ANTIGRAVITY_TRAJECTORY_ID
      
      with ANTIGRAVITY_LS_ADDRESS=localhost:<second port>, the plain HTTP one. The agy binary's embedded sidecar and skill docs use exactly this contract: curl -H "x-codeium-csrf-token: ${ANTIGRAVITY_CSRF_TOKEN}" "http://${ANTIGRAVITY_LS_ADDRESS}/exa.language_server_pb.LanguageServerService/$1", with a default of ANTIGRAVITY_LS_ADDRESS:=localhost:5387.

    So the PRs that parse --csrf_token from a language_server* command line (e.g. #23382) only cover the desktop app. Keychain/REST approaches (#21999) hit the UNSUPPORTED_CLIENT/SUBSCRIPTION_REQUIRED wall above, at least for personal accounts. And the "no auth needed" assumption no longer holds for agy 1.2.x.

    4. Suggested implementation that needs no scraping: capture it in Orca's own agy hook

    Orca already installs ~/.orca/agent-hooks/antigravity-hook.sh and registers it in ~/.gemini/config/hooks.json. agy executes that script as a child process, so by the mechanism above it should see ANTIGRAVITY_CSRF_TOKEN and ANTIGRAVITY_LS_ADDRESS in its environment. (I have not modified the hook to prove this. It is the one assumption here that still needs a quick check. Every other agy child I inspected had them.) The hook already POSTs to http://127.0.0.1:${ORCA_AGENT_HOOK_PORT}/hook/antigravity with paneKey/launchToken, so it could forward two more fields:

      --data-urlencode "lsAddress=${ANTIGRAVITY_LS_ADDRESS:-}" \
      --data-urlencode "lsCsrf=${ANTIGRAVITY_CSRF_TOKEN:-}" \

    The main process would then keep {lsAddress, csrf} per pane (in memory only, never persisted, since it is a live credential) and have the rate-limit poller call POST http://<lsAddress>/…/RetrieveUserQuotaSummary with the header. Advantages over process scraping:

    • No ps/lsof/argv parsing, and it works the same on macOS, Linux and Windows.
    • No wrong-account risk. The earlier comment warns that long-lived agy processes keep stale accounts, so pids have to be sorted by start time. Here the token comes from the pane the user is actually using. With several panes, prefer the most recent hook event.
    • It uses plain HTTP on loopback, so there is no need for rejectUnauthorized: false.
    • It degrades cleanly: no hook event yet, or the agy process exited (connection refused / 401) → unavailable with "Start an Antigravity session to show usage".

    Fallback for agy sessions not started by Orca: enumerate agy pids, then read the environment of any child process (ps eww -o command= -p <childpid> on macOS, /proc/<pid>/environ on Linux). That is only possible while agy has at least one child alive, which is usually true when stdio MCP servers are configured.

    5. Suggested mapping to Orca's RateLimitBuckets

    • window: "5h" → windowMinutes: 300; window: "weekly" → windowMinutes: 10080.
    • usedPercent = round((1 - remainingFraction) * 100); resetsAt = Date.parse(resetTime).
    • Two groups → show "Gemini" and "Claude/GPT" separately (the session = 5h and weekly pairs per group), instead of the current single mirrored bar. It would also make sense to move the Gemini status item onto this data when no Gemini CLI project is available, since for personal accounts that pool now lives here.
  14. leonardoasb commented on Sep 30, 2026

    @leonardoasb

    Additional datapoint on 1.4.217 (macOS arm64), which is the current latest release — and I think it changes the recommended fix here: the Gemini-CLI mirror is now unrecoverable, not merely under-configured.

    Google refuses new Gemini CLI sign-ins for individuals outright:

    Failed to sign in. Message: This client is no longer supported for Gemini Code Assist
    for individuals. To continue using Gemini, please migrate to the Antigravity suite of
    products: https://antigravity.google
    

    Measured chain on this machine (Antigravity CLI agy 1.2.10 installed and signed in — agy models lists models normally):

    • ~/.gemini/oauth_creds.json is present with expiry_date 2026-09-23 (expired) and a refresh token that is still valid.
    • With no local @google/gemini-cli, the refresh is never attempted (no client id/secret) → Token refresh failed, exactly as reported above.
    • After installing @google/gemini-cli 0.62.0 so extractOAuthClientCredentials resolves (the eta() path does match: OAUTH_CLIENT_ID/OAUTH_CLIENT_SECRET are in bundle/chunk-2DHAEQE2.js / chunk-72GZSNV7.js), the same manual refresh Orca performs returns HTTP 200 with an access token (expires_in 3599).
    • With that fresh token:
      • POST https://cloudcode-pa.googleapis.com/v1internal:loadCodeAssist → 200, allowedTiers: ["standard-tier"], isDefault: true, but currentTier: null and no cloudaicompanionProject;
      • so M4() throws Gemini project ID not found; retrieveUserQuota with a project id passed manually returns 403.

    Conclusion: even with the client-credential bug fixed, the segment stays "not available" on a machine that only has Antigravity. The account has no Code Assist project, and the one flow that would create it (Gemini CLI sign-in) is now refused by Google. Worth flagging explicitly, because the documented workaround (install gemini-cli, re-auth) fails at the sign-in step, not at the refresh step — users will burn time there.

    Also re-verified against the 1.4.217 bundle: retrieveUserQuotaSummary and daily-cloudcode-pa each occur 0 times, and the antigravity provider is still {...gemini, provider: 'antigravity'}.

  15. added a commit that references this issue on Oct 1, 2026
    a76a0bc
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

bugSomething isn't working

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions