ocd/README.md
ocd 41f35aec34 Wire real OpenCode selectors and URLs from captured pages
Go page (/workspace/{id}/go): parse three [data-slot=usage-item] frames
(Rolling/Weekly/Monthly) into usage percentages + computed resets_at from the
relative reset-duration text. Zen page (/workspace/{id}): parse
[data-slot=balance] b into remaining + currency unit. Add an offline unit test
against tmp/ captures. Fix pretty renderer (percent display, money format,
day-aware relative times). Update DESIGN.md, README, examples and config
template to the real wrk_ workspace ids.
2026-07-30 01:16:36 +03:00

1.7 KiB

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.