Files
omarchy/shell/plugins/agents/README.md
T
David Heinemeier HanssonandClaude Opus 5.5 f45461a38f Bring Grok up to par with Claude and Codex in the agents panel (#13992)
* Let Grok updates through mise take effect

Grok's npm launcher runs ~/.grok/bin/grok whenever it exists, and the
install script that repoints it at a new release doesn't run under mise,
so every machine kept running the release it first unpacked. Updating
mise tools now drops a link to an older release and the old binary, and
lets the launcher unpack the installed one.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Keep several Grok accounts, the way Claude and Codex do

Grok honors GROK_HOME, so an added Grok account gets its own home holding
only its login and settings cache, with the CLI binary, sessions, skills,
plugins, memory, and config linked back to ~/.grok. The account commands,
the add flow (a second account signs in through a private window), the
launcher, and a grok shell function all take it like the others, and its
identity and plan come from the files Grok writes at login.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Show Grok's plan and credits in the agents panel

A grok collector reads each account's plan from the settings Grok caches
and its credits from the endpoint behind Grok's own /usage view, so Grok
gets a section, per-account limits, and autoswitch like Claude and Codex.
A signed-in agent with a plan now shows before its first numbers, so a
lapsed sign-in has somewhere to say so. Grok's mark joins the assets, and
with every agent able to take another account the add screen no longer
needs to dim one.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Document Grok accounts and limits alongside Claude and Codex

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Read Grok's credits the way xAI actually answers

The answer nests under config, names a weekly period with its end, and
as protobuf JSON leaves the usage percentage out while it's zero. The
collector now reads that shape, so a fresh week shows as 0% until it
resets rather than as nothing known.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Count Grok's prompts and sessions from its session summaries

Grok keeps a summary beside each session with when it was last active
and how many prompts it had, so its section and the hero's summary get
today's prompts and sessions and its active days. It records no token
counts there, so none are claimed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Give each Grok limits cache write its own temporary file

Two overlapping collector runs wrote the same cache through one .tmp
path, so one rename could leave the other's failing and its record not
updated.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Read a single Grok account from GROK_HOME when it's set

The launcher and the CLI honor GROK_HOME, but the collector always read
~/.grok, so a Grok signed in only in a custom home showed nothing. With
one account, the collector now reads the home the CLI would; with
several registered, the primary stays ~/.grok.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Drop guesses the real Grok credits answer made unnecessary

The collector carried fallbacks for fields and shapes guessed from the
binary before xAI's actual answer was seen, a numeric timestamp branch
nothing writes, the panel's default for prompt stats, and guards that an
empty sign-in already covers.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Keep the working Grok release until its update is in place

The update dropped the link and older binaries before the new release was
unpacked and ignored a failed unpack, which could leave every Grok
account without a CLI. The old release now stays until the new one is
linked, and its link comes back if it never is.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Count only Grok sessions for today, not prompts

A session's summary holds all its prompts and only when it was last
active, so a resumed session put its whole history on today. Today now
counts the sessions active in it; prompts stay an all-time total.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Reuse the Grok session scan on a limits-only refresh

Opening the panel and near-limit checks only need fresh limits, so they
reuse a scan up to 15 minutes old, as the Codex collector does; --force
still rescans.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-01 23:37:56 +02:00

199 lines
11 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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
Every subscription on one page, limits first.
- **Hero** — the agents robot, and a line that rotates through what the
token counts add up to across every agent: tokens this week and today, the
most used model, the busiest day, and today's prompts and sessions. Its
corner has + to add a subscription and >_ to start the default agent.
- **One section per agent** — its mark, name, and plan, then a compact line
per limit window: its meter and the time until it resets (the exact percentage
on hover). A model-scoped allowance on the same clock (Claude's Fable weekly
limit) is a tick on that window's meter rather than a line of its own; the
row's tooltip names it. Sign-in and endpoint trouble shows under the name in the urgent
color. Limits kept from an earlier check after a failed one dim, and their
tooltip says how old they are.
- **Accounts** — an agent with more than one subscription account (see
`omarchy agent account`) lists each: name and plan on one line (the email on hover), and its own limit
lines. An _ACTIVE_ label marks the account new sessions start as; the
others get a _Use_ link. Hovering the line also reveals Autoswitch, which
moves new sessions over on their own once the active account reaches its
threshold; while it's on it stands in for Use, which shows only when you're
on the line, and clicking it again goes back to notifying. Click a name to
rename the account in place.
- **Balance** — prepaid agents show a credit ledger instead of limits: a
fuel-gauge meter that drains toward empty, the remaining credit, and
funded-versus-spent detail.
- **Make something cool** — starter prompts (a new theme, plugin, or app) that
start the default agent on the task through `omarchy agent prompt`.
- **Adding a subscription** — the + in the hero's corner swaps the page for
Claude Code, Codex, and Grok as large marks, three across, with the first
one focused, and the hero's line reads Add an account. The + becomes the
X that goes back. An agent that can't be added is dimmed and says why on
hover. A further account asks for a name first, and Enter signs it in. The
panel then runs `omarchy-agent-account-add --events` and follows it: the
status, the code Grok asks you to confirm in the browser, a field to paste
Claude's code back if its page shows one instead of finishing, and a link to
reopen the sign-in page. Esc or the X stops the login. The browser taking focus may close the panel; the sign-in
carries on and its result arrives as a notification.
The icon is always in the bar. On a machine with no agent yet, the panel is
the blank slate for setting one up: it opens on the same choice of Claude,
Codex, or Grok, and the first agent signed in becomes the default agent if
none was picked. An agent appears once it is enabled in settings and has
recorded usage, on this machine or a synced one; a CLI installed
mid-session shows up at the next refresh. Drop the widget 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, opencode sessions on an Anthropic provider, plus `stats-cache.json` and `history.jsonl` as fallback |
| `codex` | The Codex app-server RPC | native Codex CLI session files (plus pi and opencode sessions) |
| `grok` | The credits endpoint behind Grok's `/usage` view (the billing period's included usage) | Prompts and sessions from each session's `summary.json` (Grok records no tokens there) |
| `fireworks` | Estimated prepaid balance: configured funding minus rated account costs | Fireworks billing API, grouped by day and model for the last 30 days |
When `~/.local/state/omarchy/agents/accounts/<claude|codex|grok>.json`
registers more than one account, the `claude`, `codex`, and `grok` records
also carry
`accounts: [{ id, label, email, plan, active, limits, stale, usageStatusText,
authHelpText }]`, each account probed with its own sign-in (Claude caches each
account's limits separately; Codex runs one app-server per account home), and
`accountSwitch: { mode, threshold }`. The record's top-level `limits` and
`tierLabel` keep describing the active account, and local stats stay one set,
since every account shares the primary home's history. After each run,
`omarchy-agent-usage-update` hands the fresh limits to
`omarchy-agent-account-state autoswitch`, which notifies or switches when the
active account crosses its threshold, and re-collects the record if the active
account changed.
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`, Grok via `GROK_HOME`. Grok's
plan comes from the settings it caches in its home, and its limit from the
credits endpoint its own `/usage` view reads, asked with each account's
sign-in; a sign-in left to lapse shows the last credits until Grok runs
again. Fireworks reads
`FIREWORKS_API_KEY` and `FIREWORKS_ACCOUNT_ID` first, then
`~/.fireworks/auth.ini` (which `firectl set-api-key` creates), then the key
opencode stores in `~/.local/share/opencode/auth.json` when Fireworks is
signed in there.
### Fireworks balance
The collector first asks the account's `:getBalance` endpoint for the real
prepaid ledger. That endpoint exists but is permission-gated, and as of
August 2026 no console-issued API key passes it — Fireworks appears to
reserve it for the dashboard session. The probe stays because it is cheap
and the live figure lights up automatically if Fireworks ever opens it to
keys. Until then the collector falls back to estimating the balance from
configuration in `~/.config/omarchy/agents/fireworks.json`:
```json
{
"accountId": "",
"fundedAmount": 20,
"fundedAt": "2026-07-01"
}
```
Set `fundedAmount` to the credits purchased and optionally `fundedAt` to the
purchase date; with no date, the collector uses the account creation time. It
subtracts rated account costs and the panel labels the result as estimated.
For a later top-up, increase `fundedAmount` by the new credit while keeping
the original `fundedAt`, so both the funding and spend still cover the same
period. `accountId` only matters when one API key can access several
accounts. Without a configured `fundedAmount` the tab still shows token
usage, just no balance. With a live ledger, `fundedAmount` is optional and
only adds the meter and the spent-of-funded line under the real figure.
## Interactions
- Bar icon: left = panel, right = launch agent, middle = refresh. It turns
urgent when any account new sessions use is at 90% of a window, or a
prepaid balance is down to its last 10%.
- Panel: the arrows (or `h`/`j`/`k`/`l`) walk a cursor over everything that
does something, row by row: the hero's buttons, each switchable account
(landing on Use, with Autoswitch to its left), and the starter tiles, or the
agents to add. Hovering moves the same cursor. Enter acts on it, or
refreshes when nothing is lit; `r` refreshes, Tab moves to the neighboring
bar panel, Esc closes.
- Accounts: `1`–`9` jump to an account across every agent, and Enter makes it
active (picking alone never switches). `m` toggles automatic switching for
the picked account's agent. While an agent
with several accounts has its active one within 15 points of its switch
threshold (80% at the default), the limits refresh every three minutes.
- IPC: `omarchy-shell omarchy.agents <open|close|toggle|refresh>`.
## 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:
```bash
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):
```bash
omarchy bar set omarchy.agents providers '{
"claude": { "enabled": true },
"codex": { "enabled": false },
"fireworks": { "enabled": true }
}' --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. A record may declare `"scope": "account"`
when its stats are account-global rather than machine-local (Fireworks'
billing API); those merge by taking the widest value instead of summing, so
the same account synced from two machines is not counted twice.
One caveat on "all-time": the Codex collector only reads native session files
touched in the last 30 days, and Fireworks requests the last 30 days from its
billing API, so their totals and day counts cover that window. Claude's cover
every transcript still on disk.