Omahub
← All plugins
M

OpenCode Usage

by markbus-ai

OpenCode token usage, models and Go plan subscription meters in a native Omarchy bar panel.

Security review

No obvious issues detected

Deterministic scan — not a security guarantee

None
Risk level
None
Analyzed commit
b2cf4c8
Scanned
1 month ago

No potentially dangerous behavior detected in the analyzed commit.

Automated analysis only — not a security guarantee.

AI advisory review

No obvious issues detected

Language-model assessment · ~deepseek/deepseek-v4-flash-latest — advisory only

Low
AI risk level
Low
Recommendation
install
Model
~deepseek/deepseek-v4-flash-latest
Analyzed commit
b2cf4c8
Reviewed
1 month ago

This is a transparent QML/Python widget that reads local OpenCode SQLite usage data, optionally calls OpenCode's usage endpoint with the user's API key over HTTPS for plan meters, and supports merging JSON snapshots from a user-configured sync folder. No obfuscation, hidden persistence, credential exfiltration, destructive install behavior, or unexpected commands were found, so the deterministic scan's "none" result is consistent with the reviewed code.

  • The scanner reads the OpenCode auth key from ~/.local/share/opencode/auth.json and sends it to the opencode.ai usage endpoint; this is the advertised feature, but it means the plugin handles and transmits a real credential.
  • With syncMode enabled, the widget reads every *.json snapshot from an arbitrary user-configured folder; a malicious or corrupted snapshot could distort displayed usage numbers, though it cannot execute code.
  • The sampled files did not include the complete scanner implementation, so the network/auth and sync-handling paths are worth a quick human spot-check during review.
How this check works

This review combines the deterministic scan (the rule-based results above) with an independent look at the plugin's code by a language model. The model reads a trimmed sample of the repository's files, the manifest, and the README, then gives a plain-language risk level and a recommendation: install (no notable danger), review (look closer first), or avoid (clearly dangerous).

It runs on the same analyzed commit as the deterministic scan and is strictly advisory — it is not a security guarantee and never blocks a plugin by itself. A human moderator still reviews plugins before they are listed.

AI advisory only — automated analysis, not a security guarantee.

Install
$ omarchy plugin add https://github.com/markbus-ai/omarchy-opencode-usage --enable
Developer Tools #bar #quickshell #ai

OpenCode Usage

One bar icon and one panel that shows the tokens you have spent in OpenCode, read from OpenCode's local database — plus the subscription meters of your OpenCode Go plan when a key is available.

Panel.qml owns the bar button and the popup; Main.qml owns the scanner fan-out and the optional cross-device aggregation; providers/ holds the provider adapter; scripts/opencode_usage_scanner.py reads the SQLite database and probes the usage endpoint with nothing but the Python standard library.

What you see

  • Hero — the OpenCode mark and where the numbers come from ("Go" when plan meters are live, "Local stats" otherwise, or a status such as "Waiting for auth").
  • Limits — one percent meter per Go plan window (Session, Weekly, Monthly) with a reset countdown. When meters are unavailable the panel shows the status and the help text instead of empty meters.
  • Tokens by day — one row per day for the last week: day, bar, tokens, with today bolded at the bottom. Hover today for its prompt and session count.
  • Tokens by model — tokens per model with the bar behind each row scaled to the heaviest model. Hover for the input / output / cache split.

The widget appears in the bar once a scan finds usage (or limits arrive), and leaves the bar entirely on a machine that has never run OpenCode.

Go plan meters

Meters come from OpenCode's usage endpoint (https://opencode.ai/zen/go/v1/usage). The key is resolved in this order:

  1. OPENCODE_GO_API_KEY environment variable, otherwise
  2. the OpenCode CLI login stored in ~/.local/share/opencode/auth.json (create it with opencode auth login).

The endpoint base can be overridden with OPENCODE_API_BASE_URL; it must be https:// — the scanner refuses to send the key over plain HTTP. Without a key the panel reports "Waiting for auth" and keeps showing local stats.

