claude-usage-limits 1.13.2 → 1.14.0
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.
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "usage-limits",
|
|
3
3
|
"displayName": "Usage Limits",
|
|
4
|
-
"version": "1.
|
|
4
|
+
"version": "1.14.0",
|
|
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.14.0",
|
|
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
|
@@ -1010,3 +1010,33 @@ licence is there for. Do not wait on me to add something for you.
|
|
|
1010
1010
|
## License
|
|
1011
1011
|
|
|
1012
1012
|
MIT. See [LICENSE](LICENSE).
|
|
1013
|
+
|
|
1014
|
+
## The wall is not the end of the budget
|
|
1015
|
+
|
|
1016
|
+
A full window is not always a reason to stop, and the plugin now says which.
|
|
1017
|
+
|
|
1018
|
+
A **per-model weekly** counts turns by that model only. It is not your budget,
|
|
1019
|
+
it is that model's: lowering effort frees nothing, and switching model retires
|
|
1020
|
+
the window outright while every other window carries on. A **shared window**
|
|
1021
|
+
follows the account wherever the model goes, so a switch buys nothing and
|
|
1022
|
+
effort is the lever instead.
|
|
1023
|
+
|
|
1024
|
+
Once the binding window is half gone the budget line names the lever that
|
|
1025
|
+
applies, which window would bind after the switch and how full it is, and the
|
|
1026
|
+
command:
|
|
1027
|
+
|
|
1028
|
+
```
|
|
1029
|
+
This window is scoped to one model, so it is not the account's budget:
|
|
1030
|
+
switching model retires it. After a switch the binding window would be weekly
|
|
1031
|
+
at 77 per cent. Use /model opus.
|
|
1032
|
+
```
|
|
1033
|
+
|
|
1034
|
+
At the wall it goes further and says outright that you are not out of budget
|
|
1035
|
+
and must not stop as though you were. It refuses to claim an escape it cannot
|
|
1036
|
+
evidence: trading an 89 for an 87 is a lateral move, not a way out, and with no
|
|
1037
|
+
other readable window there is nothing behind the claim, so it says nothing.
|
|
1038
|
+
|
|
1039
|
+
This exists because of a real session. The Fable weekly hit 89 per cent, the
|
|
1040
|
+
line said the budget was nearly gone, and the work stopped - with the 5-hour
|
|
1041
|
+
window at 46 and every other model untouched. One command would have carried it
|
|
1042
|
+
on.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "claude-usage-limits",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.14.0",
|
|
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",
|
|
@@ -370,7 +370,39 @@ effort setting does not control any of it:
|
|
|
370
370
|
`references/tactics.md` has the full list and the billing reasons behind each
|
|
371
371
|
one.
|
|
372
372
|
|
|
373
|
-
## 5.
|
|
373
|
+
## 5. The wall is not the end of the budget: switch, do not stop
|
|
374
|
+
|
|
375
|
+
Before treating a full window as a reason to stop, check what kind of window it
|
|
376
|
+
is. There are two, and only one of them is the account's budget.
|
|
377
|
+
|
|
378
|
+
- **A per-model weekly** (`weekly (Fable)`, `weekly (Opus)`, `weekly (Sonnet)`)
|
|
379
|
+
counts turns by *that model only*. It is not your budget, it is that model's.
|
|
380
|
+
Lowering effort does not free a single point of it. **Switching model retires
|
|
381
|
+
it outright** - `/model opus`, `/model sonnet`, or
|
|
382
|
+
`node scripts/lowpower.js on --model <id>`. Every other window carries on
|
|
383
|
+
exactly as before.
|
|
384
|
+
- **A shared window** (the 5-hour, the all-models weekly) follows the account
|
|
385
|
+
wherever the model goes, so a switch buys nothing. Here the lever is
|
|
386
|
+
**effort**: `/effort medium` measured six times cheaper a turn than ultra on
|
|
387
|
+
this account. `node scripts/usage.js --recommend` names both levers with the
|
|
388
|
+
commands.
|
|
389
|
+
|
|
390
|
+
The budget line does this arithmetic for you. Once the binding window is half
|
|
391
|
+
gone it says which lever applies, and at the wall it says outright that you are
|
|
392
|
+
not out of budget and must not stop as though you were. When it does, the
|
|
393
|
+
sequence is: switch, say in one line that you switched and why, carry on with
|
|
394
|
+
the whole request at full quality.
|
|
395
|
+
|
|
396
|
+
This is written down because it was got wrong. A session ended with the Fable
|
|
397
|
+
weekly at 89 per cent and the line saying the budget was nearly gone - while the
|
|
398
|
+
5-hour sat at 46 and every other model on the account was untouched. One command
|
|
399
|
+
would have carried it on. Stopping there was not caution; it was quitting with a
|
|
400
|
+
reason that sounded like one.
|
|
401
|
+
|
|
402
|
+
Only when the switch is genuinely unavailable - no other window has room, or the
|
|
403
|
+
user has ruled it out - does the checkpoint below apply.
|
|
404
|
+
|
|
405
|
+
## 6. Checkpoint before the wall
|
|
374
406
|
|
|
375
407
|
When the binding window is under roughly 10 percent, or under about ten turns
|
|
376
408
|
of headroom, keep working and start keeping the work landable:
|
|
@@ -389,7 +421,7 @@ afternoon, so there is no longer anything to buy by winding down.
|
|
|
389
421
|
The one thing not to economise on is the handoff itself. Everything else can be
|
|
390
422
|
picked up next session; a session that ends without one cannot.
|
|
391
423
|
|
|
392
|
-
##
|
|
424
|
+
## 7. The relay: when the handoff picks itself up
|
|
393
425
|
|
|
394
426
|
If a relay is armed, the budget line says so, and the shape of the last hour
|
|
395
427
|
changes. The handoff stops being a note for a person to find and becomes the
|
|
@@ -565,6 +565,26 @@ function briefText(parts) {
|
|
|
565
565
|
}
|
|
566
566
|
if (parts.othersSummary) sentences.push('Other windows: ' + parts.othersSummary + '.');
|
|
567
567
|
|
|
568
|
+
// Being at the wall and being out of budget are different things, and the
|
|
569
|
+
// difference is a command. Said as soon as the window is half gone, so it is
|
|
570
|
+
// already known by the time it matters.
|
|
571
|
+
const escape = parts.escape;
|
|
572
|
+
const escapeText =
|
|
573
|
+
escape && escape.kind === 'model'
|
|
574
|
+
? 'This window is scoped to one model, so it is not the account\'s budget: switching model retires it. ' +
|
|
575
|
+
(escape.nextLabel
|
|
576
|
+
? 'After a switch the binding window would be ' + escape.nextLabel + ' at ' + escape.nextPercent + ' per cent. '
|
|
577
|
+
: '') +
|
|
578
|
+
'Use /model ' + (escape.suggest || '<another model>') + ' (or scripts/lowpower.js on --model <id>).'
|
|
579
|
+
: escape && escape.kind === 'effort'
|
|
580
|
+
? 'A model switch does not free this window - it follows the account - but effort does: ' +
|
|
581
|
+
escape.to + ' measured ' + (escape.multiple ? escape.multiple + 'x ' : '') + 'cheaper a turn than ' +
|
|
582
|
+
(escape.from || 'the current effort') + '. Use /effort ' + escape.to + '.'
|
|
583
|
+
: null;
|
|
584
|
+
if (escapeText && parts.binding && Number.isFinite(parts.binding.percentUsed) && parts.binding.percentUsed >= HALF_SPENT) {
|
|
585
|
+
sentences.push(escapeText);
|
|
586
|
+
}
|
|
587
|
+
|
|
568
588
|
// A window that is not binding can still be the expensive one to exhaust.
|
|
569
589
|
if (parts.critical && parts.critical.length) {
|
|
570
590
|
for (const other of parts.critical) {
|
|
@@ -668,7 +688,18 @@ function briefText(parts) {
|
|
|
668
688
|
// go, keep a note of where things stand - not to shrink the work until it is
|
|
669
689
|
// guaranteed to fit.
|
|
670
690
|
const instruction =
|
|
671
|
-
|
|
691
|
+
// The escape outranks everything below it. A session that stops while a
|
|
692
|
+
// command would have carried it on has not been careful, it has quit - and
|
|
693
|
+
// that is a real session: the Fable weekly hit 89 per cent, the line said
|
|
694
|
+
// the budget was nearly gone, and the work ended with the five-hour window
|
|
695
|
+
// at 46 and every other model untouched.
|
|
696
|
+
escapeText && (parts.pressure === 'tight' || parts.pressure === 'gone')
|
|
697
|
+
? 'This window is nearly gone, but you are not out of budget and you must ' +
|
|
698
|
+
'not stop as though you were. ' + escapeText + ' Do that, say in one ' +
|
|
699
|
+
'line that you switched and why, and carry on with the whole request at ' +
|
|
700
|
+
'full quality. Only if the switch is impossible or the user has ruled it ' +
|
|
701
|
+
'out: save the work, write the handoff, and say what is left.'
|
|
702
|
+
: parts.pressure === 'gone'
|
|
672
703
|
? 'The budget is gone, so nothing further will run. Save what exists and ' +
|
|
673
704
|
'write the handoff: what is finished, what is next and in what order, ' +
|
|
674
705
|
'which files are mid-change, and when the window resets.' +
|
|
@@ -917,6 +948,9 @@ async function run(now, hookInput) {
|
|
|
917
948
|
turnsLeft: binding && Number.isFinite(binding.turnsLeft) ? binding.turnsLeft : null,
|
|
918
949
|
session: data.session,
|
|
919
950
|
othersSummary: summariseOthers(data.windows, binding && binding.key),
|
|
951
|
+
// The way out that is not stopping. Cached with the rest of the view
|
|
952
|
+
// because it is derived from the same one pass over the windows.
|
|
953
|
+
escape: usage.escapeRoute(data.windows, binding, data.effortWarning || null),
|
|
920
954
|
// Every window, trimmed to the cacheable fields, so the corrected reading
|
|
921
955
|
// can be recorded for all three columns of the status line on a cache
|
|
922
956
|
// hit too. Recording the binding window alone left the other two at
|
|
@@ -996,6 +1030,7 @@ async function run(now, hookInput) {
|
|
|
996
1030
|
? familyLabel(binding.family)
|
|
997
1031
|
: null,
|
|
998
1032
|
othersSummary: view.othersSummary,
|
|
1033
|
+
escape: view.escape || null,
|
|
999
1034
|
turnsLeft: view.turnsLeft,
|
|
1000
1035
|
effortWarning: view.effortWarning || null,
|
|
1001
1036
|
// Outside the cache: it is cheap, and it belongs to the other agent's
|
|
@@ -2091,6 +2091,64 @@ function criticalOthers(windows, bindingKey, threshold) {
|
|
|
2091
2091
|
);
|
|
2092
2092
|
}
|
|
2093
2093
|
|
|
2094
|
+
// The way out that is not stopping.
|
|
2095
|
+
//
|
|
2096
|
+
// This exists because of a session that ended for no reason. The Fable weekly
|
|
2097
|
+
// was at 89 per cent and binding, the line said the budget was nearly gone, and
|
|
2098
|
+
// the work stopped - while the five-hour window sat at 46 and every other model
|
|
2099
|
+
// on the account was untouched. A per-model weekly is not the account's budget.
|
|
2100
|
+
// It is one model's, and switching model retires it outright.
|
|
2101
|
+
//
|
|
2102
|
+
// So: when the window that binds is scoped to a model, say which window would
|
|
2103
|
+
// bind after a switch and how full it is. When it is shared, a model switch
|
|
2104
|
+
// changes nothing and the lever is effort instead. Either way the point is the
|
|
2105
|
+
// same - being at the wall is not the same as being out of budget, and an agent
|
|
2106
|
+
// that cannot tell the difference stops early and calls it caution.
|
|
2107
|
+
function escapeRoute(windows, binding, effortNote) {
|
|
2108
|
+
if (!binding || binding.percentUsed === null || binding.percentUsed === undefined) return null;
|
|
2109
|
+
const live = (windows || []).filter(
|
|
2110
|
+
(w) => w && w.percentUsed !== null && w.percentUsed !== undefined && !w.stale && w.key !== binding.key
|
|
2111
|
+
);
|
|
2112
|
+
|
|
2113
|
+
if (binding.family) {
|
|
2114
|
+
// Everything that would still apply once this model is no longer the one
|
|
2115
|
+
// running: the shared windows, plus any other model's weekly.
|
|
2116
|
+
const after = live.filter((w) => w.family !== binding.family);
|
|
2117
|
+
const next = after.length
|
|
2118
|
+
? after.reduce((worst, w) => (w.percentUsed > worst.percentUsed ? w : worst))
|
|
2119
|
+
: null;
|
|
2120
|
+
// Only worth calling an escape if what replaces it is meaningfully emptier.
|
|
2121
|
+
// Trading an 89 for an 87 is not a way out, it is a lateral move. And with
|
|
2122
|
+
// no other readable window there is no evidence a switch helps at all: it
|
|
2123
|
+
// is true that the scoped window would retire, but "you have room" is a
|
|
2124
|
+
// claim, and a claim with nothing behind it is the thing not to make.
|
|
2125
|
+
if (!next || next.percentUsed >= binding.percentUsed - 10) return null;
|
|
2126
|
+
const roomier = after
|
|
2127
|
+
.filter((w) => w.family && w.family !== binding.family)
|
|
2128
|
+
.sort((a, b) => a.percentUsed - b.percentUsed)[0] || null;
|
|
2129
|
+
return {
|
|
2130
|
+
kind: 'model',
|
|
2131
|
+
frees: binding.label || binding.key,
|
|
2132
|
+
family: binding.family,
|
|
2133
|
+
nextLabel: next ? next.label || next.key : null,
|
|
2134
|
+
nextPercent: next ? Math.round(next.percentUsed) : null,
|
|
2135
|
+
suggest: roomier && roomier.family ? roomier.family : null,
|
|
2136
|
+
};
|
|
2137
|
+
}
|
|
2138
|
+
|
|
2139
|
+
// A shared window follows the account wherever the model goes, so the only
|
|
2140
|
+
// lever left is how dear a turn is.
|
|
2141
|
+
if (effortNote && effortNote.cheaper && effortNote.cheaper.effort) {
|
|
2142
|
+
return {
|
|
2143
|
+
kind: 'effort',
|
|
2144
|
+
from: effortNote.effort || null,
|
|
2145
|
+
to: effortNote.cheaper.effort,
|
|
2146
|
+
multiple: Number.isFinite(effortNote.cheaper.multiple) ? effortNote.cheaper.multiple : null,
|
|
2147
|
+
};
|
|
2148
|
+
}
|
|
2149
|
+
return null;
|
|
2150
|
+
}
|
|
2151
|
+
|
|
2094
2152
|
// The window that will stop the work first.
|
|
2095
2153
|
function bindingWindow(windows) {
|
|
2096
2154
|
// A per-model weekly for a model that is not running cannot be the window
|
|
@@ -3681,6 +3739,7 @@ module.exports = {
|
|
|
3681
3739
|
lastRejections,
|
|
3682
3740
|
bindingWindow,
|
|
3683
3741
|
criticalOthers,
|
|
3742
|
+
escapeRoute,
|
|
3684
3743
|
betterCalibration,
|
|
3685
3744
|
calibrationForPlan,
|
|
3686
3745
|
stampPlan,
|