claude-usage-limits 1.9.2 → 1.11.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/plugin.json +1 -1
- package/.codex-plugin/plugin.json +1 -1
- package/README.md +196 -25
- package/bin/cli.js +21 -1
- package/commands/panel.md +14 -0
- package/commands/statusline.md +15 -0
- package/package.json +1 -1
- package/skills/usage-limits/SKILL.md +36 -0
- package/skills/usage-limits/references/how-it-works.md +115 -2
- package/skills/usage-limits/scripts/activity.js +198 -0
- package/skills/usage-limits/scripts/bars.js +340 -0
- package/skills/usage-limits/scripts/brief.js +59 -6
- package/skills/usage-limits/scripts/feed.js +400 -0
- package/skills/usage-limits/scripts/live.js +489 -0
- package/skills/usage-limits/scripts/panel.js +731 -0
- package/skills/usage-limits/scripts/pulse.js +24 -0
- package/skills/usage-limits/scripts/recommend.js +56 -5
- package/skills/usage-limits/scripts/sessionend.js +5 -1
- package/skills/usage-limits/scripts/statusline.js +305 -0
- package/skills/usage-limits/scripts/stop.js +5 -1
- package/skills/usage-limits/scripts/tally.js +4 -10
- package/skills/usage-limits/scripts/usage.js +477 -17
- package/skills/usage-limits/scripts/view.js +222 -0
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "usage-limits",
|
|
3
3
|
"displayName": "Usage Limits",
|
|
4
|
-
"version": "1.
|
|
4
|
+
"version": "1.11.2",
|
|
5
5
|
"description": "Puts your remaining Claude Code usage limit into Claude's context before every prompt, so it opens with what fits in the budget instead of starting work that gets cut off. Reports headroom as turns rather than percentages, prices a job before you start it, and detects your plan tier.",
|
|
6
6
|
"author": {
|
|
7
7
|
"name": "Ridelink",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "usage-limits",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.11.2",
|
|
4
4
|
"description": "Reports how much of your Codex usage limit is left as turns of work rather than a percentage, prices a job before you start it, and counts the other agents sharing the same budget.",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Ridelink",
|
package/README.md
CHANGED
|
@@ -39,9 +39,10 @@ you just asked for is going to finish, and answering that needs the request and
|
|
|
39
39
|
the budget in the same place. That place is the model's context, which is where
|
|
40
40
|
this puts them.
|
|
41
41
|
|
|
42
|
-
So: if you want to watch your usage, install a status line. This ships one
|
|
43
|
-
|
|
44
|
-
|
|
42
|
+
So: if you want to watch your usage, install a status line. This ships one
|
|
43
|
+
too, and a live panel that sits beside the chat, both drawn in Claude Code's
|
|
44
|
+
own colours from Claude Code's own numbers. If you want the thing spending the
|
|
45
|
+
budget to know it is spending the budget, that is what this is for.
|
|
45
46
|
|
|
46
47
|
## What it prints
|
|
47
48
|
|
|
@@ -275,30 +276,120 @@ trusted publishing over OIDC, so there is no publish token stored in the repo
|
|
|
275
276
|
or in CI. `npm version` also syncs the version in the plugin manifest, so the
|
|
276
277
|
marketplace and the npm package never disagree about which release is current.
|
|
277
278
|
|
|
278
|
-
##
|
|
279
|
+
## Right next to the chat
|
|
279
280
|
|
|
280
|
-
|
|
281
|
-
|
|
281
|
+
```
|
|
282
|
+
npx claude-usage-limits panel --open
|
|
283
|
+
```
|
|
282
284
|
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
285
|
+
That opens a narrow pane to the right of the one Claude Code is running in
|
|
286
|
+
(Windows Terminal, tmux, WezTerm, kitty, zellij and iTerm2 are all understood)
|
|
287
|
+
and draws the limits in it, live:
|
|
288
|
+
|
|
289
|
+
```
|
|
290
|
+
✻ Claude usage
|
|
291
|
+
Fable 5.1 · xhigh · working
|
|
292
|
+
|
|
293
|
+
Current session
|
|
294
|
+
███████░░░░░░░░░░░░░░░░░░░░░ 24%
|
|
295
|
+
resets in 4h 12m at 6:40 PM
|
|
296
|
+
|
|
297
|
+
Current week (all models)
|
|
298
|
+
█░░░░░░░░░░░░░░░░░░░░░░░░░░░ 4%
|
|
299
|
+
resets in 1d 5h at Sun 7:00 PM
|
|
300
|
+
|
|
301
|
+
Current week (Fable)
|
|
302
|
+
█░░░░░░░░░░░░░░░░░░░░░░░░░░░ 3%
|
|
303
|
+
resets in 1d 5h at Sun 7:00 PM
|
|
304
|
+
|
|
305
|
+
Sessions · 1 working, 1 idle
|
|
306
|
+
✳ Fable 5.1 usage-limits working
|
|
307
|
+
· Opus 5 ridelink idle 4m ago
|
|
308
|
+
|
|
309
|
+
live, updated 12s ago
|
|
310
|
+
q quit · r refresh
|
|
290
311
|
```
|
|
291
312
|
|
|
292
|
-
|
|
313
|
+
Four things about it are deliberate.
|
|
314
|
+
|
|
315
|
+
**It is drawn the way Claude Code draws things.** The colours are Claude
|
|
316
|
+
Code's own theme, read out of the CLI rather than approximated: the bar is the
|
|
317
|
+
one `/usage` paints, the title is the Claude orange, the spinner is Claude's
|
|
318
|
+
spinner with Claude's frames. A bar turns yellow at 80 percent and red at 90,
|
|
319
|
+
each window judged on its own. While Claude is working the title shimmers and
|
|
320
|
+
the spinner turns; while it waits, they stop. Under ultracode both go rainbow,
|
|
321
|
+
which is what Claude Code does with its max effort tag.
|
|
322
|
+
|
|
323
|
+
**The numbers are the ones Claude Code uses.** Every reading is the same GET
|
|
324
|
+
that `/usage` makes, with the login Claude Code already holds, plus the
|
|
325
|
+
rate-limit headers on Claude's own API responses whenever the status line
|
|
326
|
+
below is installed. Whichever is newer wins, and the footer says how old it
|
|
327
|
+
is. The week for one model (the Fable line above) only appears while that
|
|
328
|
+
model is the one running, because it cannot stop work on any other; when the
|
|
329
|
+
model cannot be told at all, nothing is hidden on a guess. The
|
|
330
|
+
reading is kept in `usage-limits-live.json`, and the report, the hooks and the
|
|
331
|
+
status line all prefer it whenever it is newer than Claude Code's own cache,
|
|
332
|
+
which can sit hours behind.
|
|
333
|
+
|
|
334
|
+
**It keeps drawing when things go wrong.** Offline, it shows the last reading
|
|
335
|
+
and says how old it is, and tries again at a widening interval. Signed out, it
|
|
336
|
+
says so in red and keeps checking, because Claude Code refreshes the login on
|
|
337
|
+
its own next call. Told to slow down by the endpoint, it waits exactly as long
|
|
338
|
+
as it was told. Too narrow a pane loses the breathing room, then the footer,
|
|
339
|
+
never the bars. Nothing in it refreshes or rotates the token, and the token is
|
|
340
|
+
never written anywhere by this plugin.
|
|
341
|
+
|
|
342
|
+
**It knows about the other Claudes.** Two windows share one limit, so the
|
|
343
|
+
panel lists every session this machine has heard from in the last quarter of
|
|
344
|
+
an hour: what it runs, where, and whether it is working right now, each with
|
|
345
|
+
its own spinner. The hooks are what say so (a prompt marks a session working,
|
|
346
|
+
every tool call keeps it so, the Stop hook marks it idle), so the list is live
|
|
347
|
+
without anyone polling anything. The status line adds `+1 working` when
|
|
348
|
+
another session is spending.
|
|
349
|
+
|
|
350
|
+
`panel` alone runs it in the current pane, `--once` prints one frame, `--json`
|
|
351
|
+
prints the fields, `--no-fetch` (or `USAGE_LIMITS_FETCH=off`) keeps it
|
|
352
|
+
entirely offline on the reading already on disk, and `--poll N` sets the
|
|
353
|
+
seconds between readings (30 while Claude works and 120 while it waits
|
|
354
|
+
otherwise). Installed as a plugin, `/usage-limits:panel` opens it from inside
|
|
355
|
+
the chat.
|
|
356
|
+
|
|
357
|
+
Not on the desktop app or claude.ai, which show the limits themselves. This is
|
|
358
|
+
for the terminal and the VS Code extension, where the only way to see them is
|
|
359
|
+
to ask with `/usage`.
|
|
360
|
+
|
|
361
|
+
## Status line
|
|
362
|
+
|
|
363
|
+
The same bars, one line under the prompt:
|
|
364
|
+
|
|
365
|
+
```
|
|
366
|
+
✻ Fable 5.1 · xhigh session ████░░░░░░ 42% week █░░░░░░░░░ 7% fable █░░░░░░░░░ 3% +1 working
|
|
367
|
+
```
|
|
293
368
|
|
|
294
369
|
```
|
|
295
|
-
|
|
370
|
+
npx claude-usage-limits statusline on
|
|
371
|
+
npx claude-usage-limits statusline off
|
|
296
372
|
```
|
|
297
373
|
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
374
|
+
`on` points Claude Code's `statusLine` setting at a small launcher in the
|
|
375
|
+
config directory that finds wherever the plugin is currently installed, so a
|
|
376
|
+
plugin update does not leave the status line pointing at a folder that has
|
|
377
|
+
gone. A status line that was already there is kept and printed above ours;
|
|
378
|
+
`--no-chain` replaces it instead, and `off` restores exactly what was there,
|
|
379
|
+
including nothing. `--refresh N` re-runs it every N seconds as well as on every
|
|
380
|
+
change, which keeps the spinner turning between responses at the cost of a
|
|
381
|
+
Node process every N seconds. The change applies to new sessions.
|
|
382
|
+
|
|
383
|
+
The line is also where the panel learns what Claude is doing. Claude Code
|
|
384
|
+
hands the status line the model in use, the effort level, and the rate limits
|
|
385
|
+
from its own response headers, and the line records them for the panel, which
|
|
386
|
+
never sees that JSON. It reads no transcripts and makes no network calls, so it
|
|
387
|
+
costs about a tenth of a second on every redraw. It shrinks to fit narrow
|
|
388
|
+
windows, honours `NO_COLOR` and Claude Code's `prefersReducedMotion`, and
|
|
389
|
+
prints nothing rather than an error if anything goes wrong.
|
|
390
|
+
|
|
391
|
+
The older one-line form is still there as `usage.js --status`, which prints
|
|
392
|
+
`5h 62% 1h 40m wk 75% 2d 4h` and prefixes `LOW` past 90 percent.
|
|
302
393
|
|
|
303
394
|
## It tells you where you stand, every time
|
|
304
395
|
|
|
@@ -331,6 +422,15 @@ explaining is pace: two days into a week you should be near 29 percent spent, so
|
|
|
331
422
|
60 percent means you will not last the week, and that is worth hearing at 60
|
|
332
423
|
rather than at 85.
|
|
333
424
|
|
|
425
|
+
The percentages behind the line are kept fresh too. If the reading on disk is
|
|
426
|
+
older than three minutes when a prompt goes in, the hook first takes the same
|
|
427
|
+
reading Claude Code takes for `/usage`, and the mid-turn pulse does the same
|
|
428
|
+
every two minutes through a long turn. That is what stops a burst of parallel
|
|
429
|
+
agents from emptying a window between two readings: eight of them once spent
|
|
430
|
+
half a window in five minutes while the line, seventeen minutes old, still
|
|
431
|
+
said 42 percent. Offline that is one quick failure and then a widening
|
|
432
|
+
backoff, never a wait on every prompt.
|
|
433
|
+
|
|
334
434
|
One limit worth knowing: the hook fires when a prompt is submitted, so a
|
|
335
435
|
message sent while Claude is already working does not refresh it. Claude Code
|
|
336
436
|
delivers those into the running turn without re-running hooks, which no plugin
|
|
@@ -353,6 +453,14 @@ minute, so it costs about 400ms cold and 120ms warm.
|
|
|
353
453
|
| `USAGE_LIMITS_PULSE` | on | `off` silences the mid-turn line; `always` prints it even when there is room. |
|
|
354
454
|
| `USAGE_LIMITS_PULSE_SECONDS` | 120 | How often the mid-turn line can fire. |
|
|
355
455
|
| `USAGE_LIMITS_TALLY` | on | Set to `off` to turn off the after-reply tally, the closing line and the session history. |
|
|
456
|
+
| `USAGE_LIMITS_FETCH` | on | `off` keeps the panel and the hooks off the network; they show the reading already on disk. |
|
|
457
|
+
| `USAGE_LIMITS_REFRESH` | 180 | Seconds a reading may age before the before-prompt hook takes a fresh one. The mid-turn pulse uses its own interval. |
|
|
458
|
+
| `USAGE_LIMITS_POLL` | 30 / 120 | Seconds between the panel's readings, working / idle. Never under 15. |
|
|
459
|
+
| `USAGE_LIMITS_MOTION` | on | `off` stops the spinner, the shimmer and the rainbow. Claude Code's `prefersReducedMotion` setting does the same. |
|
|
460
|
+
| `USAGE_LIMITS_STATUSLINE` | on | `off` blanks the status line while still recording the feed the panel reads. |
|
|
461
|
+
| `USAGE_LIMITS_CLOCK` | from settings | `12h` or `24h` for reset times; otherwise follows Claude Code's `timeFormat`. |
|
|
462
|
+
| `USAGE_LIMITS_COLOUR` | detected | `256` or `none` to override colour detection. `NO_COLOR` and `FORCE_COLOR` are honoured. |
|
|
463
|
+
| `USAGE_LIMITS_ASCII` | off | `1` draws the bars and the spinner with plain characters. |
|
|
356
464
|
|
|
357
465
|
## What a session cost
|
|
358
466
|
|
|
@@ -514,6 +622,18 @@ codex plugin marketplace add https://github.com/ridelink0/claude-code-usage-limi
|
|
|
514
622
|
codex plugin add usage-limits@usage-limits
|
|
515
623
|
```
|
|
516
624
|
|
|
625
|
+
The panel works under Codex too, GPT-6 Astra included:
|
|
626
|
+
|
|
627
|
+
```
|
|
628
|
+
npx claude-usage-limits panel --open --host codex
|
|
629
|
+
```
|
|
630
|
+
|
|
631
|
+
It reads Codex's own meter the way `/status` does, through a short-lived
|
|
632
|
+
`codex app-server`, and draws the same bars under the title `Codex usage`,
|
|
633
|
+
with the model named the way Codex names it. Codex has no status line and no
|
|
634
|
+
hooks, so there is no spinner for a working session and no Sessions list; the
|
|
635
|
+
numbers are the point.
|
|
636
|
+
|
|
517
637
|
### One thing is different, and it is worth being straight about
|
|
518
638
|
|
|
519
639
|
Under Claude Code the budget line arrives on its own, because a plugin can ship
|
|
@@ -542,6 +662,27 @@ Two smaller differences. There is no money column: Codex meters a share of an
|
|
|
542
662
|
allowance and never quotes a price, so the percentages stand alone. And
|
|
543
663
|
`lowpower` is Claude Code only, because it writes Claude's `settings.json`.
|
|
544
664
|
|
|
665
|
+
## VS Code
|
|
666
|
+
|
|
667
|
+
The Claude Code extension for VS Code shows the limits only when you ask with
|
|
668
|
+
`/usage`, and it does not render a custom status line. So there is an
|
|
669
|
+
extension of its own in [vscode/](vscode/): the same bars as a view that sits
|
|
670
|
+
directly under the Claude Code chat in the secondary side bar (it contributes
|
|
671
|
+
into the Claude Code extension's own view container, so there is no gap and
|
|
672
|
+
nothing to arrange), a status bar item with the percentages that turns yellow
|
|
673
|
+
and red at the same thresholds, the Sessions list, and the same animations in
|
|
674
|
+
CSS. It carries the plugin's scripts inside it, so it has no dependencies and
|
|
675
|
+
reads the same files and takes the same reading as the terminal panel.
|
|
676
|
+
|
|
677
|
+
```
|
|
678
|
+
cd vscode && npm run package
|
|
679
|
+
code --install-extension claude-usage-limits-<version>.vsix
|
|
680
|
+
```
|
|
681
|
+
|
|
682
|
+
The `.vsix` is attached to each GitHub release. It is not on the Marketplace
|
|
683
|
+
yet; that needs a publisher account, and the steps are in
|
|
684
|
+
[vscode/README.md](vscode/README.md).
|
|
685
|
+
|
|
545
686
|
## Where it works
|
|
546
687
|
|
|
547
688
|
Every surface of Claude Code on a machine shares one config directory, so
|
|
@@ -550,9 +691,9 @@ this reads all of them and does not care which one you are in:
|
|
|
550
691
|
| Surface | Works | Notes |
|
|
551
692
|
| --- | --- | --- |
|
|
552
693
|
| Terminal (`claude`) | yes | |
|
|
553
|
-
| VS Code extension | yes | |
|
|
694
|
+
| VS Code extension | yes | The VS Code extension above puts the bars under the chat and in the status bar. |
|
|
554
695
|
| JetBrains extension | yes | |
|
|
555
|
-
| Desktop app | yes | |
|
|
696
|
+
| Desktop app | yes | The budget line and the hooks. The panel, the status line and the VS Code extension are for the terminal and VS Code; the app shows the limits itself. |
|
|
556
697
|
| Headless (`claude -p`) | yes | Scripts run fine, but there are no slash commands, so `lowpower.js` is the only way to change effort. |
|
|
557
698
|
| Cloud and web sessions | partly | Those run on a remote machine with their own config directory. Percentages are per-account and stay correct; the pace is measured from whatever transcripts are local to wherever you run the script. |
|
|
558
699
|
|
|
@@ -600,8 +741,13 @@ Node 18 or newer, and a Claude Code recent enough to write
|
|
|
600
741
|
`cachedUsageUtilization` into `~/.claude.json`. If the report says it found no
|
|
601
742
|
snapshot, run `/usage` once inside Claude Code and it will be there.
|
|
602
743
|
|
|
603
|
-
Nothing is uploaded.
|
|
604
|
-
|
|
744
|
+
Nothing is uploaded. The report and the status line read only files already on
|
|
745
|
+
the machine. The panel, and the hooks when the reading on disk is older than a
|
|
746
|
+
few minutes, take the same reading Claude Code takes for `/usage`: they read
|
|
747
|
+
the login token Claude Code keeps and send it to Anthropic's usage endpoint,
|
|
748
|
+
nowhere else. The token is never written to disk by this plugin, never
|
|
749
|
+
printed, and never refreshed or rotated. `USAGE_LIMITS_FETCH=off` keeps all of
|
|
750
|
+
it offline, on the reading Claude Code itself last cached.
|
|
605
751
|
|
|
606
752
|
## How accurate is it
|
|
607
753
|
|
|
@@ -631,6 +777,24 @@ Good enough to plan with, not a bill. The honest caveats:
|
|
|
631
777
|
- The account's own list of limits is read as well as the per-window buckets,
|
|
632
778
|
so a per-model weekly such as `weekly (Fable)` shows up as a window of its
|
|
633
779
|
own, priced from that model's calls alone.
|
|
780
|
+
- A per-model weekly only counts against you while you are running that model.
|
|
781
|
+
One at 88 per cent is not your wall if you are working on Opus: nothing you
|
|
782
|
+
do moves it. Those windows are still listed, marked `not in use`, but they
|
|
783
|
+
are never picked as the binding window, never raised as a warning, never a
|
|
784
|
+
reason a forecast says the job does not fit, and never what puts `LOW` on the
|
|
785
|
+
status line. Start using that model and they come straight back. Nothing is
|
|
786
|
+
suppressed unless both sides are recognised: an unknown model in the setting,
|
|
787
|
+
or a weekly scoped to a model this table has never heard of, is treated as
|
|
788
|
+
live, because hiding a limit that can stop the work is worse than showing one
|
|
789
|
+
that cannot.
|
|
790
|
+
- The report also says what the room left buys in turns of each model, priced
|
|
791
|
+
from that model's own measured cost per turn, against the window its spend
|
|
792
|
+
lands in. Rows sharing a window are alternatives rather than additions. A
|
|
793
|
+
model that has only ever run as a subagent gets no projected turn count at
|
|
794
|
+
all - its errands are not turns - though what delegating to it has cost is
|
|
795
|
+
still reported. What each model cost is remembered in
|
|
796
|
+
`usage-limits-models.json`, one entry per family, so a session that opens on
|
|
797
|
+
a model it has not run this week still knows its price.
|
|
634
798
|
- The turn cost behind "turns of headroom" is a median over at least five
|
|
635
799
|
turns, so one compaction cannot define your pace.
|
|
636
800
|
- What a point of a window costs is learned once from the best sample seen and
|
|
@@ -670,15 +834,22 @@ skills/usage-limits/SKILL.md what the agent reads
|
|
|
670
834
|
skills/usage-limits/agents/ how Codex lists the skill
|
|
671
835
|
skills/usage-limits/scripts/ usage.js, brief.js, pulse.js, stop.js,
|
|
672
836
|
sessionend.js, tally.js, codex.js, host.js,
|
|
673
|
-
lowpower.js, install-codex-hook.js
|
|
837
|
+
lowpower.js, install-codex-hook.js,
|
|
838
|
+
recommend.js, panel.js, feed.js,
|
|
839
|
+
statusline.js, live.js, view.js, bars.js,
|
|
840
|
+
activity.js
|
|
674
841
|
skills/usage-limits/references/ the longer notes
|
|
675
842
|
hooks/hooks.json runs brief.js before each prompt, pulse.js
|
|
676
843
|
during long turns, stop.js after each reply
|
|
677
844
|
and sessionend.js when the session closes
|
|
678
845
|
commands/check.md the /usage-limits:check command
|
|
679
846
|
commands/session.md the /usage-limits:session command
|
|
847
|
+
commands/panel.md the /usage-limits:panel command
|
|
848
|
+
commands/statusline.md the /usage-limits:statusline command
|
|
680
849
|
bin/cli.js the npx entry point
|
|
681
850
|
tools/sync-version.js keeps the manifest version in step
|
|
851
|
+
vscode/ the VS Code extension; build.js copies the
|
|
852
|
+
scripts into vscode/lib and makes the vsix
|
|
682
853
|
test/ node --test, no dependencies
|
|
683
854
|
```
|
|
684
855
|
|
|
@@ -688,7 +859,7 @@ test/ node --test, no dependencies
|
|
|
688
859
|
node --test
|
|
689
860
|
```
|
|
690
861
|
|
|
691
|
-
|
|
862
|
+
469 tests over the pricing, the window arithmetic, plan and credit detection,
|
|
692
863
|
the status line, the before-prompt line, the mid-turn pulse, the after-reply tally and the session history, job forecasting,
|
|
693
864
|
per-project attribution, the Codex reader and its installer, the CLI,
|
|
694
865
|
packaging, and the settings save/restore.
|
package/bin/cli.js
CHANGED
|
@@ -18,6 +18,14 @@ const HELP = `claude-usage-limits - how much agent usage is left, and whether th
|
|
|
18
18
|
claude-usage-limits --host codex read Codex's limits instead
|
|
19
19
|
claude-usage-limits --host codex --refresh ask Codex for a live reading
|
|
20
20
|
|
|
21
|
+
claude-usage-limits panel live bars beside the chat; q quits
|
|
22
|
+
claude-usage-limits panel --open open it in a split pane to the right
|
|
23
|
+
claude-usage-limits panel --once one frame, for a pipe or a screenshot
|
|
24
|
+
|
|
25
|
+
claude-usage-limits statusline status is the status line installed
|
|
26
|
+
claude-usage-limits statusline on bars under the Claude Code prompt
|
|
27
|
+
claude-usage-limits statusline off put back what was there
|
|
28
|
+
|
|
21
29
|
claude-usage-limits lowpower status show the current effort setting
|
|
22
30
|
claude-usage-limits lowpower on lower effortLevel, remembering the old value
|
|
23
31
|
claude-usage-limits lowpower on --effort medium --model sonnet
|
|
@@ -30,7 +38,9 @@ const HELP = `claude-usage-limits - how much agent usage is left, and whether th
|
|
|
30
38
|
Reads the usage figures the agent already keeps on disk, plus its own session
|
|
31
39
|
history, to report the remaining headroom as turns of work. Works with Claude
|
|
32
40
|
Code and with Codex; the host is detected, or state it with --host. Nothing is
|
|
33
|
-
uploaded and
|
|
41
|
+
uploaded. The panel, and the hooks when the reading on disk has aged, take the
|
|
42
|
+
same reading Claude Code takes for /usage, with the login Claude Code already
|
|
43
|
+
holds, and send it nowhere else (USAGE_LIMITS_FETCH=off keeps it all offline).
|
|
34
44
|
|
|
35
45
|
https://github.com/ridelink0/claude-code-usage-limits
|
|
36
46
|
`;
|
|
@@ -58,6 +68,16 @@ function run(argv) {
|
|
|
58
68
|
return Promise.resolve(installer.main(args.slice(1)));
|
|
59
69
|
}
|
|
60
70
|
|
|
71
|
+
if (args[0] === 'panel') {
|
|
72
|
+
const panel = require('../skills/usage-limits/scripts/panel.js');
|
|
73
|
+
return Promise.resolve(panel.main(args.slice(1)));
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
if (args[0] === 'statusline') {
|
|
77
|
+
const statusline = require('../skills/usage-limits/scripts/statusline.js');
|
|
78
|
+
return Promise.resolve(statusline.main(args.slice(1)));
|
|
79
|
+
}
|
|
80
|
+
|
|
61
81
|
const usage = require('../skills/usage-limits/scripts/usage.js');
|
|
62
82
|
return Promise.resolve(usage.main(args));
|
|
63
83
|
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Open the live usage panel in a pane beside this chat
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
Run `node "${CLAUDE_PLUGIN_ROOT}/skills/usage-limits/scripts/panel.js" --open`.
|
|
6
|
+
|
|
7
|
+
It opens a narrow pane to the right of this one (Windows Terminal, tmux,
|
|
8
|
+
WezTerm, kitty, zellij or iTerm2) showing the current session, the current
|
|
9
|
+
week, and the week for the model in use when the account caps that model on
|
|
10
|
+
its own, as live bars in Claude's colours. If this terminal cannot be split it
|
|
11
|
+
prints the command to run in a second pane instead; pass that on to me.
|
|
12
|
+
|
|
13
|
+
Tell me in one line what happened and stop. Do not start other work as part
|
|
14
|
+
of this command.
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Put the usage bars under the prompt (on), take them out (off), or say which it is (status)
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
Run `node "${CLAUDE_PLUGIN_ROOT}/skills/usage-limits/scripts/statusline.js" $ARGUMENTS`.
|
|
6
|
+
With no argument it reports the current state.
|
|
7
|
+
|
|
8
|
+
It edits the `statusLine` entry in `settings.json` in the Claude config
|
|
9
|
+
directory (`~/.claude`, or `CLAUDE_CONFIG_DIR`) through a
|
|
10
|
+
temporary file, keeps a backup, and `off` restores exactly what was there. A
|
|
11
|
+
status line that was already set is kept and printed above ours. The change
|
|
12
|
+
applies to new Claude Code sessions, not this one.
|
|
13
|
+
|
|
14
|
+
Read the output back to me in one or two lines and stop. Do not start other
|
|
15
|
+
work as part of this command.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "claude-usage-limits",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.11.2",
|
|
4
4
|
"description": "Puts your remaining Claude Code usage limit into Claude's context before every prompt, so it opens with what fits in the budget instead of starting work that gets cut off. Reports headroom as turns rather than percentages, prices a job before you start it, and detects your plan tier.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"claude",
|
|
@@ -110,6 +110,14 @@ from the start of the turn. A message sent while you are already working does
|
|
|
110
110
|
not fire it again: it arrives without a budget line, and the numbers you are
|
|
111
111
|
holding are now older than they look.
|
|
112
112
|
|
|
113
|
+
The reading itself is kept fresh: the hook takes the same reading Claude Code
|
|
114
|
+
takes for `/usage` when the one on disk is older than three minutes, and the
|
|
115
|
+
mid-turn pulse does the same every two minutes through a long turn. So the
|
|
116
|
+
figures are as good as `/usage` at those moments. What no hook can do is fire
|
|
117
|
+
between them, and a burst of parallel agents can spend a great deal in the
|
|
118
|
+
gap: eight workflow agents once emptied half a 5-hour window in five minutes.
|
|
119
|
+
Spawn agents knowing that each fresh context re-reads what you already hold.
|
|
120
|
+
|
|
113
121
|
That matters most when it is the one thing you are about to assert. Re-check
|
|
114
122
|
before saying a job fits, if any of these are true:
|
|
115
123
|
|
|
@@ -202,6 +210,22 @@ when a window that is not binding sits near its wall, say so and weigh it. The
|
|
|
202
210
|
hook flags those. Running the weekly out to save a few turns of the 5-hour
|
|
203
211
|
window is a bad trade even though the 5-hour is what runs out first.
|
|
204
212
|
|
|
213
|
+
The exception is a weekly that caps one model. `weekly (Fable)` at 88 per cent
|
|
214
|
+
is not your wall while you are working on Opus - nothing you do moves it, and
|
|
215
|
+
doing less work will not un-spend it. The report marks those `not in use` and
|
|
216
|
+
the hook leaves them out of what it asks you to weigh. Do not weigh them back
|
|
217
|
+
in. They matter again the moment you switch to that model, and that is when
|
|
218
|
+
they come back.
|
|
219
|
+
|
|
220
|
+
That cuts both ways, and the second half is the useful one: when the window
|
|
221
|
+
that binds is a per-model weekly, the same work on another model draws on a
|
|
222
|
+
different window. The report's **Model headroom** table says what the room left
|
|
223
|
+
buys in turns of each model, priced from what that model has really cost here.
|
|
224
|
+
Moving mechanical bulk onto a model with room is not doing less work - it is
|
|
225
|
+
the same work against a wall that is further away, which is the one economy
|
|
226
|
+
worth making. A model with no turn count in that table has only ever run as a
|
|
227
|
+
subagent; its errands are not turns, so there is nothing to project from.
|
|
228
|
+
|
|
205
229
|
One thing to get right: **quote the binding window, not the roomiest one.**
|
|
206
230
|
Two windows run at once and they are rarely in the same place. The turns of
|
|
207
231
|
headroom and the reset time belong to whichever runs out first. Putting the
|
|
@@ -419,6 +443,13 @@ Do not run the report on every prompt. Once at the start of a long piece of
|
|
|
419
443
|
work, and again if the job grows or something starts looping. The report costs
|
|
420
444
|
a turn, which is the thing it is trying to save.
|
|
421
445
|
|
|
446
|
+
The panel (`scripts/panel.js --open`, or `/usage-limits:panel`) and the status
|
|
447
|
+
line (`scripts/statusline.js on`) are for the person watching, not for you.
|
|
448
|
+
Nothing in them changes what you should do, and they draw from the same
|
|
449
|
+
reading the budget line already gave you, so do not open or install them
|
|
450
|
+
unless asked. When asked, run the command, say in one line what it did, and
|
|
451
|
+
stop.
|
|
452
|
+
|
|
422
453
|
## Files
|
|
423
454
|
|
|
424
455
|
| Path | What it is |
|
|
@@ -435,4 +466,9 @@ a turn, which is the thing it is trying to save.
|
|
|
435
466
|
| `scripts/lowpower.js` | `status`, `on`, `off`. Restores what it replaced. Claude Code only. |
|
|
436
467
|
| `scripts/recommend.js` | The chooser behind `usage.js --recommend`: posture, then the effort and model commands for each lever. Not meant to be called by hand. |
|
|
437
468
|
| `references/tactics.md` | Every lever that lowers cost, and why it works. |
|
|
469
|
+
| `scripts/panel.js` | The live panel beside the chat: `--open` puts it in a split pane to the right, `--once` prints one frame, `--json` the fields. For the person, not for you; open it only when asked. |
|
|
470
|
+
| `scripts/statusline.js` | `status`, `on`, `off`. Puts the bars under the prompt and restores what was there. |
|
|
471
|
+
| `scripts/feed.js` | The status line command Claude Code runs. Not meant to be called by hand. |
|
|
472
|
+
| `scripts/live.js` | The usage reading itself, taken the way Claude Code takes it for `/usage`, kept in `usage-limits-live.json` where `collect()` prefers it when newer than the cache. |
|
|
473
|
+
| `scripts/view.js`, `scripts/bars.js`, `scripts/activity.js` | The display model, the drawing in Claude's colours, and the working/idle marks the hooks leave for the panel. Not meant to be called by hand. |
|
|
438
474
|
| `references/how-it-works.md` | Where the numbers come from and where they are soft. |
|
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
# Where the numbers come from
|
|
2
2
|
|
|
3
|
-
Everything is read from local files
|
|
4
|
-
|
|
3
|
+
Everything is read from local files, with one exception: the panel, and the
|
|
4
|
+
hooks when the reading on disk is older than a few minutes, take the same
|
|
5
|
+
reading Claude Code takes for `/usage`, which sends the login token to
|
|
6
|
+
Anthropic's usage endpoint and nowhere else (the last section of this file).
|
|
7
|
+
Nothing else is sent anywhere, and `USAGE_LIMITS_FETCH=off` stops that too.
|
|
5
8
|
|
|
6
9
|
## Sources
|
|
7
10
|
|
|
@@ -36,6 +39,68 @@ window of its own, labelled `weekly (Fable)` and priced from that model's
|
|
|
36
39
|
calls alone; `is_active` breaks ties in the binding choice; and a bucket that
|
|
37
40
|
quotes `limit_dollars` is priced from that directly instead of being calibrated.
|
|
38
41
|
|
|
42
|
+
A per-model weekly caps one model family and nothing else, so it can only stop
|
|
43
|
+
work that uses that family. Which families are in use is taken from the model
|
|
44
|
+
in `settings.json` (and `ANTHROPIC_MODEL`), plus every model this session has
|
|
45
|
+
actually run, subagents included. Another session's models are not counted:
|
|
46
|
+
what another window is burning is not this one's constraint. A setting that
|
|
47
|
+
names a strategy rather than a model resolves to every model it runs, so
|
|
48
|
+
`opusplan` counts as both Opus and Sonnet.
|
|
49
|
+
|
|
50
|
+
A window for a family that is not in use is still listed everywhere it was
|
|
51
|
+
listed before - it is real, and switching to that model would make it bite -
|
|
52
|
+
but it is never chosen as the binding window, never raised as a warning, never
|
|
53
|
+
a reason a forecast says the job does not fit, and never what puts `LOW` on the
|
|
54
|
+
status line. It is marked `not in use` in the report and "(not this session's
|
|
55
|
+
model)" in the before-prompt line.
|
|
56
|
+
|
|
57
|
+
Nothing is suppressed unless both sides are recognised. If the model in use
|
|
58
|
+
cannot be worked out, or the weekly is scoped to a model this table has never
|
|
59
|
+
heard of, the window is treated as live. Hiding a limit that can stop the work
|
|
60
|
+
is the one failure worse than over-reporting one.
|
|
61
|
+
|
|
62
|
+
The one-line `--status` readout is the exception worth knowing about: it reads
|
|
63
|
+
no transcripts by design, so the only thing it can know about the running
|
|
64
|
+
model is the setting. It therefore shows every per-model weekly and simply
|
|
65
|
+
does not let an idle one raise `LOW`. The status line proper (`feed.js`) is
|
|
66
|
+
told the model by Claude Code itself and needs no such caution.
|
|
67
|
+
|
|
68
|
+
## Model headroom
|
|
69
|
+
|
|
70
|
+
How much room is left is half the question; what that room buys is the other
|
|
71
|
+
half, and the answer differs by model. The snapshot cannot say: it has no model
|
|
72
|
+
dimension at all. Every transcript line carries its model, so each family is
|
|
73
|
+
joined to the window its spend lands in - its own weekly where the account
|
|
74
|
+
gives it one, the shared weekly otherwise - and priced from its own turns.
|
|
75
|
+
|
|
76
|
+
Rows that share a window are alternatives, not additions. They describe the
|
|
77
|
+
same remaining room spent on different models.
|
|
78
|
+
|
|
79
|
+
No turn count is projected for a model that has never taken a turn of its own.
|
|
80
|
+
A family that has only ever run as a subagent has errands to price, not turns:
|
|
81
|
+
114 Sonnet calls on one machine averaged under two cents because they were
|
|
82
|
+
one-shot lookups, and dividing the remaining budget by that promised twenty-two
|
|
83
|
+
thousand Sonnet turns. The row still reports what delegating to that model has
|
|
84
|
+
cost, because that is measured; it does not project from it.
|
|
85
|
+
|
|
86
|
+
What a turn of each model cost is kept in `usage-limits-models.json` in the
|
|
87
|
+
config directory, one entry per family so it cannot grow, stamped with the plan
|
|
88
|
+
and read back through the same guard as the window calibration. It exists so a
|
|
89
|
+
session that opens on a model it has not run this week still knows what that
|
|
90
|
+
model costs. It is deliberately not written into `usage-limits-calibration.json`:
|
|
91
|
+
that file means one thing, the plan's blended price of a point, and three
|
|
92
|
+
callers read it on that basis.
|
|
93
|
+
|
|
94
|
+
There is no per-turn log. Every model figure comes from the transcripts, which
|
|
95
|
+
already hold it; an append-only ledger would grow without bound and record
|
|
96
|
+
nothing new.
|
|
97
|
+
|
|
98
|
+
Nothing here claims the meter weights a dollar of one model differently from a
|
|
99
|
+
dollar of another. No published or observed source shows that, and the two
|
|
100
|
+
prices per point this plugin learns - one for a shared weekly, one for a scoped
|
|
101
|
+
one - are percentages of two differently sized allowances, which says nothing
|
|
102
|
+
about weighting either way.
|
|
103
|
+
|
|
39
104
|
The plan name comes from `oauthAccount.organizationType` in the same file.
|
|
40
105
|
Current effort and model come from `settings.json` in the config directory.
|
|
41
106
|
|
|
@@ -206,3 +271,51 @@ be wrong about a budget.
|
|
|
206
271
|
|
|
207
272
|
Rows priced this way are marked with an asterisk in the report, so an assumed
|
|
208
273
|
rate never quietly passes for a published one.
|
|
274
|
+
|
|
275
|
+
## The live reading, and which reading wins
|
|
276
|
+
|
|
277
|
+
Claude Code takes its own `/usage` figures with one GET to
|
|
278
|
+
`https://api.anthropic.com/api/oauth/usage`, sending the login token it holds
|
|
279
|
+
as a bearer token with the `anthropic-beta: oauth-2025-04-20` header and a
|
|
280
|
+
five second timeout. `scripts/live.js` makes exactly that call, reads the
|
|
281
|
+
token from `.credentials.json` inside the config directory (or the
|
|
282
|
+
`Claude Code-credentials` keychain entry on macOS), and writes the answer to
|
|
283
|
+
`usage-limits-live.json` with the account it belongs to. The token is used for
|
|
284
|
+
that one request and nothing else: never written, never printed, never
|
|
285
|
+
refreshed. If it has expired the endpoint says 401, the panel says "sign in to
|
|
286
|
+
Claude Code again", and Claude Code fixes it on its own next call.
|
|
287
|
+
|
|
288
|
+
`collect()` then has two snapshots of the same account, Claude Code's
|
|
289
|
+
`cachedUsageUtilization` and the live file, and takes whichever is newer. The
|
|
290
|
+
choice is `preferLive()`: the live file loses when it is older, when it names a
|
|
291
|
+
different account, or when its timestamp is more than a minute in the future.
|
|
292
|
+
`snapshotSource` in the report says which one was used. Everything downstream -
|
|
293
|
+
the budget line, the pulse, the status line, the forecast, the recommendation -
|
|
294
|
+
goes through `collect()`, so they all see the newer reading.
|
|
295
|
+
|
|
296
|
+
The status line has a third source that is fresher than either: Claude Code
|
|
297
|
+
hands it `rate_limits` built from the `anthropic-ratelimit-unified-*` headers
|
|
298
|
+
on its own API responses, for the session and the shared week. `feed.js`
|
|
299
|
+
records those per session in `usage-limits-feed.json`, along with the model
|
|
300
|
+
and effort in use, and `view.js` takes the newest of headers, live reading and
|
|
301
|
+
cache for each window. The per-model weeks are only in the endpoint's answer,
|
|
302
|
+
so they come from the live file or the cache.
|
|
303
|
+
|
|
304
|
+
Which per-model week to show is decided by the model in use, never by the
|
|
305
|
+
account's `is_active` flag: that flag marks the limit currently binding, not
|
|
306
|
+
whether the model is running. The status line's `model.id` is certain, the
|
|
307
|
+
`model` setting is the fallback, and with neither nothing is hidden.
|
|
308
|
+
|
|
309
|
+
Whether Claude is working comes from the hooks: the prompt hook marks the
|
|
310
|
+
session working (and whether the prompt said `ultracode`), every tool call
|
|
311
|
+
keeps it so, and the Stop and SessionEnd hooks mark it idle. Marks live in
|
|
312
|
+
`usage-limits-activity.json`, one per session, and a session silent for fifteen
|
|
313
|
+
minutes counts as idle whatever it last said, because a crash never sends
|
|
314
|
+
Stop.
|
|
315
|
+
|
|
316
|
+
The sessions list joins those marks with the status line feed (model, effort,
|
|
317
|
+
directory), the Stop hook's tally (project, cost, turns) and the prompt hook's
|
|
318
|
+
cache (when it last prompted), one row per session id, in
|
|
319
|
+
`activity.combine()`. A session is listed if any of them saw it in the last
|
|
320
|
+
fifteen minutes and is working only if its own mark says so and is fresh, so
|
|
321
|
+
the header, the list and the `+N working` on the status line always agree.
|