claude-use 9.10.1 → 9.12.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/README.md CHANGED
@@ -264,6 +264,8 @@ Issues and pull requests are welcome. Please keep the tool itself free of assump
264
264
  - [docs/headroom-measurement.md](docs/headroom-measurement.md): measuring what headroom's transforms are worth on real conversations, offline: the replay method, the cache-weighted cost model and its limits.
265
265
  - [docs/rc-interception-rig.md](docs/rc-interception-rig.md): the Remote Control interception rig: bring-up, per-host TLS proof, teardown, and the manual login step.
266
266
  - [docs/rc-web-client.md](docs/rc-web-client.md): the self-hosted Remote Control web client: the page the door serves behind its control token for browser control of its sessions, how it authenticates and speaks the typed API, and how it is tested.
267
+ - [docs/rc-agent-events.md](docs/rc-agent-events.md): the task and subagent lifecycle events a Remote Control session's read stream carries, and the keys that join them to the transcripts on disk.
268
+ - [docs/agent-transcripts.md](docs/agent-transcripts.md): how Claude Code lays out a session's subagents, forks, workflow runs, tasks, teams and jobs on disk, and which fields are always present.
267
269
 
268
270
  ## License
269
271
 
package/dist/cli.cjs CHANGED
@@ -33243,7 +33243,7 @@ var init_package = __esm({
33243
33243
  "package.json"() {
33244
33244
  package_default = {
33245
33245
  name: "claude-use",
33246
- version: "9.10.1",
33246
+ version: "9.12.0",
33247
33247
  description: "A profile manager and launcher for Claude Code that lets one person run multiple logins from one machine while controlling what gets shared between them.",
33248
33248
  license: "MIT",
33249
33249
  author: "Joseph Mearman <joseph@mearman.co.uk>",
@@ -34027,6 +34027,25 @@ function windowBurn(records, which) {
34027
34027
  }
34028
34028
  return (last.utilization - first.utilization) / (last.atMs - first.atMs);
34029
34029
  }
34030
+ function windowRatio(records) {
34031
+ const points = [];
34032
+ for (const record2 of records) {
34033
+ const unified = record2.rateLimitHeaders === void 0 ? void 0 : parseUnifiedRateLimit(record2.rateLimitHeaders);
34034
+ const five = unified?.fiveHour;
34035
+ const seven = unified?.sevenDay;
34036
+ if (five?.utilization !== void 0 && five.resetsAt !== void 0 && seven?.utilization !== void 0 && seven.resetsAt !== void 0) {
34037
+ points.push({ fiveResetsAt: five.resetsAt, sevenResetsAt: seven.resetsAt, five: five.utilization, seven: seven.utilization });
34038
+ }
34039
+ }
34040
+ const latest = points.at(-1);
34041
+ const current = points.filter((point) => point.fiveResetsAt === latest?.fiveResetsAt && point.sevenResetsAt === latest.sevenResetsAt);
34042
+ const first = current.at(0);
34043
+ const last = current.at(-1);
34044
+ if (first === void 0 || last === void 0 || last.five <= first.five || last.seven <= first.seven) {
34045
+ return void 0;
34046
+ }
34047
+ return (last.seven - first.seven) / (last.five - first.five);
34048
+ }
34030
34049
  function percent(fraction) {
34031
34050
  return `${String(Math.round(fraction * PERCENT))}%`;
34032
34051
  }
@@ -34108,15 +34127,21 @@ function assessIdentity(member, nowMs) {
34108
34127
  }
34109
34128
  const remaining = Math.max(0, 1 - basis.window.utilization);
34110
34129
  const untilResetMs = basis.window.resetsAtMs === void 0 ? basis.windowMs : Math.max(basis.window.resetsAtMs - nowMs, MS_PER_SECOND3);
34111
- const score = remaining * plan.capacity / (untilResetMs / MS_PER_HOUR2);
34130
+ const weeklyScore = remaining * plan.capacity / (untilResetMs / MS_PER_HOUR2);
34112
34131
  const fiveRemaining = five?.utilization === void 0 ? void 0 : Math.max(0, 1 - five.utilization);
34113
34132
  const fiveUntil = five?.resetsAtMs === void 0 ? FIVE_HOUR_WINDOW_MS : Math.max(five.resetsAtMs - nowMs, MS_PER_SECOND3);
34133
+ const ratio = windowRatio(member.records);
34134
+ const fiveHourScore = basis.name === "sevenDay" && fiveRemaining !== void 0 && ratio !== void 0 ? Math.min(fiveRemaining * ratio, remaining) * plan.capacity / (fiveUntil / MS_PER_HOUR2) : void 0;
34135
+ const fiveHourLeads = fiveHourScore !== void 0 && fiveHourScore > weeklyScore;
34136
+ const score = fiveHourLeads ? fiveHourScore : weeklyScore;
34137
+ const scoreWindow = fiveHourLeads ? "fiveHour" : basis.name;
34138
+ const fiveHourTermReasons = basis.name !== "sevenDay" || fiveRemaining === void 0 ? [] : ratio === void 0 ? ["5h reset not scored: no measured 5h to 7d ratio yet"] : fiveHourLeads ? [`5h term leads: ${percent(fiveRemaining)} of 5h unused is about ${percent(Math.min(fiveRemaining * ratio, remaining))} of the week at the measured ratio, resets in ${formatAge(fiveUntil)}`] : [];
34114
34139
  const burn = windowBurn(member.records, "fiveHour");
34115
34140
  const sevenRemaining = seven?.utilization === void 0 ? void 0 : Math.max(0, 1 - seven.utilization);
34116
34141
  const sevenUntil = seven?.resetsAtMs === void 0 ? SEVEN_DAY_WINDOW_MS : Math.max(seven.resetsAtMs - nowMs, MS_PER_SECOND3);
34117
34142
  const sevenDayBurn = windowBurn(member.records, "sevenDay");
34118
34143
  return {
34119
- candidate: { ...base, class: "scored", score, scoreWindow: basis.name, reasons: [...windowReasons.map((reason, index) => index === windowReasons.length - 1 ? `${reason}${observedAgo}` : reason), ...planReasons] },
34144
+ candidate: { ...base, class: "scored", score, scoreWindow, reasons: [...fiveHourTermReasons, ...windowReasons.map((reason, index) => index === windowReasons.length - 1 ? `${reason}${observedAgo}` : reason), ...planReasons] },
34120
34145
  ...fiveRemaining === void 0 ? {} : { fiveHour: { remaining: fiveRemaining, untilResetMs: fiveUntil } },
34121
34146
  ...burn === void 0 ? {} : { burn },
34122
34147
  ...sevenRemaining === void 0 ? {} : { sevenDay: { remaining: sevenRemaining, untilResetMs: sevenUntil } },
@@ -120492,7 +120517,7 @@ var PoolPickCandidateViewSchema = external_exports.strictObject({
120492
120517
  class: external_exports.enum(["scored", "unknown", "pay-per-use", "ineligible"]),
120493
120518
  /** Plan-size-weighted remaining quota per hour until its reset; present for `scored` only. */
120494
120519
  score: external_exports.number().optional(),
120495
- /** Which window's reset divides the score: the seven-day window, or the five-hour one when the member reports no seven-day utilisation; present with `score`. */
120520
+ /** Which window's reset divides the score: the seven-day window, or the five-hour one when the member reports no seven-day utilisation or its measured-ratio five-hour term outranks the weekly one; present with `score`. */
120496
120521
  scoreWindow: external_exports.enum(["sevenDay", "fiveHour"]).optional(),
120497
120522
  /** False when the five-hour window would run dry, at the observed pace, before it resets. */
120498
120523
  feasible: external_exports.boolean(),
@@ -120610,6 +120635,82 @@ var CheckReportJsonSchema = external_exports.strictObject({
120610
120635
  init_middleware();
120611
120636
  init_preflight();
120612
120637
 
120638
+ // src/usage/resets.ts
120639
+ init_preflight();
120640
+ init_rateLimit();
120641
+ var MS_PER_HOUR3 = 36e5;
120642
+ var HOURS_PER_DAY4 = 24;
120643
+ var PERCENT4 = 100;
120644
+ function formatPeriod(window) {
120645
+ if (window.periodMs === void 0) {
120646
+ return window.period ?? "unknown period";
120647
+ }
120648
+ const hours = window.periodMs / MS_PER_HOUR3;
120649
+ return hours >= HOURS_PER_DAY4 && Number.isInteger(hours / HOURS_PER_DAY4) ? `${String(hours / HOURS_PER_DAY4)}d` : `${String(hours)}h`;
120650
+ }
120651
+ function groupOf(row) {
120652
+ return row.resetsAt === void 0 ? 2 : row.reset ? 1 : 0;
120653
+ }
120654
+ function compareRows(left, right) {
120655
+ return groupOf(left) - groupOf(right) || (left.resetsAt ?? "").localeCompare(right.resetsAt ?? "") || left.identity.localeCompare(right.identity) || left.provider.localeCompare(right.provider) || left.window.localeCompare(right.window);
120656
+ }
120657
+ function rowOf(snapshot, provider, window, observedAt2, recorded, nowMs) {
120658
+ const effective = effectiveWindow(recorded, nowMs);
120659
+ return {
120660
+ identity: snapshot.identity,
120661
+ provider,
120662
+ window,
120663
+ observedAt: observedAt2,
120664
+ ...recorded.resetsAt === void 0 ? {} : { resetsAt: recorded.resetsAt },
120665
+ reset: effective.reset,
120666
+ ...effective.utilization === void 0 ? {} : { utilization: effective.utilization },
120667
+ ...effective.status === void 0 ? {} : { status: effective.status }
120668
+ };
120669
+ }
120670
+ function collectResets(snapshots, nowMs) {
120671
+ const rows = snapshots.flatMap(
120672
+ (snapshot) => Object.entries(snapshot.providers).flatMap(([provider, state]) => {
120673
+ const unified = state.rateLimit?.unified;
120674
+ const observedAt2 = state.rateLimit?.observedAt;
120675
+ const overage = unified === void 0 ? void 0 : soleOverageWindow(unified);
120676
+ const headerRows = observedAt2 === void 0 || unified === void 0 ? [] : [
120677
+ ...unified.fiveHour === void 0 ? [] : [rowOf(snapshot, provider, "5h", observedAt2, unified.fiveHour, nowMs)],
120678
+ ...unified.sevenDay === void 0 ? [] : [rowOf(snapshot, provider, "7d", observedAt2, unified.sevenDay, nowMs)],
120679
+ ...overage === void 0 ? [] : [rowOf(snapshot, provider, "extra usage", observedAt2, overage, nowMs)]
120680
+ ];
120681
+ const quota = state.quota;
120682
+ const quotaRows = quota === void 0 ? [] : quota.windows.map((window) => rowOf(snapshot, provider, `${window.measures} ${formatPeriod(window)}`, quota.observedAt, window, nowMs));
120683
+ return [...headerRows, ...quotaRows];
120684
+ })
120685
+ );
120686
+ return { resets: rows.sort(compareRows) };
120687
+ }
120688
+ function formatResetRow(row, nowMs) {
120689
+ const used = row.utilization === void 0 ? "usage unknown" : `${String(Math.round(row.utilization * PERCENT4))}% used`;
120690
+ const when = row.resetsAt === void 0 ? "no reset time reported" : row.reset ? `reset at ${row.resetsAt}` : `resets ${row.resetsAt} (in ${formatAge(Date.parse(row.resetsAt) - nowMs)})`;
120691
+ return `${row.identity} / ${row.provider}: ${row.window} ${used}, ${when}${row.status === void 0 ? "" : ` (${row.status})`}`;
120692
+ }
120693
+
120694
+ // src/usage/resetsSchema.ts
120695
+ init_zod();
120696
+ var ResetRowSchema = external_exports.strictObject({
120697
+ identity: external_exports.string(),
120698
+ provider: external_exports.string(),
120699
+ /** What the window is: `5h`, `7d` or `extra usage` for an Anthropic account, or the provider's own measure and period (`tokens 5h`). */
120700
+ window: external_exports.string(),
120701
+ /** When the state the window comes from was observed, as an ISO instant. */
120702
+ observedAt: external_exports.iso.datetime(),
120703
+ /** When the window resets, as an ISO instant; absent when the upstream reported none. */
120704
+ resetsAt: external_exports.iso.datetime().optional(),
120705
+ /** True when the reset time has passed, so the recorded observation describes a window that no longer exists and its utilisation reads as 0. */
120706
+ reset: external_exports.boolean(),
120707
+ /** The fraction used, as `effectiveWindow` reads it at the report's own clock. */
120708
+ utilization: external_exports.number().optional(),
120709
+ /** The window's own status, for a window that has not reset yet. */
120710
+ status: external_exports.string().optional()
120711
+ });
120712
+ var ResetScheduleSchema = external_exports.strictObject({ resets: external_exports.readonly(external_exports.array(ResetRowSchema)) });
120713
+
120613
120714
  // src/frontdoor/controlSchemas.ts
120614
120715
  var import_node_path41 = __toESM(require("node:path"), 1);
120615
120716
  init_zod();
@@ -123735,6 +123836,7 @@ function createControlApiRouter(deps) {
123735
123836
  return {
123736
123837
  usage: {
123737
123838
  list: authed.meta(openapi({ method: "GET", path: "/rest/usage/snapshots", summary: "List every identity's usage snapshot", tags: [USAGE_API_TAG] })).output(UsageListOutputSchema).handler(() => ({ snapshots: deps.usageSnapshots() })),
123839
+ resets: authed.meta(openapi({ method: "GET", path: "/rest/usage/resets", summary: "List every recorded quota window with when it resets", tags: [USAGE_API_TAG] })).output(ResetScheduleSchema).handler(() => collectResets(deps.usageSnapshots(), deps.now())),
123738
123840
  effectiveWindow: authed.meta(openapi({ method: "GET", path: "/rest/usage/windows", summary: "Read one identity's effective quota windows", tags: [USAGE_API_TAG] })).input(UsageWindowsInputSchema).output(UsageWindowsOutputSchema).handler(({ input: input2 }) => {
123739
123841
  const snapshot = deps.usageSnapshotOf(input2.identity);
123740
123842
  if (snapshot === void 0) {
@@ -123924,11 +124026,11 @@ function rcFanoutOnDoorHub(fanout, hub) {
123924
124026
 
123925
124027
  // src/frontdoor/quotaExpiringEvents.ts
123926
124028
  init_schema2();
123927
- var MS_PER_HOUR3 = 36e5;
124029
+ var MS_PER_HOUR4 = 36e5;
123928
124030
  var MS_PER_DAY3 = 864e5;
123929
124031
  var FIVE_HOUR_WINDOW_HOURS = 5;
123930
124032
  var SEVEN_DAY_WINDOW_DAYS = 7;
123931
- var FIVE_HOUR_WINDOW_MS2 = FIVE_HOUR_WINDOW_HOURS * MS_PER_HOUR3;
124033
+ var FIVE_HOUR_WINDOW_MS2 = FIVE_HOUR_WINDOW_HOURS * MS_PER_HOUR4;
123932
124034
  var SEVEN_DAY_WINDOW_MS2 = SEVEN_DAY_WINDOW_DAYS * MS_PER_DAY3;
123933
124035
  var FINAL_SPAN_DENOMINATOR = 30;
123934
124036
  var QUOTA_EXPIRING_WINDOW_FRACTION = 1 / FINAL_SPAN_DENOMINATOR;
@@ -126747,7 +126849,7 @@ function numberOf(record2, field) {
126747
126849
  }
126748
126850
  return void 0;
126749
126851
  }
126750
- function pageOfRcChannel(url2, rows, idOf, rowOf) {
126852
+ function pageOfRcChannel(url2, rows, idOf, rowOf2) {
126751
126853
  const query = new URL(url2, "http://127.0.0.1").searchParams;
126752
126854
  const anchor2 = query.get("after_event_id") ?? query.get("cursor");
126753
126855
  const rawLimit = query.get("limit");
@@ -126761,7 +126863,7 @@ function pageOfRcChannel(url2, rows, idOf, rowOf) {
126761
126863
  }
126762
126864
  const page = limit === void 0 ? rows.slice(from) : rows.slice(from, from + limit);
126763
126865
  const last = page[page.length - 1];
126764
- return { data: page.map(rowOf), ...last === void 0 ? {} : { next_cursor: idOf(last) } };
126866
+ return { data: page.map(rowOf2), ...last === void 0 ? {} : { next_cursor: idOf(last) } };
126765
126867
  }
126766
126868
  async function serveRcClientChannels(ctx, tail, method, maxBatchEvents) {
126767
126869
  const { request: request7, response, host } = ctx;
@@ -139643,14 +139745,14 @@ function collectUsageReport(fs22, paths, filters) {
139643
139745
  invalidLines: log.invalidLines
139644
139746
  };
139645
139747
  }
139646
- var PERCENT4 = 100;
139748
+ var PERCENT5 = 100;
139647
139749
  var DECIMAL_RADIX = 10;
139648
139750
  function formatWindow(label, window) {
139649
139751
  if (window === void 0) {
139650
139752
  return void 0;
139651
139753
  }
139652
- const used = window.utilization === void 0 ? "usage unknown" : `${String(Math.round(window.utilization * PERCENT4))}% used`;
139653
- const grace = window.graceUtilization === void 0 ? "" : `, in grace, ${String(Math.round(window.graceUtilization * PERCENT4))}% of the allowance used`;
139754
+ const used = window.utilization === void 0 ? "usage unknown" : `${String(Math.round(window.utilization * PERCENT5))}% used`;
139755
+ const grace = window.graceUtilization === void 0 ? "" : `, in grace, ${String(Math.round(window.graceUtilization * PERCENT5))}% of the allowance used`;
139654
139756
  return `${label} ${used}${grace}${window.resetsAt === void 0 ? "" : `, resets ${window.resetsAt}`}${window.status === void 0 ? "" : ` (${window.status})`}`;
139655
139757
  }
139656
139758
  function formatMoney(minor, currency) {
@@ -139687,15 +139789,6 @@ function formatLimit(limit) {
139687
139789
  return `last limit: ${limit.kind} (${String(limit.status)}) at ${limit.observedAt}${limit.window === void 0 ? "" : ` on the ${limit.window} window`}${wait2.length === 0 ? "" : `, ${wait2.join(", ")}`}`;
139688
139790
  }
139689
139791
  var MONEY_DECIMALS = 2;
139690
- var MS_PER_HOUR4 = 36e5;
139691
- var HOURS_PER_DAY4 = 24;
139692
- function formatPeriod(window) {
139693
- if (window.periodMs === void 0) {
139694
- return window.period ?? "unknown period";
139695
- }
139696
- const hours = window.periodMs / MS_PER_HOUR4;
139697
- return hours >= HOURS_PER_DAY4 && Number.isInteger(hours / HOURS_PER_DAY4) ? `${String(hours / HOURS_PER_DAY4)}d` : `${String(hours)}h`;
139698
- }
139699
139792
  function formatCount(value2) {
139700
139793
  return String(Number(value2.toFixed(MONEY_DECIMALS)));
139701
139794
  }
@@ -139704,7 +139797,7 @@ function formatQuota(quota) {
139704
139797
  const counts = window.used !== void 0 && window.limit !== void 0 ? `, ${formatCount(window.used)} of ${formatCount(window.limit)}` : "";
139705
139798
  const resets = window.resetsAt === void 0 ? "" : `, resets ${window.resetsAt}`;
139706
139799
  const head = index === 0 ? `quota via ${quota.source}${quota.level === void 0 ? "" : ` (${quota.level})`}, observed ${quota.observedAt}: ` : " ";
139707
- return ` ${head}${window.measures} ${formatPeriod(window)} ${String(Math.round(window.utilization * PERCENT4))}% used${counts}${resets}`;
139800
+ return ` ${head}${window.measures} ${formatPeriod(window)} ${String(Math.round(window.utilization * PERCENT5))}% used${counts}${resets}`;
139708
139801
  });
139709
139802
  }
139710
139803
  function snapshotLines(snapshot, provider) {
@@ -139831,7 +139924,7 @@ function registerUsageCommands(program2, deps) {
139831
139924
  withExamples(
139832
139925
  program2.command("usage").description(
139833
139926
  `Report recorded requests, token usage and the latest quota state per identity and provider, from the usage log the front door writes (the last ${String(USAGE_RETENTION_MS / DAY_MS3)} days). Read-only.`
139834
- ).option("--identity <name>", "Only this identity's requests and snapshot.").option("--provider <name>", "Only this provider's requests (anthropic for OAuth sessions).").option("--since <duration>", "Only requests from this long ago on: a count followed by m, h, d or w, such as 5h or 7d.", parseDurationOption).option("--refresh", "First fetch the quota of providers that report it through their own usage endpoint (z.ai) or a plan-window usage endpoint (Anthropic subscriptions), regardless of how fresh the stored one is.").option("--json", "Print the report as JSON.").action(async (options) => {
139927
+ ).option("--identity <name>", "Only this identity's requests and snapshot.").option("--provider <name>", "Only this provider's requests (anthropic for OAuth sessions).").option("--since <duration>", "Only requests from this long ago on: a count followed by m, h, d or w, such as 5h or 7d.", parseDurationOption).option("--refresh", "First fetch the quota of providers that report it through their own usage endpoint (z.ai) or a plan-window usage endpoint (Anthropic subscriptions), regardless of how fresh the stored one is.").option("--resets", "Instead of the usage report, list every recorded quota window with when it resets, soonest first.").option("--json", "Print the report as JSON.").action(async (options) => {
139835
139928
  if (options.refresh === true) {
139836
139929
  for (const warning of await refreshQuotas(paths, { ...options.identity === void 0 ? {} : { identity: options.identity }, ...options.provider === void 0 ? {} : { provider: options.provider } })) {
139837
139930
  console.error(warning);
@@ -139842,6 +139935,18 @@ function registerUsageCommands(program2, deps) {
139842
139935
  ...options.provider === void 0 ? {} : { provider: options.provider },
139843
139936
  ...options.since === void 0 ? {} : { sinceMs: Date.now() - options.since }
139844
139937
  });
139938
+ if (options.resets === true) {
139939
+ const nowMs = Date.now();
139940
+ const schedule = collectResets(report.snapshots, nowMs);
139941
+ if (options.json === true) {
139942
+ printJson(schedule);
139943
+ return;
139944
+ }
139945
+ for (const line of schedule.resets.length === 0 ? ["no quota windows recorded yet"] : schedule.resets.map((row) => formatResetRow(row, nowMs))) {
139946
+ console.log(line);
139947
+ }
139948
+ return;
139949
+ }
139845
139950
  if (options.json === true) {
139846
139951
  printJson(report);
139847
139952
  return;
@@ -139850,7 +139955,7 @@ function registerUsageCommands(program2, deps) {
139850
139955
  console.log(line);
139851
139956
  }
139852
139957
  }),
139853
- ["agent-shim usage", "agent-shim usage --identity work --since 5h", "agent-shim usage --provider z --refresh --json"]
139958
+ ["agent-shim usage", "agent-shim usage --identity work --since 5h", "agent-shim usage --provider z --refresh --json", "agent-shim usage --resets"]
139854
139959
  );
139855
139960
  const account = withExamples(program2.command("account").description("Inspect the Claude account behind each identity: plan, tier and latest quota."), [
139856
139961
  "agent-shim account show work"