claude-usage-limits 1.18.0 → 1.23.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.
- package/.claude-plugin/plugin.json +1 -1
- package/.codex-plugin/plugin.json +1 -1
- package/README.md +220 -2
- package/bin/cli.js +16 -0
- package/commands/usage-mode.md +64 -0
- package/hooks/hooks.json +1 -1
- package/package.json +1 -1
- package/skills/usage-limits/SKILL.md +166 -18
- package/skills/usage-limits/references/tactics.md +40 -9
- package/skills/usage-limits/scripts/agy-hook.js +175 -0
- package/skills/usage-limits/scripts/brief.js +406 -46
- package/skills/usage-limits/scripts/ceiling.js +191 -0
- package/skills/usage-limits/scripts/codex-lowpower.js +95 -4
- package/skills/usage-limits/scripts/codex.js +87 -6
- package/skills/usage-limits/scripts/drift.js +254 -0
- package/skills/usage-limits/scripts/feed.js +23 -1
- package/skills/usage-limits/scripts/host.js +23 -3
- package/skills/usage-limits/scripts/install-antigravity.js +215 -0
- package/skills/usage-limits/scripts/install-codex-hook.js +22 -2
- package/skills/usage-limits/scripts/lowpower.js +48 -0
- package/skills/usage-limits/scripts/mode.js +1637 -0
- package/skills/usage-limits/scripts/pulse.js +254 -17
- package/skills/usage-limits/scripts/reading.js +12 -3
- package/skills/usage-limits/scripts/sessionend.js +8 -0
- package/skills/usage-limits/scripts/stop.js +43 -0
- package/skills/usage-limits/scripts/usage.js +364 -17
- package/skills/usage-limits/scripts/view.js +4 -0
- package/skills/usage-limits/scripts/voice.js +10 -1
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "usage-limits",
|
|
3
3
|
"displayName": "Usage Limits",
|
|
4
|
-
"version": "1.
|
|
4
|
+
"version": "1.23.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.23.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
|
@@ -839,6 +839,109 @@ and are counted together. On this machine the transcripts carry both `cli` and
|
|
|
839
839
|
Windows, macOS, and Linux all work. `CLAUDE_CONFIG_DIR` is honoured if you have
|
|
840
840
|
moved the config directory.
|
|
841
841
|
|
|
842
|
+
## Budget modes
|
|
843
|
+
|
|
844
|
+
This plugin is not free. It puts a line into the model's context before every
|
|
845
|
+
prompt, refreshes readings after tool calls, and keeps a status line alive. A
|
|
846
|
+
mode called "save tokens" that still injects four hundred tokens of advice per
|
|
847
|
+
turn is not saving anything - it is charging you for the advice about saving.
|
|
848
|
+
|
|
849
|
+
So a mode changes two things, not one: what the plugin tells the agent to do,
|
|
850
|
+
and what it costs to say it.
|
|
851
|
+
|
|
852
|
+
```
|
|
853
|
+
claude-usage-limits mode which one, where it came from
|
|
854
|
+
claude-usage-limits mode max set it
|
|
855
|
+
claude-usage-limits mode off --guard 95 off, except one line near the wall
|
|
856
|
+
claude-usage-limits mode auto pick from pressure, always reported
|
|
857
|
+
claude-usage-limits mode --list all four, and the aliases
|
|
858
|
+
claude-usage-limits mode --ledger measured cost per turn, per mode
|
|
859
|
+
```
|
|
860
|
+
|
|
861
|
+
| mode | what it does | what it costs |
|
|
862
|
+
| --- | --- | --- |
|
|
863
|
+
| `max` | fewest tokens that can still finish the job | one terse line, readings every 10 minutes, silent while nothing a decision depends on has moved |
|
|
864
|
+
| `high` | full capability, re-costed every two minutes mid-turn | the normal line, **plus a standing directive on every prompt** (about 650 characters, so a `high` briefing runs roughly 40% longer than `standard`), plus a short re-cost the first time a cheaper tier would do the same job - re-measured every two minutes, said only when the answer changes |
|
|
865
|
+
| `standard` | what the plugin has always done | today's line, today's cadences, unchanged |
|
|
866
|
+
| `off` | nothing at all | every hook returns before reading anything: no scan, no state write, no line, no end-of-reply tally |
|
|
867
|
+
|
|
868
|
+
`high` is the mode that spends a little more to waste a lot less: it carries a
|
|
869
|
+
standing directive and re-measures mid-turn, so its own line is longer than
|
|
870
|
+
`standard`'s. `max` is the one that costs less to say. Picking `high` because
|
|
871
|
+
the word sounds efficient and expecting a shorter line is the one
|
|
872
|
+
misunderstanding worth heading off.
|
|
873
|
+
|
|
874
|
+
Aliases, because people ask for these in their own words: `ultra`,
|
|
875
|
+
`ultra-efficient`, `maxtoken`, `maxefficient` for `max`; `smart`,
|
|
876
|
+
`high-efficient` for `high`; `efficient`, `token-efficient`, `default`, `on`
|
|
877
|
+
for `standard`; `none`, `quiet`, `silent`, `ignore` for `off`.
|
|
878
|
+
|
|
879
|
+
**`normal` is deliberately not an alias.** To some people it means "the plugin
|
|
880
|
+
working as usual" (`standard`); to others it means "the plugin stays out of the
|
|
881
|
+
way" (`off`). Those are opposite instructions, so guessing is wrong half the
|
|
882
|
+
time. Ask for `normal` and you get a question back, not a setting.
|
|
883
|
+
|
|
884
|
+
`off` means off, including at 100 per cent used. That is what it says and it is
|
|
885
|
+
honoured literally - which is also the failure this plugin exists to prevent,
|
|
886
|
+
so setting it prints the consequence once and offers `--guard 95`: one short
|
|
887
|
+
line when the window is nearly spent, and nothing else, ever. The default guard
|
|
888
|
+
is none. Discoverable, not imposed.
|
|
889
|
+
|
|
890
|
+
The one thing a mode never does is lower the quality of the work. When things
|
|
891
|
+
are tight you change the ORDER of the work, never the amount or the quality.
|
|
892
|
+
The savings come from ceremony - speculative reads, re-reads, preamble,
|
|
893
|
+
subagents nobody needed, workflows that cost more context than they save - and
|
|
894
|
+
the directives say that outright, because a model reading "use fewer tokens"
|
|
895
|
+
will otherwise quietly decide to skip the hard part. There is a test for it,
|
|
896
|
+
and another one that checks the `max` line is never longer than the `standard`
|
|
897
|
+
line for the same reading.
|
|
898
|
+
|
|
899
|
+
### Two planes, and which one is whose
|
|
900
|
+
|
|
901
|
+
There are two separate things people mean by "change the model":
|
|
902
|
+
|
|
903
|
+
- **The user plane** is your `settings.json` (`model`, `effortLevel`), the
|
|
904
|
+
`/effort` and `/model` pickers, and `lowpower.js`. It is you saying what you
|
|
905
|
+
want for yourself. The plugin reads it, shows it, and **never writes it on
|
|
906
|
+
its own initiative.** Claude may recommend a change, and make one if you ask;
|
|
907
|
+
it may not make one unasked. There is a test that exercises every mode, every
|
|
908
|
+
alias, `auto`, the bounds and the guard, and then checks `settings.json` is
|
|
909
|
+
byte-identical.
|
|
910
|
+
- **The agent plane** is the tier actually running the turn, and the tier of
|
|
911
|
+
everything the turn spawns. That is what costs money, and that is what the
|
|
912
|
+
modes govern.
|
|
913
|
+
|
|
914
|
+
`claude-usage-limits mode --baseline` shows both side by side. The budget line
|
|
915
|
+
now says the tier as well, and where the reading came from, because the number
|
|
916
|
+
that decides what a turn costs was the one number the line never printed.
|
|
917
|
+
|
|
918
|
+
What Claude can genuinely move, stated without embroidery: the model on an
|
|
919
|
+
`Agent` call, and the model and effort inside a `Workflow` script. Its own
|
|
920
|
+
model and effort it cannot change mid-session - no hook output field exists for
|
|
921
|
+
it, on either host - so the plugin names the exact command and leaves it with
|
|
922
|
+
you. It does not pretend otherwise.
|
|
923
|
+
|
|
924
|
+
You can bound what it may suggest:
|
|
925
|
+
|
|
926
|
+
```
|
|
927
|
+
claude-usage-limits mode --floor sonnet/medium # never point below this
|
|
928
|
+
claude-usage-limits mode --ceiling opus/xhigh # nor above it
|
|
929
|
+
claude-usage-limits mode --pin # report only, suggest nothing
|
|
930
|
+
claude-usage-limits mode --decline # no, and stop suggesting that
|
|
931
|
+
```
|
|
932
|
+
|
|
933
|
+
And when you say "put it back", there is something to put it back to:
|
|
934
|
+
|
|
935
|
+
```
|
|
936
|
+
claude-usage-limits mode --history what changed, when, at whose instruction
|
|
937
|
+
claude-usage-limits mode undo reverse the last change, naming it first
|
|
938
|
+
```
|
|
939
|
+
|
|
940
|
+
`undo` reverses what the plugin owns. For a change to your own settings it
|
|
941
|
+
names the entry and the command that undoes it and leaves the file alone -
|
|
942
|
+
which is the same rule as everywhere else, and the reason the byte-identical
|
|
943
|
+
test can never go green by accident.
|
|
944
|
+
|
|
842
945
|
## Working cheaply on purpose
|
|
843
946
|
|
|
844
947
|
Half the problem is measurement. The other half is that a high effort setting
|
|
@@ -972,7 +1075,8 @@ skills/usage-limits/scripts/ usage.js, brief.js, pulse.js, stop.js,
|
|
|
972
1075
|
lowpower.js, install-codex-hook.js,
|
|
973
1076
|
recommend.js, panel.js, feed.js,
|
|
974
1077
|
statusline.js, live.js, view.js, bars.js,
|
|
975
|
-
activity.js
|
|
1078
|
+
activity.js, reading.js, drift.js,
|
|
1079
|
+
mode.js, voice.js, relay.js, wake.js
|
|
976
1080
|
skills/usage-limits/references/ the longer notes
|
|
977
1081
|
hooks/hooks.json runs brief.js before each prompt, pulse.js
|
|
978
1082
|
during long turns, stop.js after each reply
|
|
@@ -981,6 +1085,7 @@ commands/check.md the /usage-limits:check command
|
|
|
981
1085
|
commands/session.md the /usage-limits:session command
|
|
982
1086
|
commands/panel.md the /usage-limits:panel command
|
|
983
1087
|
commands/statusline.md the /usage-limits:statusline command
|
|
1088
|
+
commands/usage-mode.md the /usage-mode command
|
|
984
1089
|
bin/cli.js the npx entry point
|
|
985
1090
|
tools/sync-version.js keeps the manifest version in step
|
|
986
1091
|
vscode/ the VS Code extension; build.js copies the
|
|
@@ -994,11 +1099,18 @@ test/ node --test, no dependencies
|
|
|
994
1099
|
node --test
|
|
995
1100
|
```
|
|
996
1101
|
|
|
997
|
-
|
|
1102
|
+
712 tests over the pricing, the window arithmetic, plan and credit detection,
|
|
998
1103
|
the status line, the before-prompt line, the mid-turn pulse, the after-reply tally and the session history, job forecasting,
|
|
999
1104
|
per-project attribution, the Codex reader and its installer, the CLI,
|
|
1000
1105
|
packaging, and the settings save/restore.
|
|
1001
1106
|
|
|
1107
|
+
The budget modes are checked as rules rather than examples: the whole stopping
|
|
1108
|
+
matrix is walked in every mode (640 lines), `off` must inject nothing at any
|
|
1109
|
+
percentage and any pressure, the `max` line must never be longer than the
|
|
1110
|
+
`standard` line for the same reading, no line may tell the agent to do the work
|
|
1111
|
+
worse, and every mode path, alias, bound and guard is exercised before
|
|
1112
|
+
`settings.json` is compared byte for byte.
|
|
1113
|
+
|
|
1002
1114
|
## Status
|
|
1003
1115
|
|
|
1004
1116
|
It works and I use it daily.
|
|
@@ -1040,3 +1152,109 @@ This exists because of a real session. The Fable weekly hit 89 per cent, the
|
|
|
1040
1152
|
line said the budget was nearly gone, and the work stopped - with the 5-hour
|
|
1041
1153
|
window at 46 and every other model untouched. One command would have carried it
|
|
1042
1154
|
on.
|
|
1155
|
+
|
|
1156
|
+
## 1.23.0 - the ceiling, and three hosts that can be told no
|
|
1157
|
+
|
|
1158
|
+
Everything before this release reported. This one intervenes.
|
|
1159
|
+
|
|
1160
|
+
### The Codex meter was going blind about a third of the time
|
|
1161
|
+
|
|
1162
|
+
Codex writes more than one meter into its rollouts, and they are not successive
|
|
1163
|
+
readings of one thing. A ChatGPT Plus session carries `limit_id: "codex"`, which
|
|
1164
|
+
holds the 5-hour and weekly windows, interleaved with `limit_id: "premium"`,
|
|
1165
|
+
which holds the credit balance and has `primary` and `secondary` set to `null`.
|
|
1166
|
+
The reader took whichever was written last.
|
|
1167
|
+
|
|
1168
|
+
On the machine this was found on, two of every six rollouts ended on a `premium`
|
|
1169
|
+
payload - and when one did, the plugin reported no windows at all. Measured on a
|
|
1170
|
+
real session: the final line was a `premium` payload two lines after a `codex`
|
|
1171
|
+
payload reading **99 per cent of the 5-hour window**, and what reached the agent
|
|
1172
|
+
was a meter with nothing in it.
|
|
1173
|
+
|
|
1174
|
+
That is the whole of "Codex does not slow down when the limit is close": nothing
|
|
1175
|
+
ever told it the limit was close. The reader now keeps the newest reading of each
|
|
1176
|
+
meter and prefers the one that actually describes a window. Nothing is merged or
|
|
1177
|
+
synthesised - the payload returned is one Codex really wrote.
|
|
1178
|
+
|
|
1179
|
+
### An old snapshot is a floor, not a reading
|
|
1180
|
+
|
|
1181
|
+
There was already a warning for a reading spent past its own remainder. It could
|
|
1182
|
+
never fire for a snapshot taken at the start of a window, because everything
|
|
1183
|
+
spent since is still inside the remainder.
|
|
1184
|
+
|
|
1185
|
+
So a session ran for most of an hour being told **7 per cent** while the account
|
|
1186
|
+
was at **41**: Claude Code's own cache had not moved in fifty minutes, the
|
|
1187
|
+
plugin's live reading was rate-limited into backoff, and the correction was
|
|
1188
|
+
quietly carrying the entire difference on its own. A correction is a good
|
|
1189
|
+
adjustment to a recent snapshot and a bad substitute for an old one, because the
|
|
1190
|
+
pricing error compounds with every point it has to bridge. Past fifteen minutes
|
|
1191
|
+
the brief now says the figure is a floor and points at `/usage`.
|
|
1192
|
+
|
|
1193
|
+
### The ceiling
|
|
1194
|
+
|
|
1195
|
+
node bin/cli.js mode --cap 60
|
|
1196
|
+
node bin/cli.js mode --cap off
|
|
1197
|
+
|
|
1198
|
+
Past the ceiling, **fan-out calls are refused at the hook** - `Agent`, `Task`,
|
|
1199
|
+
`Workflow` and their equivalents on each host. Everything else keeps working at
|
|
1200
|
+
any percentage: reads, edits, tests, commands. The work still finishes, just
|
|
1201
|
+
sequentially, in one session, which is where the saving is. A measured fan-out
|
|
1202
|
+
costs between 2.6x and 5.9x the same work done in sequence, because every agent
|
|
1203
|
+
warms its own cache from cold and none can report back until they all stop.
|
|
1204
|
+
|
|
1205
|
+
It is off until you set a number, it never fires without a reading behind it, and
|
|
1206
|
+
the refusal says what to do instead - a denial that only says "over budget" gets
|
|
1207
|
+
retried.
|
|
1208
|
+
|
|
1209
|
+
**Why a refusal rather than a sentence.** On Codex the reported figure
|
|
1210
|
+
demonstrably does not change behaviour, and the reason is not stubbornness.
|
|
1211
|
+
`gpt-6-astra`'s own system prompt, shipped in `models_cache.json`, says: *"Do not
|
|
1212
|
+
settle for a partial or 'helpful enough' solution that does not fully satisfy the
|
|
1213
|
+
user's task to save time, effort or tokens"* - and ranks the live user
|
|
1214
|
+
instruction above anything an `AGENTS.md` or a skill says. A line asking it to
|
|
1215
|
+
economise is arguing with its own instructions, and losing.
|
|
1216
|
+
|
|
1217
|
+
### The Codex subagent clamp
|
|
1218
|
+
|
|
1219
|
+
`lowpower on --host codex` now also bounds `[agents]`. Two facts read out of the
|
|
1220
|
+
model catalog Codex itself caches, not out of documentation:
|
|
1221
|
+
|
|
1222
|
+
gpt-6-astra: default_reasoning_level = "low"
|
|
1223
|
+
multi_agent_reasoning_effort = "xhigh"
|
|
1224
|
+
|
|
1225
|
+
Astra's own default effort is the cheapest one, and its subagents run at the
|
|
1226
|
+
dearest one **no matter what the session is set to**. Lowering effort without
|
|
1227
|
+
bounding them leaves the most expensive path in the product untouched. The clamp
|
|
1228
|
+
is a marked block, removed exactly by `lowpower off`, and it refuses outright
|
|
1229
|
+
rather than writing a second `[agents]` table over one you wrote yourself.
|
|
1230
|
+
`--no-agents` declines just that half.
|
|
1231
|
+
|
|
1232
|
+
### Antigravity
|
|
1233
|
+
|
|
1234
|
+
node skills/usage-limits/scripts/install-antigravity.js on
|
|
1235
|
+
|
|
1236
|
+
Installs into `~/.gemini/config/plugins/usage-limits/`. `PreInvocation` carries
|
|
1237
|
+
the budget line as an injected ephemeral message; `PreToolUse` carries the
|
|
1238
|
+
ceiling, which Antigravity implements as a real `decision: "deny"`.
|
|
1239
|
+
|
|
1240
|
+
One thing is said plainly rather than papered over: **Antigravity publishes no
|
|
1241
|
+
remaining quota anywhere readable on disk.** It refreshes quota - its own log
|
|
1242
|
+
says so - and keeps it in memory. A previous version filled that gap by reporting
|
|
1243
|
+
*Claude's* meter under a `cross-agent-claude` source, next to a hardcoded plan
|
|
1244
|
+
and a model name invented for a settings file that has no model key in it. All of
|
|
1245
|
+
that is gone. Where there is nothing to read, the report says the quota is
|
|
1246
|
+
unreadable.
|
|
1247
|
+
|
|
1248
|
+
### Caveman, and why it is not here
|
|
1249
|
+
|
|
1250
|
+
It was on the list for this release and it is not in it. JetBrains ran a
|
|
1251
|
+
controlled A/B of the caveman skill - 86 tasks, paired, ~240 billed trials - and
|
|
1252
|
+
measured output tokens down **8.5 per cent** against an advertised 65, with
|
|
1253
|
+
quality differences indistinguishable from noise (p=0.82). An independent
|
|
1254
|
+
benchmark found the literal instruction `be brief.` matched or beat it, and
|
|
1255
|
+
because agentic cost is input-dominated, the skill's own rules riding along every
|
|
1256
|
+
turn can cost more than they save. Its engine is also BSL-licensed, not open.
|
|
1257
|
+
|
|
1258
|
+
Claude Code already ships a built-in **Concise** output style that does the same
|
|
1259
|
+
job in the cached system-prompt layer at no marginal cost. Use that. This plugin
|
|
1260
|
+
will not ship a measured 8 per cent as a 65 per cent saving.
|
package/bin/cli.js
CHANGED
|
@@ -26,6 +26,16 @@ const HELP = `claude-usage-limits - how much agent usage is left, and whether th
|
|
|
26
26
|
claude-usage-limits statusline on bars under the Claude Code prompt
|
|
27
27
|
claude-usage-limits statusline off put back what was there
|
|
28
28
|
|
|
29
|
+
claude-usage-limits mode which budget mode the hooks are in
|
|
30
|
+
claude-usage-limits mode max fewest tokens that still finish the job
|
|
31
|
+
claude-usage-limits mode high full capability, re-costed every two minutes
|
|
32
|
+
claude-usage-limits mode standard what the plugin does today
|
|
33
|
+
claude-usage-limits mode off inject nothing; hooks return immediately
|
|
34
|
+
claude-usage-limits mode off --guard 95 off, except one line when nearly spent
|
|
35
|
+
claude-usage-limits mode auto pick from pressure, always reported
|
|
36
|
+
claude-usage-limits mode --list the four modes and their aliases
|
|
37
|
+
claude-usage-limits mode --ledger measured cost per mode
|
|
38
|
+
|
|
29
39
|
claude-usage-limits lowpower status show the current effort setting
|
|
30
40
|
claude-usage-limits lowpower on lower effortLevel, remembering the old value
|
|
31
41
|
claude-usage-limits lowpower on --effort medium --model sonnet
|
|
@@ -59,6 +69,12 @@ function run(argv) {
|
|
|
59
69
|
return Promise.resolve(0);
|
|
60
70
|
}
|
|
61
71
|
|
|
72
|
+
if (args[0] === 'mode') {
|
|
73
|
+
const budget = require('../skills/usage-limits/scripts/mode.js');
|
|
74
|
+
process.stdout.write(budget.main(args.slice(1)) + '\n');
|
|
75
|
+
return Promise.resolve(0);
|
|
76
|
+
}
|
|
77
|
+
|
|
62
78
|
if (args[0] === 'lowpower') {
|
|
63
79
|
const lowpower = require('../skills/usage-limits/scripts/lowpower.js');
|
|
64
80
|
return Promise.resolve(lowpower.main(args.slice(1)));
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Show or set the budget mode - how hard the plugin leans, and what it costs to say it
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
Run `node "${CLAUDE_PLUGIN_ROOT}/skills/usage-limits/scripts/mode.js" $ARGUMENTS`
|
|
6
|
+
and report the answer back. Then stop; do not start other work as part of this
|
|
7
|
+
command.
|
|
8
|
+
|
|
9
|
+
The plugin is not free. It puts a line into your context before every prompt,
|
|
10
|
+
refreshes readings after tool calls, and keeps a status line alive. A mode
|
|
11
|
+
changes two things at once: what the plugin tells you to do, and what it costs
|
|
12
|
+
to say it.
|
|
13
|
+
|
|
14
|
+
| mode | what it is |
|
|
15
|
+
| --- | --- |
|
|
16
|
+
| `max` | fewest tokens that can still finish the job: one terse line, readings every ten minutes, silent when nothing a decision depends on has moved |
|
|
17
|
+
| `high` | full capability, re-costed every two minutes mid-turn: the normal line plus a directive to keep checking whether the tier is bigger than the task. The mid-turn re-cost is re-measured on that cadence and said only when the answer changes |
|
|
18
|
+
| `standard` | what the plugin does today, unchanged |
|
|
19
|
+
| `off` | nothing is injected at all, and every hook returns before reading anything - including the end-of-reply cost line and the closing line |
|
|
20
|
+
|
|
21
|
+
Aliases: `ultra`, `ultra-efficient`, `maxefficient` and friends for `max`;
|
|
22
|
+
`smart`, `high-efficient` for `high`; `efficient`, `token-efficient`,
|
|
23
|
+
`default`, `on` for `standard`; `none`, `quiet`, `silent`, `ignore` for `off`.
|
|
24
|
+
|
|
25
|
+
**`normal` is deliberately not an alias for either `standard` or `off`.** To
|
|
26
|
+
some people it means "the plugin working as usual" and to others "the plugin
|
|
27
|
+
stays out of the way", and those are opposite instructions. The script answers
|
|
28
|
+
it with a question. Ask which was meant; never guess.
|
|
29
|
+
|
|
30
|
+
Commands:
|
|
31
|
+
|
|
32
|
+
- (no arguments) - the current mode, where it came from, and what it changes.
|
|
33
|
+
- `<name>` - set it. `<name> --session --session-id <id>` sets it for one
|
|
34
|
+
session only.
|
|
35
|
+
- `auto` / `auto off` - pick from pressure. Under 50 per cent used it is
|
|
36
|
+
standard, 50 to 79 high, 80 or over (or tight, or gone) max. It is always
|
|
37
|
+
reported as what it resolved to (`auto -> max`) and it never picks `off`.
|
|
38
|
+
- `off --guard 95` - off, except one short line when the window is nearly
|
|
39
|
+
spent. `off` on its own is silent even at 100 per cent; that is what it means
|
|
40
|
+
and it is honoured literally, so the guard exists and is offered once.
|
|
41
|
+
- `--list`, `--explain <name>` - the modes, and one mode's full record.
|
|
42
|
+
- `--floor sonnet/medium`, `--ceiling opus/xhigh`, `--pin` - the user's own
|
|
43
|
+
bounds on what the plugin may suggest. `--pin` means report only: the gap
|
|
44
|
+
between the baseline and what is running is stated and nothing is suggested.
|
|
45
|
+
- `--baseline` - the user's own setting and the tier actually running, side by
|
|
46
|
+
side.
|
|
47
|
+
- `--advice` / `--no-advice` / `--advice-on` - the recommendation channel.
|
|
48
|
+
- `--decline [id]` - the user said no. That recommendation is remembered as
|
|
49
|
+
declined and is never raised again, in this session or any later one. With no
|
|
50
|
+
id it declines whatever is pending.
|
|
51
|
+
- `--history`, `undo` - what changed, when, at whose instruction; and reverse
|
|
52
|
+
the last one, naming it first.
|
|
53
|
+
- `--ledger` - measured turns and cost per turn, per mode, from what replies
|
|
54
|
+
actually cost.
|
|
55
|
+
|
|
56
|
+
Two rules that hold in every mode:
|
|
57
|
+
|
|
58
|
+
1. **The modes govern the agent plane only.** `settings.json`, `/effort`,
|
|
59
|
+
`/model` and `lowpower.js` are the user's own baseline. The plugin reads
|
|
60
|
+
them, shows them, and never writes them on its own initiative. Recommend a
|
|
61
|
+
change freely; make one when asked; never make one unasked.
|
|
62
|
+
2. **A mode never lowers the quality of the work.** The savings come from
|
|
63
|
+
ceremony - speculative reads, re-reads, preamble, subagents nobody needed -
|
|
64
|
+
and never from doing the job less well.
|
package/hooks/hooks.json
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "claude-usage-limits",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.23.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",
|
|
@@ -275,6 +275,137 @@ The user can also ask any time with `/usage-limits:session`, or run
|
|
|
275
275
|
`--sessions` for the history of recent sessions on this machine.
|
|
276
276
|
|
|
277
277
|
|
|
278
|
+
## Budget modes
|
|
279
|
+
|
|
280
|
+
How hard this plugin leans, and what it costs to say it. Four modes, set by the
|
|
281
|
+
user and read by every hook:
|
|
282
|
+
|
|
283
|
+
```
|
|
284
|
+
node scripts/mode.js # which one, where it came from, what it changes
|
|
285
|
+
node scripts/mode.js max # set it
|
|
286
|
+
node scripts/mode.js --list # all four, and the aliases
|
|
287
|
+
node scripts/mode.js --explain high # one mode's full record
|
|
288
|
+
```
|
|
289
|
+
|
|
290
|
+
| mode | one line |
|
|
291
|
+
| --- | --- |
|
|
292
|
+
| `max` | fewest tokens that can still finish the job: one terse line, readings every ten minutes, silent when nothing a decision depends on has moved |
|
|
293
|
+
| `high` | full capability, re-measured every two minutes mid-turn, and said only when the answer changes |
|
|
294
|
+
| `standard` | what the plugin does today, unchanged. The default |
|
|
295
|
+
| `off` | nothing injected at all; every hook returns before reading anything, including the end-of-reply tally |
|
|
296
|
+
|
|
297
|
+
Aliases: `ultra`, `ultra-efficient`, `maxtoken`, `maxefficient` map to `max`;
|
|
298
|
+
`smart`, `high-efficient` to `high`; `efficient`, `token-efficient`, `default`,
|
|
299
|
+
`on` to `standard`; `none`, `quiet`, `silent`, `ignore` to `off`.
|
|
300
|
+
|
|
301
|
+
**`normal` is not an alias for either.** To some people it means "the plugin
|
|
302
|
+
working as usual" (`standard`) and to others "the plugin stays out of the way"
|
|
303
|
+
(`off`) - opposite instructions, so a silent guess is wrong half the time. If
|
|
304
|
+
the user says "normal", ask which they meant and say what each one does. The
|
|
305
|
+
script answers the same way.
|
|
306
|
+
|
|
307
|
+
`auto` picks from how full the binding window is - standard under 50 per cent
|
|
308
|
+
used, high from 50 to 79, max at 80 or above - and always reports itself as
|
|
309
|
+
what it resolved to (`auto -> max`). It reads the snapshot already on disk
|
|
310
|
+
rather than scanning, because the mode has to be settled before anything
|
|
311
|
+
expensive runs, and with no readable window it stays on `standard` rather than
|
|
312
|
+
guessing. It never picks `off`: turning the plugin off is a decision a person
|
|
313
|
+
makes.
|
|
314
|
+
|
|
315
|
+
`off` means off, including at 100 per cent. That is deliberate. If the user
|
|
316
|
+
wants one line at the wall and nothing else, `node scripts/mode.js off --guard 95`
|
|
317
|
+
is it.
|
|
318
|
+
|
|
319
|
+
Two rules hold in every mode, and they are not negotiable:
|
|
320
|
+
|
|
321
|
+
- **A mode never lowers the quality of the work.** When things are tight you
|
|
322
|
+
change the ORDER of the work, never the amount or the quality. The savings
|
|
323
|
+
come from ceremony - speculative reads, re-reads, preamble, subagents nobody
|
|
324
|
+
needed, workflows that cost more context than they save.
|
|
325
|
+
- **The modes govern the agent plane only**, and never write `settings.json`.
|
|
326
|
+
|
|
327
|
+
### Two planes, and the conversation between them
|
|
328
|
+
|
|
329
|
+
The **user plane** is `settings.json` (`model`, `effortLevel`), the `/effort`
|
|
330
|
+
and `/model` pickers, and `lowpower.js`. It is the user saying what they want
|
|
331
|
+
for themselves. It is theirs.
|
|
332
|
+
|
|
333
|
+
The **agent plane** is the tier actually running this turn, and the tier of
|
|
334
|
+
everything this turn spawns. That is what costs money.
|
|
335
|
+
|
|
336
|
+
What is actually yours to move, stated exactly, because a claim beyond this
|
|
337
|
+
would be a lie the user cannot check:
|
|
338
|
+
|
|
339
|
+
- **The model on an `Agent` call is yours.** `model: "sonnet" | "opus" |
|
|
340
|
+
"haiku" | "fable"` on any Agent call, and it overrides both the agent
|
|
341
|
+
definition and the configured default. It is ignored for `subagent_type:
|
|
342
|
+
"fork"`, which always inherits the parent model.
|
|
343
|
+
- **Model and effort inside a `Workflow` script are yours**, per `agent()`
|
|
344
|
+
call: `opts.model` and `opts.effort` (`low` | `medium` | `high` | `xhigh` |
|
|
345
|
+
`max`). The host's own advice is to omit `opts.model` unless you are
|
|
346
|
+
confident, and to use `opts.effort: 'low'` for mechanical stages - so lean on
|
|
347
|
+
effort rather than model when sizing what you spawn.
|
|
348
|
+
- **Your own model and effort are NOT yours to change mid-session.** Nothing a
|
|
349
|
+
hook can emit changes them: there is no such field anywhere in the hook
|
|
350
|
+
output contract, and `PreModelSwitch` can only veto a switch someone else
|
|
351
|
+
started. `/model` and `/effort` are typed by a person and
|
|
352
|
+
`CLAUDE_CODE_EFFORT_LEVEL` is read at launch. So say the exact command in one
|
|
353
|
+
line and let the user run it. Never imply you changed it yourself.
|
|
354
|
+
- `xhigh` and `max` are refused outright when thinking is disabled, so never
|
|
355
|
+
point at either without that being true.
|
|
356
|
+
|
|
357
|
+
The two planes talk to each other, in both directions, through the
|
|
358
|
+
conversation. The whole rule in one line:
|
|
359
|
+
|
|
360
|
+
**You may RECOMMEND a user-plane change. You may MAKE one when asked. You may
|
|
361
|
+
never make one unasked.**
|
|
362
|
+
|
|
363
|
+
Recommending, when you do it:
|
|
364
|
+
|
|
365
|
+
- **Evidence or silence.** Cite a measurement - what this account has actually
|
|
366
|
+
measured, from `usage.js --recommend`, the fit line in the budget briefing,
|
|
367
|
+
or `scripts/drift.js`. "Recommended" with no number is nagging.
|
|
368
|
+
- **At most one per session**, and none at all in `off`. The plugin enforces
|
|
369
|
+
this; do not route around it.
|
|
370
|
+
- **A declined recommendation is not raised again.** When the user says no,
|
|
371
|
+
record it - `node scripts/mode.js --decline` - and it is never volunteered
|
|
372
|
+
again, in this session or any later one. `--advice` shows what is pending.
|
|
373
|
+
- **Name the exact command, the plane it changes, and when it takes effect.**
|
|
374
|
+
|
|
375
|
+
When the user asks you to change something, or says **"change it back"**: read
|
|
376
|
+
`node scripts/mode.js --history` first, say out loud what you are reverting and
|
|
377
|
+
to what, then do it. Never infer a target that is not in the log. `node
|
|
378
|
+
scripts/mode.js undo` reverses the last change the plugin owns and names it
|
|
379
|
+
first; for a change to the user's own settings it names the command and leaves
|
|
380
|
+
the file alone, because that plane is not the plugin's to write.
|
|
381
|
+
|
|
382
|
+
The surprise to head off, every time: **a user-plane change does not move the
|
|
383
|
+
session already running.** If the user says "turn low power on" and you do it,
|
|
384
|
+
nothing about this session changes - `lowpower.js` says so itself ("Applies to
|
|
385
|
+
new sessions. For the session you are in, run /effort X"). Relay that in your
|
|
386
|
+
own words whenever you make one, and the same in reverse: putting the baseline
|
|
387
|
+
back does not restore this session's tier either.
|
|
388
|
+
|
|
389
|
+
### Bounds the user can set
|
|
390
|
+
|
|
391
|
+
```
|
|
392
|
+
node scripts/mode.js --floor sonnet/medium # never point below this, even in max
|
|
393
|
+
node scripts/mode.js --ceiling opus/xhigh # nor above it, even on the hard part
|
|
394
|
+
node scripts/mode.js --pin # do not self-switch at all: report only
|
|
395
|
+
```
|
|
396
|
+
|
|
397
|
+
Under `--pin` the plugin reports the gap between the baseline and what is
|
|
398
|
+
running and suggests nothing. Respect it in your own words too: report, do not
|
|
399
|
+
switch.
|
|
400
|
+
|
|
401
|
+
### Stepping back up
|
|
402
|
+
|
|
403
|
+
The efficient modes are two-directional, and that matters more than it sounds.
|
|
404
|
+
Having dropped to a cheap tier for a mechanical stretch, say so when the work
|
|
405
|
+
turns hard again and point back at the baseline. A one-way ratchet down is how
|
|
406
|
+
a long session quietly degrades, which is the thing the quality rule forbids.
|
|
407
|
+
|
|
408
|
+
|
|
278
409
|
## 4. Low power
|
|
279
410
|
|
|
280
411
|
Two halves, and the second one is the half that actually binds.
|
|
@@ -404,41 +535,48 @@ waste at 10 per cent used exactly as much as at 80; the only difference is that
|
|
|
404
535
|
at 80 somebody notices.
|
|
405
536
|
|
|
406
537
|
It cannot judge how hard your work is. You can. So when you see it, look at what
|
|
407
|
-
is actually in front of you and
|
|
408
|
-
|
|
538
|
+
is actually in front of you and reach for one of three levers, saying which in
|
|
539
|
+
one line. Two of them are yours to pull; the first is not.
|
|
409
540
|
|
|
410
541
|
1. **Drop the effort** for that stretch - a rename, a docs pass, running tests,
|
|
411
|
-
applying a fix you have already worked out.
|
|
412
|
-
|
|
413
|
-
|
|
542
|
+
applying a fix you have already worked out. `/effort` and `settings.json` are
|
|
543
|
+
the user's own baseline, so this one you **offer**: name the command, say why
|
|
544
|
+
the stretch does not need the tier, and leave the pulling of it to them.
|
|
545
|
+
2. **Hand the stretch to a cheaper model.** Your own model is the user's setting
|
|
546
|
+
too, so say that in one line rather than switching - but the model on
|
|
547
|
+
anything you SPAWN is entirely yours: an Agent call takes a model, and a
|
|
548
|
+
Workflow's `agent()` takes a model and an effort. Size those to the stage.
|
|
414
549
|
3. **Do less of it at this setting** - a fan-out multiplies the setting across
|
|
415
|
-
every agent, so six agents at ultra is six ultra turns, not one.
|
|
550
|
+
every agent, so six agents at ultra is six ultra turns, not one. Yours.
|
|
416
551
|
|
|
417
552
|
Put it back when the work gets hard again. The question is asked once per
|
|
418
553
|
setting per session, not every prompt, and never at all unless there is a real
|
|
419
554
|
measured comparison behind it - a ratio from a price list would have you drop
|
|
420
555
|
effort on a hunch and call it evidence.
|
|
421
556
|
|
|
422
|
-
**This is
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
557
|
+
**This is worth raising early, not only at the wall.** Say it whenever the
|
|
558
|
+
current setting is dearer than the work in front of you needs, long before any
|
|
559
|
+
window is tight: a mechanical rename, a docs pass or a mass find-and-replace
|
|
560
|
+
does not need the model and effort a hard design decision does. An agent that
|
|
561
|
+
only ever reads this as a wall notice runs every trivial turn at the top setting
|
|
562
|
+
and then wonders where the window went.
|
|
563
|
+
|
|
564
|
+
**And "offer it" is one line, not a stop.** Naming the lever and carrying on is
|
|
565
|
+
the whole action. Waiting for an answer before doing the work would cost more
|
|
566
|
+
than the tier ever did.
|
|
430
567
|
|
|
431
568
|
The budget line does this arithmetic for you. Once the binding window is half
|
|
432
569
|
gone it says which lever applies, and at the wall it says outright that you are
|
|
433
570
|
not out of budget and must not stop as though you were. When it does, the
|
|
434
|
-
sequence is:
|
|
435
|
-
the whole request at full quality.
|
|
571
|
+
sequence is: say in one line which command frees it and why, and carry on with
|
|
572
|
+
the whole request at full quality. A per-model weekly is not the account's
|
|
573
|
+
budget, and treating it as one is the error.
|
|
436
574
|
|
|
437
575
|
This is written down because it was got wrong. A session ended with the Fable
|
|
438
576
|
weekly at 89 per cent and the line saying the budget was nearly gone - while the
|
|
439
577
|
5-hour sat at 46 and every other model on the account was untouched. One command
|
|
440
|
-
would have carried it on
|
|
441
|
-
reason that sounded like one.
|
|
578
|
+
would have carried it on, and naming that command costs a line. Stopping there
|
|
579
|
+
was not caution; it was quitting with a reason that sounded like one.
|
|
442
580
|
|
|
443
581
|
Only when the switch is genuinely unavailable - no other window has room, or the
|
|
444
582
|
user has ruled it out - does the checkpoint below apply.
|
|
@@ -540,6 +678,14 @@ of it.
|
|
|
540
678
|
|
|
541
679
|
## Running under Codex
|
|
542
680
|
|
|
681
|
+
One difference that matters for the budget modes. Every entry in Codex's
|
|
682
|
+
`hooks.json` carries an `additionalContextLimit` - a per-hook cap on how much
|
|
683
|
+
context a hook may inject, which Claude Code has no equivalent of. A long
|
|
684
|
+
briefing can therefore be truncated there without a word. If a line looks cut
|
|
685
|
+
off under Codex, that is why: `node scripts/mode.js max` keeps it to one line,
|
|
686
|
+
and `high` is the verbose one.
|
|
687
|
+
|
|
688
|
+
|
|
543
689
|
Everything above works the same. The numbers come from a different place and
|
|
544
690
|
one thing about how they arrive is different, and both are worth knowing.
|
|
545
691
|
|
|
@@ -654,6 +800,7 @@ stop.
|
|
|
654
800
|
| `scripts/host.js` | Works out which agent this is running inside, so one host's percentages are never reported against the other's turns. |
|
|
655
801
|
| `scripts/codex.js` | The Codex reader: the meter and the pace out of `~/.codex/sessions`, plus the live `--refresh` call. |
|
|
656
802
|
| `scripts/install-codex-hook.js` | `status`, `on`, `off`. Installs the Codex-side instruction, which Claude Code does not need. |
|
|
803
|
+
| `scripts/mode.js` | The budget mode: no arguments to report it, `max`/`high`/`standard`/`off` to set it, `auto`, `off --guard 95`, `--list`, `--explain <name>`, `--floor`/`--ceiling`/`--pin`, `--baseline`, `--advice`/`--no-advice`, `--history`, `undo`, `--ledger`. Reads settings.json and never writes it. |
|
|
657
804
|
| `scripts/lowpower.js` | `status`, `on`, `off`. Restores what it replaced. Claude Code only. |
|
|
658
805
|
| `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. |
|
|
659
806
|
| `references/tactics.md` | Every lever that lowers cost, and why it works. |
|
|
@@ -661,6 +808,7 @@ stop.
|
|
|
661
808
|
| `scripts/statusline.js` | `status`, `on`, `off`. Puts the bars under the prompt and restores what was there. |
|
|
662
809
|
| `scripts/feed.js` | The status line command Claude Code runs. Not meant to be called by hand. |
|
|
663
810
|
| `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. |
|
|
811
|
+
| `scripts/drift.js` | How wrong the reading was: each correction written down against the one it replaced. Run it with no arguments for the median and worst gap measured so far, `--json` for the fields. Answer "how far behind does this plugin actually run" from here rather than from memory. |
|
|
664
812
|
| `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. |
|
|
665
813
|
| `scripts/relay.js` | The relay: `status`, `on`/`off`, `at N`, `grace N`, `mode notify\|resume`, `permission MODE`, `thinking off\|resume\|always`, `note "<text>"`, `cancel`, `log`. |
|
|
666
814
|
| `scripts/wake.js` | What the scheduler runs after the reset: re-checks the meter, then notifies or resumes. Never called by hand. |
|