Skip to content

v0.5.0

Choose a tag to compare

@github-actions github-actions released this 13 Oct 12:46
· 43 commits to main since this release

UTILIZATION: how full each window got before it reset

A new section under SUBSCRIPTIONS says how full each subscription's windows got before each reset, over the last 90 days. SUBSCRIPTIONS says how this week will end; UTILIZATION says how the last ones did: a subscription that runs out week after week, or one mostly left unused.

UTILIZATION  fullest % before each reset

  CLAUDE           CYCLES  OUT  AVG  NEWEST FIRST
● mira@studio.dev      13    5  91%   100   94  ~71  100   88  100   82   97  100   76   91  100
    5h                 11    4  77%   100   64   38  100   92  ~55   71  100   47   83  100

  CODEX
● mira@studio.dev      13    ·  47%    52   41  ~29   63   48   37   55   44   71   39   46   58
  • An account's row is its main window, the weekly one, with its other windows, such as a model's or the 5-hour one, under it. CYCLES counts the periods that ended, OUT those that ran out, and AVG is their average. Then comes each period's percent, newest first, colored as AT RESET is: out at 100%, tight from 85%, ok from 50%, and under below that.
  • A period is one reset of a window, and its percent is the fullest reading any device took of it. A week that ran out stays at 100% when the provider resets it early or takes usage back.
  • ~ marks a period last read well before it ended, as when the laptop slept, so it may have got fuller.
  • A period read only at 0% is left out, and so is Hermes, whose quota is another login's. Of a window shorter than a day, such as the 5-hour one, only the newest 12 periods are kept.
  • The history is there from the first run after the update: each device finds the periods in the samples of the last 90 days that earlier releases kept too.
  • The JSON has utilization on each team account, and cycles_held_back_by and cycles_reason on the team. The schema version stays 4. See docs/json-schema.md.

How the team's cycles arrive

Each device sends its periods in its snapshot, as cycles, and the team takes the fullest reading of each period across devices: a week one laptop read at 71% and a server read at 100% shows 100%.

A release before v0.5.0 rejects a snapshot with fields it does not know. So a device sends cycles only once its last team read, at most 3 hours old, shows every teammate on v0.5.0 or later. The gate v0.4.0 added for weighted tokens must be open too. Until then no device sends them, each device's UTILIZATION shows its own periods, and a line under the section's title names the devices holding them back and what to do:

UTILIZATION  fullest % before each reset
  only this device's cycles: leo-air runs v0.4.0: it updates itself within 15 minutes
  • Releases from v0.2.5 on update themselves within 15 minutes, so on most teams the line is gone within about half an hour of the release. Older ones need install.sh again; the line says so.
  • A retired device, or one silent for over a week, holds the cycles back until ai-usage team forget-device ID forgets it.
  • A relay that does not accept cycles yet gets the snapshot without them in the same run, and is offered them again a day later. Meanwhile the line says the relay did not accept cycles, with when the device tries again.

Forecasts: no false OVER after an early reset

A window's pace is now measured over a tenth of the window at least: 16.8 hours in a week, and 30 minutes in a 5-hour window.

Until now the forecast took a week's first busy hours as the pace of the week. When Codex reset every weekly window early, each account that worked a little that morning showed OVER with most of its quota left: 6% used 3 hours into the week read as 311% at the reset. A window that sat at 0% and then read 1% a few minutes later did the same in mid-week.

  • The average pace runs from the window's start, or from its last reading at 0%, but over a tenth of the window at least: what was used in less time counts as used over that tenth. In its first tenth, a window is over only once about a tenth of it is used already.
  • The recent pace, the slope of the last day's readings, needs readings that span a tenth of the window: at least an hour, as before, so 5-hour windows forecast as they did, and at most 20 hours.
  • Past a window's first tenth, with a reading every 15 minutes, nothing changes. The JSON's shape is the same.

Notifications in the menu bar app

The menu bar app now posts a notification when a window runs out, or will run out before its reset: the windows ATTENTION marks out and over.

  • Out: "Claude mira · 5h is out", with when it is back.
  • Will run out: "Claude mira · 7d runs out ~Sat 10:28", with how long that is before its reset.

