Skip to content

[feature]: optional quota state export to JSON file for external tool integration #102

@vmvarela

Description

@vmvarela

Pre-flight checks

  • I searched existing issues and did not find a duplicate request.
  • I reviewed current behavior on the production released OpenCode version.

OpenCode version reviewed

1.15.11

Problem statement

opencode-quota does the hard work of knowing how to authenticate with each provider and fetch quota data — including non-trivial cases like web scraping for OpenCode Go or OAuth flows for Copilot. However, this data is only available inside the OpenCode TUI. There is no way for external tools, scripts, or other plugins to consume it without reimplementing all that provider-specific logic from scratch.

This creates an unfortunate situation: any tool that wants to act on quota data (shell scripts, status bars, proxy routers, CI pipelines that use LLMs) must either duplicate the authentication and fetching logic for every provider, or go without quota awareness entirely.

Proposed change

Expose quota data to external tools through the data opencode-quota already holds — no additional API calls. Two complementary surfaces emit the same JSON schema, both reading from the existing per-provider disk cache:

  1. opencode-quota show --json — a CLI surface for on-demand reads (status bars, scripts, CI gates). Pairs with --threshold <pct> (exit 1 when any provider is below the threshold) and --provider <id>.
  2. Opt-in periodic export file — disabled by default, configured in quota-toast.json. When enabled, the TUI writes the JSON file after each background refresh:
{
  "export": {
    "enabled": true,
    "path": "~/.cache/opencode/quota-export.json" // empty string => $XDG_CACHE_HOME/opencode/quota-export.json
  }
}

Both surfaces emit a normalized document built from the same per-provider data used to render the TUI. Because quota is normalized internally (providers map their native shapes into a universal percent/value model), the schema exposes percentRemaining and resetAt rather than provider-specific remaining/limit numerics, which are not uniformly available across providers:

{
  "version": 1,
  "exportedAt": 1748736000, // unix seconds
  "fromCache": true,
  "cacheAgeSeconds": 42, // age of the oldest provider entry
  "providers": {
    "github-copilot": {
      "status": "ok",
      "fetchedAt": 1748735958,
      "entries": [
        {
          "name": "Premium Requests",
          "window": "monthly", // present when the provider reports multiple windows
          "percentRemaining": 62.3,
          "resetAt": 1748908800, // unix seconds; absent when not reported
          "unlimited": false
        }
      ]
    },
    "opencode-go": {
      "status": "error", // fetch attempted but failed
      "fetchedAt": 1748735958,
      "error": "Request timeout after 5000ms"
    },
    "anthropic": {
      "status": "unavailable" // credentials not detected / not attempted
    }
  }
}

The write happens on the same interval as the existing background refresh, reusing data already fetched. No new network requests, no new dependencies — just an atomic fs.writeFile on the existing cached state.

Alternatives considered

Use cases this would unlock, in rough order of simplicity:

  • Shell scripts: check remaining quota before running expensive automated tasks
  • Terminal status bars (tmux, starship, waybar): show live quota without reimplementing auth
  • Local LLM proxy routers: select the optimal model/account based on remaining quota, enabling "save mode" when approaching limits and load-balancing across multiple accounts of the same provider
  • Team dashboards: aggregate quota usage across multiple developers without accessing provider dashboards

Acceptance criteria

  • Export is disabled by default; no file is written unless explicitly enabled in quota-toast.json
  • When enabled, the file is refreshed on the same interval as the existing background quota check
  • The same normalized JSON schema is emitted by both the export file and opencode-quota show --json
  • The exported document is valid JSON and includes at minimum: exportedAt (unix seconds) and, per provider, a status of ok / error / unavailable; for ok providers, an entries array where each entry carries percentRemaining, optional resetAt (unix seconds), and unlimited
  • Providers that fail to fetch quota are included with status: "error" and an error message instead of silently omitted, so consumers can distinguish "quota is zero" from "fetch failed"; providers without detected credentials are included with status: "unavailable"
  • The export path is configurable and supports ~ expansion; an empty path falls back to $XDG_CACHE_HOME/opencode/quota-export.json
  • Writing the file does not block the main quota fetch or affect TUI rendering
  • If the file cannot be written (permissions, invalid path), a warning is logged but the plugin continues to function normally

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions