claude-usage-limits 1.9.0 → 1.9.1

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.9.0",
4
+ "version": "1.9.1",
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.9.0",
3
+ "version": "1.9.1",
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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claude-usage-limits",
3
- "version": "1.9.0",
3
+ "version": "1.9.1",
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",
@@ -130,7 +130,17 @@ calculation.
130
130
  **List prices are a proxy.** The rate table is first-party API pricing. How a
131
131
  subscription plan actually meters usage is not published, and the weighting
132
132
  almost certainly is not exactly this. It is close enough for ratios, which is
133
- all it is used for.
133
+ all it is used for. No published or community source shows the meter weighting
134
+ models differently from their dollar prices, so calibrating dollars against
135
+ your own meter remains the best method anyone outside Anthropic has.
136
+
137
+ **The snapshot is slow by design.** The percentages come from Claude Code's
138
+ own cache of the account meter, which refreshes on its own schedule - roughly
139
+ hourly in practice, because the endpoint behind it rate-limits aggressive
140
+ polling. Between refreshes every figure here is the last real reading plus
141
+ arithmetic. That is why an old snapshot is reported as a floor with its age
142
+ attached rather than dressed up as a current percentage, and why `/usage` is
143
+ the one way to force a fresh reading.
134
144
 
135
145
  **A reset time can be in the past.** The cache refreshes when Claude Code
136
146
  talks to the API, so an idle spell leaves it behind. A window whose `resets_at`
@@ -168,6 +178,13 @@ immediately. Re-run the report if the shape of the work changes.
168
178
  The rate table in `scripts/usage.js` is a plain object at the top of the file.
169
179
  When new models ship, add a row.
170
180
 
181
+ A bracketed suffix on a model id (`claude-sonnet-5[1m]`) is stripped before
182
+ the lookup: it marks a context-window variant of the same model, not a new
183
+ one. Cache reads price at a tenth of the input rate unless a row carries a
184
+ `cacheRead` figure of its own - Fable and Mythos 5.1 price reads outright at
185
+ $0.25 per million, far under the tenth rule, and reads are the dominant input
186
+ in exactly the long sessions where the difference matters.
187
+
171
188
  Until someone does, a model this table has not seen is priced at the average of
172
189
  the family its name contains: an unreleased `claude-opus-5-2` is charged at the
173
190
  mean of every Opus rate on record. Averaging assumes nothing about which
@@ -47,8 +47,12 @@ const MINUTE = 60 * 1000;
47
47
  const HOUR = 60 * MINUTE;
48
48
  const DAY = 24 * HOUR;
49
49
 
50
- // USD per million tokens, first-party API rates.
50
+ // USD per million tokens, first-party API rates. `cacheRead` is an absolute
51
+ // $/MTok override for the few models that price reads outright instead of at
52
+ // a tenth of input; everything else uses the CACHE_READ multiplier below.
51
53
  const RATES = {
54
+ 'claude-fable-5-1': { input: 10, output: 50, cacheRead: 0.25 },
55
+ 'claude-mythos-5-1': { input: 10, output: 50, cacheRead: 0.25 },
52
56
  'claude-fable-5': { input: 10, output: 50 },
53
57
  'claude-mythos-5': { input: 10, output: 50 },
54
58
  'claude-opus-5': { input: 5, output: 25 },
@@ -91,9 +95,21 @@ function familyAverage(family, table) {
91
95
  return { input: input / members.length, output: output / members.length };
92
96
  }
93
97
 
98
+ // Claude Code aliases and some transcript records carry a bracketed variant
99
+ // suffix - "fable[1m]" is the 1M-context toggle on the same model, not a
100
+ // different one. Left in place it misses the exact rate lookup and lands on
101
+ // the family average, which is wrong whenever a family's members price
102
+ // differently (sonnet 5 at $2 against sonnet 4.6 at $3).
103
+ function normalizeModel(model) {
104
+ return String(model || '')
105
+ .toLowerCase()
106
+ .replace(/\[[^\]]*\]\s*$/, '')
107
+ .trim();
108
+ }
109
+
94
110
  // Whether the price came from the table or from an assumption.
95
111
  function isKnownModel(model) {
96
- return Object.prototype.hasOwnProperty.call(RATES, String(model || '').toLowerCase());
112
+ return Object.prototype.hasOwnProperty.call(RATES, normalizeModel(model));
97
113
  }
98
114
 
99
115
  // Cache traffic is priced as a multiple of the input rate.
@@ -184,7 +200,7 @@ function readJson(file) {
184
200
  }
185
201
 
186
202
  function rateFor(model) {
187
- const id = String(model || '').toLowerCase();
203
+ const id = normalizeModel(model);
188
204
  if (RATES[id]) return RATES[id];
189
205
  return familyAverage(familyOf(id)) || FALLBACK_RATE;
190
206
  }
@@ -199,16 +215,26 @@ function costOf(usage, model) {
199
215
 
200
216
  let writeUnits = write5m * CACHE_WRITE_5M + write1h * CACHE_WRITE_1H;
201
217
  if (writeUnits === 0) {
202
- // Older records only carry the undifferentiated total.
218
+ // Older records only carry the undifferentiated total. Five minutes is
219
+ // the default TTL, so that is the assumption; an old-format one-hour
220
+ // session is under-priced by it, but assuming 2x would overcharge the
221
+ // common case to be right about the rare one.
203
222
  writeUnits = (usage.cache_creation_input_tokens || 0) * CACHE_WRITE_5M;
204
223
  }
205
224
 
206
- const inputUnits =
207
- (usage.input_tokens || 0) +
208
- (usage.cache_read_input_tokens || 0) * CACHE_READ +
209
- writeUnits;
225
+ // Reads price at a tenth of the input rate unless the model prices them
226
+ // outright. The distinction matters most exactly where reads dominate: a
227
+ // long session re-reads its whole context every turn, and pricing Fable
228
+ // 5.1's $0.25 reads by the tenth rule would overstate that spend fourfold.
229
+ const readTokens = usage.cache_read_input_tokens || 0;
230
+ const readCost = Number.isFinite(rate.cacheRead)
231
+ ? readTokens * rate.cacheRead
232
+ : readTokens * CACHE_READ * rate.input;
210
233
 
211
- return (inputUnits * rate.input + (usage.output_tokens || 0) * rate.output) / 1e6;
234
+ const inputUnits = (usage.input_tokens || 0) + writeUnits;
235
+ return (
236
+ (inputUnits * rate.input + readCost + (usage.output_tokens || 0) * rate.output) / 1e6
237
+ );
212
238
  }
213
239
 
214
240
  function tokensOf(usage) {