opencode multi acc limits/balance checker cli/api
Go to file
ocd 5393e4eab5 Add health subcommand; detect dead auth cookies
OpenCode rejects a dead auth cookie with HTTP 302 to /auth/authorize (or
401/403). The HTTP client now disables redirect following so this surfaces
as a FetchError::Unauthorized instead of a 200 login page that fails to parse.

ocd health probes each account's cookie against its default workspace Zen
page and reports alive/dead/errored/misconfigured with a total count. Exit is
0 only when all accounts are alive.

The main walk (pretty/raw/fetch) also classifies a dead cookie as the new
ReportStatus::CookieDead, labels it [cookie dead] in pretty output and
cookie_dead in raw output, and continues with the valid accounts rather than
aborting. Verified live: valid account surfaces [ok], dead account surfaces
[cookie dead], unfilled account surfaces [cookie dead].
2026-07-30 02:04:53 +03:00
examples Wire real OpenCode selectors and URLs from captured pages 2026-07-30 01:16:36 +03:00
src Add health subcommand; detect dead auth cookies 2026-07-30 02:04:53 +03:00
.gitignore Scaffold ocd: config, HTTP fetch, cache, paced pipeline, render 2026-07-30 01:07:30 +03:00
Cargo.lock Scaffold ocd: config, HTTP fetch, cache, paced pipeline, render 2026-07-30 01:07:30 +03:00
Cargo.toml Scaffold ocd: config, HTTP fetch, cache, paced pipeline, render 2026-07-30 01:07:30 +03:00
DESIGN.md Add health subcommand; detect dead auth cookies 2026-07-30 02:04:53 +03:00
README.md Wire real OpenCode selectors and URLs from captured pages 2026-07-30 01:16:36 +03:00

ocd

Console dashboard for opencode account limits and balance.

ocd reads a config of opencode accounts and auth cookies. It scrapes the opencode Zen page for balance and the Go page for limits. It prints usage for the 5-hour, week, and month time frames, each reset time, the next update time, and remaining balance.

Install

cargo install --path .

Configure

ocd config init
$EDITOR ocd.toml
ocd config check   # lists accounts and workspaces, no network

Each account section carries default_workspace and optional extra_workspaces.

[[account]]
name              = "work"
cookie            = "${OCD_COOKIE_WORK}"
default_workspace = "wrk_01KYNTSGXF7GFXMAMT36N3GH21"
extra_workspaces  = ["wrk_02KYNTSGXF7GFXMAMT36N3GH21"]

${VAR} expands from the environment so cookies stay out of the file.

Run

ocd pretty            # default terminal output
ocd raw json          # one JSON object for widgets and agent plugins
ocd raw plain         # TSV-ish lines for shell and awk
ocd fetch             # update cache, print nothing; for cron
ocd cache ls | clear
ocd -a work -w wrk_02KYNTSGXF7GFXMAMT36N3GH21 pretty   # one account, one workspace

Politeness

Per workspace two requests run at once (Zen, Go). The walk paces 500 ms between workspaces. Cache TTL defaults to 180 s. Use --force-refresh to bypass.

Status

The HTTP client, cache, pacing, and renderer work. The src/scrape.rs selectors target the real Zen balance element and the Go usage frames, and parse correctly against captured pages (see the scrape::tests unit test). Live fetching needs a valid account cookie and a workspace id. Conditional GET headers are not yet sent; the TTL cache handles politeness alone. See DESIGN.md.