Settings, General, Notifications picks which:

Setting Choices Default
When a Window Is Out on, off on
When a Window Will Run Out Within a Day, Any Time, Never Within a Day
Subscriptions This Mac's, The Team's This Mac's
  • Within a Day says nothing until the window runs out within the next 24 hours, since a forecast early in a long window can change by the next reading.
  • This Mac's are the subscriptions logged in on this Mac. The Team's are all the subscriptions with a reading, bots' included, and the notification also names the device that uses one most, as in "used on build-01 +9".
  • Each window is said once per period and state: once when it will run out, once more when it is out, and again only after it resets. A forecast that dips under 100% and rises again says nothing new, and a restart repeats nothing.
  • A click on a notification opens the popover on that subscription in Limits.
  • macOS asks for permission when there is first something to say, or when you turn a notification on. If you decline, the app asks no more, and Settings says that notifications are off, with a button to System Settings.

The notifications come from the report the popover shows; the app computes nothing of its own.

Long log lines

A session log line over 32 MiB, such as a prompt with a huge paste or a tool's huge output, was skipped and counted as malformed. Claude Code, Codex, or Grok then showed partial with 1 malformed lines at every run, and the usage on such a line was lost.

  • Such a line is now read with its lists and long texts left out, in no more memory than 32 MiB, so its usage counts and it is no error.
  • A line still over 32 MiB after that is skipped and named apart, as N lines too long to read rather than N malformed lines. The tool stays partial for it, since that line could have held usage.
  • The first v0.5.0 run reads the Claude Code transcripts once more in full, since what it keeps of them moves to cache/claude-v2.gob, and removes the old claude-v1.gob. The ledger counts only what a session grew, so nothing is counted twice.

Compatibility and upgrade

What to do. Usually nothing. Releases from v0.2.5 on install v0.5.0 within 15 minutes, and on a Mac the menu bar app updates with the binary. Reinstall a teammate on a release before v0.2.5 with install.sh, and forget a retired device with ai-usage team forget-device, so that the team's cycles arrive.

Relay. If you run your own relay, deploy it from this release before your devices update: it accepts snapshots with cycles and without. An older relay answers a snapshot with cycles with 422. The device then sends it without them in the same run and offers them again 24 hours later, so nothing breaks, but each device shows only its own UTILIZATION until the relay is updated. See docs/relay.md.

Mixed-version teams. A device on an earlier release keeps reading the team as before, since no device sends cycles while it is there. One case is left, as with v0.4.0: a device the team has never seen, freshly installed with a release before v0.5.0 that someone pinned, can read snapshots with cycles on its first run and skip them until it updates itself at its next run, or until the others close the gate at their next team read. The installers always install the newest release.

State. The ledger keeps its format; state.json gains one field, for when the relay last refused cycles.

Building from source. ai-usage now needs Go 1.26 or newer, up from 1.25, for the updated modules, among them Bubble Tea v2.1.0 and SQLite v1.60.1. go.mod names Go 1.26.9 as its toolchain, so an older Go 1.26 downloads 1.26.9 to build, unless GOTOOLCHAIN=local. A relay run in Docker needs the golang:1.26 image. A build from source reports devel and counts as new, so it never holds the cycles back. Give a hand build with a suffix a release of v0.5.0 or later before it, such as v9.9.9-local: one before v0.5.0 counts as that release and holds the cycles back from the whole team.

Known limitations

  • UTILIZATION knows only the periods some device of the team read. A period nobody read near its end is marked ~, and one from before ai-usage was installed, or over 90 days ago, is not there.
  • A v0.4.x built from source reports devel, so it does not hold the cycles back, and it skips the snapshots with them until it is built again from v0.5.0.
  • Notifications come from the menu bar app, only while it runs, and only on macOS. The collector itself notifies no one.

What's Changed

  • Measure a window's pace over a tenth of the window at least by @neoromantic in #4
  • Read a valid log line over 32 MiB instead of counting it as malformed by @neoromantic in #5
  • Quota utilization per account: how full each window got before each reset by @neoromantic in #9
  • Notify when a window runs out or will run out by @neoromantic in #10

New Contributors

Full Changelog: v0.4.0...v0.5.0