Skip to content

feat(opencode): expose account usage limits - #146

Open
Aser-Osama wants to merge 2 commits into
raine:mainfrom
Aser-Osama:feat/opencode-go-usage
Open

feat(opencode): expose account usage limits#146
Aser-Osama wants to merge 2 commits into
raine:mainfrom
Aser-Osama:feat/opencode-go-usage

Conversation

@Aser-Osama

@Aser-Osama Aser-Osama commented Sep 10, 2026

Copy link
Copy Markdown
Contributor

OpenCode Go exposes rolling five-hour, weekly, and monthly quota windows, but claude-code-proxy currently surfaces only per-request token usage and limit failures. Users cannot inspect their remaining account allowance before sending a request, and dashboards pointed at the proxy have no account endpoint to poll.

This PR builds on #145, which refreshed the OpenCode Go catalog and runtime behavior, by adding focused account-usage support on top of that provider foundation.

What changes

  • Adds claude-code-proxy opencode usage
  • Adds claude-code-proxy opencode usage --json for scripts
  • Fetches OpenCode Go's authenticated /usage endpoint with a bounded response body, a 10-second timeout, disabled redirects, and the versioned claude-code-proxy User-Agent
  • Exposes CCR-compatible account snapshots at:
    • GET /.well-known/ccr/account
    • GET /v1/account/limits
  • Normalizes rolling five-hour, weekly, and monthly percentages into CCR quota meters
  • Preserves optional reset times and upstream status details
  • Clamps out-of-range percentages to 0–100 and reports that normalization explicitly
  • Preserves unknown upstream JSON fields in CLI JSON output for forward compatibility

OpenCode implements the upstream usage endpoint, including all three quota windows, although it is not yet listed as a stable public API contract. The parser therefore keeps known fields typed while tolerating missing fields and unknown additions. It rejects responses with no recognizable quota information instead of fabricating values.

Caching and HTTP behavior

The server keeps the latest successful upstream result in a small 60-second in-process cache. Frequent Claude Code Router polling therefore reuses the same snapshot, and concurrent refreshes are coalesced.

After the cache expires, an upstream failure is returned explicitly instead of serving an unmarked stale quota. Upstream status codes are retained, including Retry-After on HTTP 429 responses. All local account responses include Cache-Control: no-store.

Claude Code Router compatibility

The local responses follow Claude Code Router's Standard usage endpoint contract. Configure the CCP provider with Fetch usage enabled and select Standard usage endpoint; CCR discovers /.well-known/ccr/account automatically.

A generic CCP /usage endpoint is deliberately omitted because #62 already proposes that API for Codex with a separate provider-neutral design discussion.

Security

The account routes intentionally ignore incoming placeholder bearer and API-key headers and use CCP's configured OpenCode credential, consistent with generation routes.

The credential is never serialized or recorded in traffic capture. Upstream error text is also scrubbed if it echoes the configured key. Since the local proxy does not authenticate clients, account usage remains visible to anyone who can reach a non-loopback listener; the documentation calls for a firewall or authenticating reverse proxy in that configuration.

Scope

Codex quota support is deliberately outside this PR. CCP currently receives some Codex rate-limit telemetry internally, while #62 proposes exposing Codex usage. This change remains scoped to OpenCode Go and does not alter Kimi, Grok, Cursor, or Codex behavior.

Validation

  • cargo fmt --all --check
  • cargo test --all
  • cargo clippy --all-targets -- -D warnings -A deprecated
  • Locked Astro documentation build, including generated llms.txt
  • git diff --check
  • Live OpenCode CLI usage query
  • Live requests to both local CCR account aliases

Rust 1.100 reports an existing AtomicU64::fetch_update deprecation in unchanged Codex websocket code. Current main has the same finding; the required Clippy invocation above passes.

@Aser-Osama
Aser-Osama force-pushed the feat/opencode-go-usage branch from f8d309b to eb0457c Compare September 10, 2026 15:10
@Aser-Osama
Aser-Osama marked this pull request as draft September 10, 2026 15:20
@Aser-Osama
Aser-Osama force-pushed the feat/opencode-go-usage branch from eb0457c to 184749b Compare September 10, 2026 20:06
@Aser-Osama
Aser-Osama marked this pull request as ready for review September 10, 2026 20:08
@Aser-Osama

Copy link
Copy Markdown
Contributor Author

@raine Kept this PR "OpenCode Go" only to avoid overlapping with the existing Codex usage work in #62, but I’m happy to extend the same account/usage surface to Codex as part of this PR if you’d prefer a unified implementation. Also happy to adjust the HTTP/API shape if you have a preferred direction.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant