Files
omarchycn/shell/plugins/agents
David Heinemeier HanssonandClaude Fable 5 66b10156e4 Keep the agent mark fallback from stranding on a missing -light twin
The panel resolves marks by walking assets/<id>-light.svg then
assets/<id>.svg, advancing on Image.Error. But the candidates binding is
re-evaluated whenever the provider objects are rebuilt, and a fresh array
identity with identical content reset the walk to the -light candidate.
Re-pointing source at a URL whose load already failed emits no
statusChanged, so the walker never advanced again and agents that ship a
single mark — Claude — fell back to the generic bar glyph on light
surfaces.

Key the reset on the candidate URLs instead of the array identity, and
defer the error advance one tick so stepping source from inside its own
status change doesn't trip the binding-loop detector.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-07 17:13:31 +02:00
..

Agents

One bar icon and one panel for every AI coding subscription on the machine. The panel is strictly a display: it watches the usage records that omarchy-agent-usage-update writes to ~/.local/state/omarchy/agents/usage/ and draws whatever appears there. Panel.qml owns the bar button and the popup; Main.qml discovers and watches the records (and handles the optional cross-device aggregation); Agent.qml is the per-record file watcher.

Panel

  • Hero — the mark, the tool, and the plan it runs on ("Max 20x", "Pro"). Auth and endpoint problems replace the plan line and repeat in a card.
  • Subscription switch — one chip per enabled agent (h/l or click). It appears only when more than one agent is enabled.
  • Limits — the percentage of each allowance used, a matching meter, and the time until the session or weekly window resets.
  • 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, the same way the weekly chart scales to its busiest day. Hover for the input / output / cache split.

A subscription appears only when it is enabled in settings and has actually recorded usage — on this machine or on a synced one. With one such agent there is no switch row at all; with none, the module leaves the bar entirely rather than sitting there with nothing to say. A CLI installed mid-session shows up at the next refresh, so nothing polls the disk waiting for it.

That self-hiding is why the widget ships in the default bar layout: a machine that has never run an AI coding agent draws nothing, and the icon arrives on its own the first time a scan finds usage. Drop it with omarchy plugin disable omarchy.agents.

Data

Each agent is one JSON record in ~/.local/state/omarchy/agents/usage/, written by omarchy-agent-usage-update. That command runs one omarchy-agent-usage-<agent> collector per agent; the widget invokes it on its refresh timer and whenever you ask for a refresh, and picks up any record that lands in the directory regardless of who wrote it.

Adding an agent therefore never touches this plugin: ship a collector that prints the record contract (see the claude and codex collectors in bin/), and the panel gains a tab. An assets/<id>.svg mark is optional — with an assets/<id>-light.svg twin if the mark needs a dark variant for light surfaces — and the bar glyph stands in when there is none.

Collector Limits Local stats
claude Anthropic's OAuth usage endpoint (5-hour session + 7-day weekly) ~/.claude/projects transcripts, plus stats-cache.json and history.jsonl as fallback
codex The Codex app-server RPC native Codex CLI session files (and pi sessions)

Claude limits need a signed-in CLI; without credentials the panel says so and falls back to local stats only. A non-default Claude directory is honored via CLAUDE_CONFIG_DIR, Codex via CODEX_HOME.

Interactions

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

Settings

Settings live in the widget's entry in ~/.config/omarchy/shell.json. The top-level keys can be set with omarchy bar set omarchy.agents <key> <value>:

Key Default What it does
refreshIntervalSec 900 How often the usage records regenerate
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 omarchy.agents refreshIntervalSec 300 --json
omarchy bar set omarchy.agents syncDir '~/Sync/agent-usage'

Per-agent enablement is nested, and set writes its key literally rather than walking a dotted path — so pass the whole providers object as JSON (or edit shell.json directly):

omarchy bar set omarchy.agents providers '{
  "claude": { "enabled": true },
  "codex": { "enabled": false }
}' --json

enabled defaults to true for every discovered agent; set it to false to hide a subscription that is installed. Disabled agents are also skipped when the records regenerate.

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. Rate limits stay per-account and are never merged.

One caveat on "all-time": the Codex collector only reads native session files touched in the last 30 days, so Codex totals and its day count cover that window. Claude's cover every transcript still on disk.