Repository navigation
How it works
Each account is polled against its provider's own usage endpoint: Anthropic's OAuth usage endpoint (the data behind /usage in Claude Code) and the ChatGPT backend usage endpoint for Codex. Both are undocumented and unsupported by their vendors, so they can change without notice. The Claude request needs a claude-cli/… User-Agent, otherwise it lands in an aggressively rate-limited bucket.
Settings → General offers 30s, 1m, 3m, 5m and 10m, and the default is 180 seconds. The 180 s minimum comes from community-measured rate-limit behavior. Each account polls independently in its own task, and a 429 backs off per account (3 → 6 → 12 → 15 minutes, holding at 15, reset by any success), so one throttled account never stalls the others.
For local Claude accounts, reads go through a small cache file per config dir:
~/Library/Caches/<bundle id>/<config-dir-name>.usage.json
It holds the last raw response, its fetch time, and a throttled_until time. A response younger than 180 seconds is reused instead of fetched, and a 429 parks every reader of that file until Retry-After has passed. This keeps repeated polls from multiplying requests and lengthening the 429 window. A lock file stops simultaneous fetches.
Claude Code and Codex own the refresh token of a local login. Both rotate it on use, so if Agents Monitor spent it, the CLI's next refresh would fail with invalid_grant and force you to log in again. A monitoring tool must not log you out of your own CLI, so for local Claude and Codex accounts the app only reads the access token, fresh on every poll, and never refreshes it. Using the CLI occasionally keeps the token fresh on its own.
Only remote accounts, whose credentials the app owns entirely, are refreshed by Agents Monitor.
A self-signed app reading another app's keychain item normally blocks on a password prompt. Agents Monitor:
- turns keychain user interaction off, so a consent request becomes a clean failure instead of a dialog;
- on that failure, falls back to Apple-signed
/usr/bin/security find-generic-password, which passes the item's access check silently, with a 5-second watchdog.
Result: no keychain password prompt, it survives rebuilds, and it works headless. Codex keeps credentials in auth.json, so that path needs none of this.
Decoding is tolerant: every field is optional, a missing key degrades instead of failing, and any window whose resets_at has already passed is dropped rather than shown stale. Settings, accounts and alert memory are stored in UserDefaults, decoded with a fallback to defaults.
The tick on each bar marks where you would be if you burned the limit evenly across its window (elapsed time divided by window length). A bar left of the tick means you are under pace; right of it means you will likely hit the limit before the reset.
Every successful poll appends one line per account to ~/Library/Application Support/AgentsMonitor/history.jsonl: the time, the account id, each limit's percent keyed by its label (Session, Week, Week · Fable, ...) and the spend so far. At most one line per account every 2 minutes, whatever the poll interval. Lines older than 90 days are dropped at launch; the last 30 days are kept in memory for the graphs.
The graph side of a card draws those samples in the bar's color. The "full in ~Xh at this pace" warning takes the rise over the last fifth of the window (one hour of a session, about 33 hours of a week), counting only samples since the window last reset, and shows only when that pace runs the limit out before it resets.
Notarization needs a paid Apple Developer ID. Releases are self-signed with a stable identity, so permissions survive updates, at the cost of the first-launch Gatekeeper dialog. See Installation.
Agents Monitor · MIT © Roy Padina · More Mac apps · Support on Ko-fi ☕