claude-usage-limits 1.18.0 → 1.19.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.19.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.19.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/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "claude-usage-limits",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.19.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",
|
|
@@ -2160,6 +2160,85 @@ function criticalOthers(windows, bindingKey, threshold) {
|
|
|
2160
2160
|
);
|
|
2161
2161
|
}
|
|
2162
2162
|
|
|
2163
|
+
// What effort is ACTUALLY running, and how we know.
|
|
2164
|
+
//
|
|
2165
|
+
// This looked like a plugin bug and is not one. Ultracode is not a separate
|
|
2166
|
+
// effort level: Claude Code's own words are "ultracode: xhigh + dynamic
|
|
2167
|
+
// workflow orchestration (this session only)". So a session in ultracode has
|
|
2168
|
+
// effortLevel xhigh in settings.json and writes effort "xhigh" into every
|
|
2169
|
+
// transcript line - both correct, and both unable to say which MODE is on.
|
|
2170
|
+
// "This session only" means it is never written to disk at all.
|
|
2171
|
+
//
|
|
2172
|
+
// So the honest answer is a chain, and every reading says where it came from,
|
|
2173
|
+
// because "xhigh" from a stale settings file and "xhigh" from a live override
|
|
2174
|
+
// deserve different confidence:
|
|
2175
|
+
//
|
|
2176
|
+
// 1. CLAUDE_CODE_EFFORT_LEVEL - Claude Code's own session override. Hooks
|
|
2177
|
+
// inherit the environment, so this is live and authoritative.
|
|
2178
|
+
// 2. An override recorded here by hand, for the one case nothing can see:
|
|
2179
|
+
// /effort ultracode typed in the UI, which touches neither disk nor env.
|
|
2180
|
+
// 3. settings.effortLevel - the persisted default.
|
|
2181
|
+
// 4. The transcript - stamped at session start and never re-stamped.
|
|
2182
|
+
const EFFORT_LEVELS = ['low', 'medium', 'high', 'xhigh', 'ultracode'];
|
|
2183
|
+
|
|
2184
|
+
function effortOverrideFile() {
|
|
2185
|
+
return path.join(configDir(), 'usage-limits-effort.json');
|
|
2186
|
+
}
|
|
2187
|
+
|
|
2188
|
+
function readEffortOverride() {
|
|
2189
|
+
try {
|
|
2190
|
+
const parsed = JSON.parse(fs.readFileSync(effortOverrideFile(), 'utf8'));
|
|
2191
|
+
if (!parsed || !EFFORT_LEVELS.includes(parsed.effort)) return null;
|
|
2192
|
+
// A hand-set override describes one session. Left lying around it would
|
|
2193
|
+
// outlive the session it was true for, so it expires.
|
|
2194
|
+
if (!Number.isFinite(parsed.at) || Date.now() - parsed.at > 12 * 60 * 60 * 1000) return null;
|
|
2195
|
+
return parsed;
|
|
2196
|
+
} catch (err) {
|
|
2197
|
+
return null;
|
|
2198
|
+
}
|
|
2199
|
+
}
|
|
2200
|
+
|
|
2201
|
+
function writeEffortOverride(level, now) {
|
|
2202
|
+
if (level === null) {
|
|
2203
|
+
try {
|
|
2204
|
+
fs.unlinkSync(effortOverrideFile());
|
|
2205
|
+
} catch (err) {
|
|
2206
|
+
// Already gone is the outcome asked for.
|
|
2207
|
+
}
|
|
2208
|
+
return { ok: true, cleared: true };
|
|
2209
|
+
}
|
|
2210
|
+
if (!EFFORT_LEVELS.includes(level)) return { ok: false, error: 'effort must be one of: ' + EFFORT_LEVELS.join(', ') };
|
|
2211
|
+
try {
|
|
2212
|
+
fs.mkdirSync(configDir(), { recursive: true });
|
|
2213
|
+
writeJsonAtomic(effortOverrideFile(), { effort: level, at: Number.isFinite(now) ? now : Date.now() });
|
|
2214
|
+
return { ok: true, effort: level };
|
|
2215
|
+
} catch (err) {
|
|
2216
|
+
return { ok: false, error: err.message };
|
|
2217
|
+
}
|
|
2218
|
+
}
|
|
2219
|
+
|
|
2220
|
+
function effortNow(sessionId, env) {
|
|
2221
|
+
const environment = env || process.env;
|
|
2222
|
+
const fromEnv = String(environment.CLAUDE_CODE_EFFORT_LEVEL || '').trim().toLowerCase();
|
|
2223
|
+
if (EFFORT_LEVELS.includes(fromEnv)) return { effort: fromEnv, source: 'environment', live: true };
|
|
2224
|
+
|
|
2225
|
+
const override = readEffortOverride();
|
|
2226
|
+
if (override) return { effort: override.effort, source: 'set by hand', live: true };
|
|
2227
|
+
|
|
2228
|
+
let configured = null;
|
|
2229
|
+
try {
|
|
2230
|
+
configured = collect(Date.now()).settings;
|
|
2231
|
+
} catch (err) {
|
|
2232
|
+
configured = null;
|
|
2233
|
+
}
|
|
2234
|
+
const level = configured && configured.effortLevel;
|
|
2235
|
+
if (EFFORT_LEVELS.includes(level)) return { effort: level, source: 'settings', live: false };
|
|
2236
|
+
|
|
2237
|
+
const seen = liveEffort(sessionId);
|
|
2238
|
+
if (seen && EFFORT_LEVELS.includes(seen.effort)) return { effort: seen.effort, source: 'transcript', live: false };
|
|
2239
|
+
return null;
|
|
2240
|
+
}
|
|
2241
|
+
|
|
2163
2242
|
// Is the setting bigger than the work needs?
|
|
2164
2243
|
//
|
|
2165
2244
|
// Everything else here is budget-triggered: it speaks when a window is filling.
|
|
@@ -3794,6 +3873,42 @@ async function main(argv) {
|
|
|
3794
3873
|
}
|
|
3795
3874
|
return 0;
|
|
3796
3875
|
}
|
|
3876
|
+
// `--effort ultracode` records what nothing on the machine can see: the
|
|
3877
|
+
// picker's choice is session-only and touches neither disk nor environment.
|
|
3878
|
+
// `--effort clear` forgets it again.
|
|
3879
|
+
const effortAt = argv.indexOf('--effort');
|
|
3880
|
+
if (effortAt !== -1) {
|
|
3881
|
+
const wanted = String(argv[effortAt + 1] || '').trim().toLowerCase();
|
|
3882
|
+
const say = (text) => {
|
|
3883
|
+
process.stdout.write(text + '\n');
|
|
3884
|
+
return 0;
|
|
3885
|
+
};
|
|
3886
|
+
if (!wanted) {
|
|
3887
|
+
const found = effortNow();
|
|
3888
|
+
if (!found) return say('No effort reading available.');
|
|
3889
|
+
const guess = found.source === 'settings' || found.source === 'transcript';
|
|
3890
|
+
return say(
|
|
3891
|
+
'Effort reads as ' + found.effort + ' (' + found.source + ').' +
|
|
3892
|
+
(guess
|
|
3893
|
+
? '\nIf you picked ultracode in the session, nothing on disk says so - Claude Code calls it' +
|
|
3894
|
+
' "xhigh + dynamic workflow orchestration (this session only)".' +
|
|
3895
|
+
' Tell this: usage.js --effort ultracode'
|
|
3896
|
+
: '')
|
|
3897
|
+
);
|
|
3898
|
+
}
|
|
3899
|
+
if (wanted === 'clear' || wanted === 'off') {
|
|
3900
|
+
writeEffortOverride(null);
|
|
3901
|
+
return say('Effort override cleared; back to the environment, then settings.');
|
|
3902
|
+
}
|
|
3903
|
+
const done = writeEffortOverride(wanted, Date.now());
|
|
3904
|
+
return say(
|
|
3905
|
+
done.ok
|
|
3906
|
+
? 'Effort recorded as ' + done.effort +
|
|
3907
|
+
'. It expires after twelve hours, and CLAUDE_CODE_EFFORT_LEVEL still wins.'
|
|
3908
|
+
: done.error
|
|
3909
|
+
);
|
|
3910
|
+
}
|
|
3911
|
+
|
|
3797
3912
|
const recommendAt = argv.indexOf('--recommend');
|
|
3798
3913
|
if (recommendAt !== -1) {
|
|
3799
3914
|
// The turn count is optional: with one the verdict is about that job,
|
|
@@ -3886,6 +4001,11 @@ module.exports = {
|
|
|
3886
4001
|
criticalOthers,
|
|
3887
4002
|
escapeRoute,
|
|
3888
4003
|
settingFit,
|
|
4004
|
+
effortNow,
|
|
4005
|
+
readEffortOverride,
|
|
4006
|
+
writeEffortOverride,
|
|
4007
|
+
effortOverrideFile,
|
|
4008
|
+
EFFORT_LEVELS,
|
|
3889
4009
|
levers,
|
|
3890
4010
|
betterCalibration,
|
|
3891
4011
|
calibrationForPlan,
|