Data source

The scanner reads assistant-message metadata from OpenCode's SQLite database. The database resolution order:

  1. the widget setting providers.opencode.dbPath, otherwise
  2. OPENCODE_DB / OPENCODE_DATABASE when set, otherwise
  3. the freshest channel database (opencode-<channel>.db — the one whose WAL was written most recently, since channel databases all carry real subscription traffic), otherwise
  4. $XDG_DATA_HOME/opencode/opencode.db (usually ~/.local/share/opencode/opencode.db).

Set an explicit override in the widget settings with:

omarchy bar set markbusai.opencode-usage providers '{"opencode": {"enabled": true, "dbPath": "/custom/path/opencode.db"}}' --json

How scanning works

The scan is SQL-side: a json_extract filter (guarded by json_valid so a malformed row can never abort the scan, with LIKE gates in front as pure acceleration) streams only opencode-go assistant rows' token splits out of SQLite — Python never holds the raw message JSON, so huge databases stay cheap.

Results are cached in ~/.cache/omarchy/agent-usage/ and refreshed incrementally. A watermark envelope records where the last scan stopped; when the database changes, only rows newer than the watermark are re-read and merged into the cached totals, with a 10-minute overlap band so rows written asynchronously are neither lost nor double-counted. Rows are also re-read when their time_updated moved past the previous scan (opencode finalizes a message's tokens in place after creation); an edited row forces one exact full rescan, since the merge cannot correct a stale contribution. A day rollover, a shrunken table, a band-width change, or a corrupt envelope all fall back to a full scan too. The cache files are locked down (0600 files, 0700 directory).

Install

omarchy plugin add https://github.com/markbus-ai/omarchy-opencode-usage --enable

The widget joins the bar's default layout at the next shell reload (omarchy-restart-shell). Remove it with:

omarchy plugin remove markbusai.opencode-usage

Settings

Settings live in the widget's entry in ~/.config/omarchy/shell.json. Set them with omarchy bar set markbusai.opencode-usage <key> <value>:

Key Default What it does
refreshIntervalSec 900 How often local scans and snapshots refresh
syncMode "Off" "On" writes this machine's snapshot and merges the others
syncDir "" A folder synced by Syncthing, Dropbox, rsync, …
syncFileName <hostname>.json This machine's snapshot file
syncDeviceId hostname Stable device name inside the snapshot

Numbers need --json, or they land in shell.json as strings:

omarchy bar set markbusai.opencode-usage refreshIntervalSec 300 --json
omarchy bar set markbusai.opencode-usage syncDir '~/Sync/opencode-usage'

With syncMode on, every *.json snapshot in syncDir is merged, so today, the last 7 days, and the all-time totals cover every machine you code on — active days are unioned by date rather than summed. The snapshot contains counts only, never conversation content.

Interactions

  • Bar icon: left = panel, right = refresh, middle = next provider.
  • Panel: j/k scroll, r or Enter refresh, Tab moves to the neighboring bar panel, Esc closes.
  • IPC: omarchy-shell markbusai.opencode-usage <open|close|toggle|refresh|next>.

Troubleshooting

  • "Waiting for auth" — no key found. Run opencode auth login or export OPENCODE_GO_API_KEY (restart the shell after either).
  • "OpenCode's usage endpoint rejected the key (status 401/403)" — the key is invalid, expired, or the account has no Go plan. Local stats still show.
  • Meters missing after a 429 or 5xx — the endpoint is rate limiting or having an outage; the panel keeps local stats and retries on the next refresh.
  • "OpenCode data not found" — run opencode once to create its usage database.
  • "OpenCode scan failed" — the database is unreadable or its schema is unsupported (for example an unrelated SQLite file at the resolved path).
  • Stale totals — the cache lives in ~/.cache/omarchy/agent-usage/; deleting it forces the next scan to rebuild everything from scratch.

License

MIT. The OpenCode mark is a trademark of its respective owner and is used here to identify the tool this widget reports on.