ccusage 16.2.0 → 16.2.2

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/dist/index.js CHANGED
@@ -1,12 +1,12 @@
1
1
  #!/usr/bin/env node
2
- import { BLOCKS_COMPACT_WIDTH_THRESHOLD, BLOCKS_DEFAULT_TERMINAL_WIDTH, BLOCKS_WARNING_THRESHOLD, BURN_RATE_THRESHOLDS, CONFIG_FILE_NAME, DEFAULT_CONTEXT_USAGE_THRESHOLDS, DEFAULT_RECENT_DAYS, DEFAULT_REFRESH_INTERVAL_SECONDS, MAX_REFRESH_INTERVAL_SECONDS, MCP_DEFAULT_PORT, MIN_REFRESH_INTERVAL_SECONDS, MIN_RENDER_INTERVAL_MS, PricingFetcher, WEEK_DAYS, __commonJSMin, __require, __toESM, andThen, fail, inspect, inspectError, isFailure, isSuccess, map, pipe, require_usingCtx, succeed, try_ } from "./pricing-fetcher-CoBMgxFA.js";
2
+ import { BLOCKS_COMPACT_WIDTH_THRESHOLD, BLOCKS_DEFAULT_TERMINAL_WIDTH, BLOCKS_WARNING_THRESHOLD, BURN_RATE_THRESHOLDS, CONFIG_FILE_NAME, DEFAULT_CONTEXT_USAGE_THRESHOLDS, DEFAULT_LOCALE, DEFAULT_RECENT_DAYS, DEFAULT_REFRESH_INTERVAL_SECONDS, MAX_REFRESH_INTERVAL_SECONDS, MCP_DEFAULT_PORT, MIN_REFRESH_INTERVAL_SECONDS, MIN_RENDER_INTERVAL_MS, PricingFetcher, WEEK_DAYS, __commonJSMin, __require, __toESM, andThen, fail, inspect, inspectError, isFailure, isSuccess, map, pipe, require_usingCtx, succeed, try_ } from "./pricing-fetcher-DPt1jOSj.js";
3
3
  import { getTotalTokens } from "./_token-utils-WjkbrjKv.js";
4
4
  import { CostModes, SortOrders, coerce, filterDateSchema, statuslineHookJsonSchema } from "./_types-DIdtMJ6V.js";
5
5
  import { calculateTotals, createTotalsObject } from "./calculate-cost-BDqO4yWA.js";
6
- import { DEFAULT_SESSION_DURATION_HOURS, calculateBurnRate, calculateContextTokens, calculateCostForEntry, createUniqueHash, filterRecentBlocks, formatDateCompact, getClaudePaths, getEarliestTimestamp, getUsageLimitResetTime, globUsageFiles, identifySessionBlocks, loadDailyUsageData, loadMonthlyUsageData, loadSessionBlockData, loadSessionData, loadSessionUsageById, loadWeeklyUsageData, projectBlockUsage, sortFilesByTimestamp, toArray, uniq, unwrap, usageDataSchema } from "./data-loader-C7KK9Yu0.js";
7
- import { description, log, logger, name, version } from "./logger-DKCIi_ai.js";
8
- import { detectMismatches, printMismatchReport } from "./debug-BOv8jTQu.js";
9
- import { createMcpHttpApp, createMcpServer, startMcpServerStdio } from "./mcp-DDHqWuGb.js";
6
+ import { DEFAULT_SESSION_DURATION_HOURS, calculateBurnRate, calculateContextTokens, calculateCostForEntry, createUniqueHash, filterRecentBlocks, formatDateCompact, getClaudePaths, getEarliestTimestamp, getFileModifiedTime, getUsageLimitResetTime, globUsageFiles, identifySessionBlocks, loadDailyUsageData, loadMonthlyUsageData, loadSessionBlockData, loadSessionData, loadSessionUsageById, loadWeeklyUsageData, projectBlockUsage, sortFilesByTimestamp, toArray, uniq, unreachable, unwrap, usageDataSchema } from "./data-loader-DGbft8qX.js";
7
+ import { description, log, logger, name, version } from "./logger-CCzV_6Z4.js";
8
+ import { detectMismatches, printMismatchReport } from "./debug-CBbNSr0C.js";
9
+ import { createMcpHttpApp, createMcpServer, startMcpServerStdio } from "./mcp-CdsxcdNL.js";
10
10
  import a, { readFile, stat } from "node:fs/promises";
11
11
  import path, { join } from "node:path";
12
12
  import process$1 from "node:process";
@@ -22,7 +22,7 @@ import { createServer } from "node:http";
22
22
  import { Http2ServerRequest } from "node:http2";
23
23
  import { Readable } from "node:stream";
24
24
  import crypto from "node:crypto";
25
- const DEFAULT_LOCALE = "en-US", BUILT_IN_PREFIX = "_", ARG_PREFIX = "arg", BUILT_IN_KEY_SEPARATOR = ":", ANONYMOUS_COMMAND_NAME = "(anonymous)", NOOP = () => {}, COMMON_ARGS = {
25
+ const DEFAULT_LOCALE$1 = "en-US", BUILT_IN_PREFIX = "_", ARG_PREFIX = "arg", BUILT_IN_KEY_SEPARATOR = ":", ANONYMOUS_COMMAND_NAME = "(anonymous)", NOOP = () => {}, COMMON_ARGS = {
26
26
  help: {
27
27
  type: "boolean",
28
28
  short: "h",
@@ -138,7 +138,7 @@ var DefaultTranslation = class {
138
138
  translate(locale, key, values = create()) {
139
139
  let message = this.getMessage(locale, key);
140
140
  if (message === void 0 && locale !== this.#options.fallbackLocale) message = this.getMessage(this.#options.fallbackLocale, key);
141
- if (message !== void 0) return message.replaceAll(/\{\{(\w+)\}\}/g, (_, name$1) => {
141
+ if (message !== void 0) return message.replaceAll(/\{\{(\w+)\}\}/g, (_$1, name$1) => {
142
142
  return values[name$1] == null ? "" : values[name$1].toString();
143
143
  });
144
144
  }
@@ -149,16 +149,16 @@ async function createCommandContext({ args, values, positionals, rest, argv: arg
149
149
  return acc[key] = Object.assign(create(), value$1), acc;
150
150
  }, create()), env$2 = Object.assign(create(), COMMAND_OPTIONS_DEFAULT, cliOptions), locale = resolveLocale(cliOptions.locale), localeStr = locale.toString(), translationAdapterFactory = cliOptions.translationAdapterFactory || createTranslationAdapter, adapter = translationAdapterFactory({
151
151
  locale: localeStr,
152
- fallbackLocale: DEFAULT_LOCALE
152
+ fallbackLocale: DEFAULT_LOCALE$1
153
153
  }), localeResources = /* @__PURE__ */ new Map();
154
154
  let builtInLoadedResources;
155
- if (localeResources.set(DEFAULT_LOCALE, mapResourceWithBuiltinKey(en_US_default)), DEFAULT_LOCALE !== localeStr) try {
155
+ if (localeResources.set(DEFAULT_LOCALE$1, mapResourceWithBuiltinKey(en_US_default)), DEFAULT_LOCALE$1 !== localeStr) try {
156
156
  builtInLoadedResources = (await import(`./locales/${localeStr}.json`, { with: { type: "json" } })).default, localeResources.set(localeStr, mapResourceWithBuiltinKey(builtInLoadedResources));
157
157
  } catch {}
158
158
  function translate(key, values$1 = create()) {
159
159
  const strKey = key;
160
160
  if (strKey.codePointAt(0) === BUILT_IN_PREFIX_CODE) {
161
- const resource = localeResources.get(localeStr) || localeResources.get(DEFAULT_LOCALE);
161
+ const resource = localeResources.get(localeStr) || localeResources.get(DEFAULT_LOCALE$1);
162
162
  return resource[strKey] || strKey;
163
163
  } else return adapter.translate(locale.toString(), strKey, values$1) || "";
164
164
  }
@@ -191,7 +191,7 @@ async function createCommandContext({ args, values, positionals, rest, argv: arg
191
191
  }), defaultCommandResource = loadedOptionsResources.reduce((res, [key, value$1]) => {
192
192
  return res[resolveArgKey(key)] = value$1, res;
193
193
  }, create());
194
- defaultCommandResource.description = command.description || "", defaultCommandResource.examples = await resolveExamples(ctx, command.examples), adapter.setResource(DEFAULT_LOCALE, defaultCommandResource);
194
+ defaultCommandResource.description = command.description || "", defaultCommandResource.examples = await resolveExamples(ctx, command.examples), adapter.setResource(DEFAULT_LOCALE$1, defaultCommandResource);
195
195
  const originalResource = await loadCommandResource(ctx, command);
196
196
  if (originalResource) {
197
197
  const resource = Object.assign(create(), originalResource, { examples: await resolveExamples(ctx, originalResource.examples) });
@@ -204,7 +204,7 @@ function getCommandName(cmd) {
204
204
  return isLazyCommand(cmd) ? cmd.commandName || cmd.name || ANONYMOUS_COMMAND_NAME : typeof cmd === "object" && cmd.name || ANONYMOUS_COMMAND_NAME;
205
205
  }
206
206
  function resolveLocale(locale) {
207
- return locale instanceof Intl.Locale ? locale : typeof locale === "string" ? new Intl.Locale(locale) : new Intl.Locale(DEFAULT_LOCALE);
207
+ return locale instanceof Intl.Locale ? locale : typeof locale === "string" ? new Intl.Locale(locale) : new Intl.Locale(DEFAULT_LOCALE$1);
208
208
  }
209
209
  async function loadCommandResource(ctx, command) {
210
210
  let resource;
@@ -351,7 +351,7 @@ function resolveDisplayValue(ctx, key) {
351
351
  return "";
352
352
  }
353
353
  async function generateOptionalArgsUsage(ctx, optionsPairs) {
354
- const optionsMaxLength = Math.max(...Object.entries(optionsPairs).map(([_, value$1]) => value$1.length)), optionSchemaMaxLength = ctx.env.usageOptionType ? Math.max(...Object.entries(optionsPairs).map(([key]) => resolveNegatableType(key, ctx).length)) : 0, usages = await Promise.all(Object.entries(optionsPairs).map(([key, value$1]) => {
354
+ const optionsMaxLength = Math.max(...Object.entries(optionsPairs).map(([_$1, value$1]) => value$1.length)), optionSchemaMaxLength = ctx.env.usageOptionType ? Math.max(...Object.entries(optionsPairs).map(([key]) => resolveNegatableType(key, ctx).length)) : 0, usages = await Promise.all(Object.entries(optionsPairs).map(([key, value$1]) => {
355
355
  let rawDesc = ctx.translate(resolveArgKey(key));
356
356
  if (!rawDesc && key.startsWith("no-")) {
357
357
  const name$1 = resolveNegatableKey(key), schema = ctx.args[name$1], optionKey = makeShortLongOptionPair(schema, name$1, ctx.toKebab);
@@ -363,7 +363,7 @@ async function generateOptionalArgsUsage(ctx, optionsPairs) {
363
363
  return usages.join("\n");
364
364
  }
365
365
  function getPositionalArgs(ctx) {
366
- return Object.entries(ctx.args).filter(([_, schema]) => schema.type === "positional");
366
+ return Object.entries(ctx.args).filter(([_$1, schema]) => schema.type === "positional");
367
367
  }
368
368
  async function generatePositionalArgsUsage(ctx) {
369
369
  const positionals = getPositionalArgs(ctx), argsMaxLength = Math.max(...positionals.map(([name$1]) => name$1.length)), usages = await Promise.all(positionals.map(([name$1]) => {
@@ -817,7 +817,7 @@ var require_picocolors = /* @__PURE__ */ __commonJSMin(((exports, module) => {
817
817
  };
818
818
  };
819
819
  module.exports = createColors(), module.exports.createColors = createColors;
820
- })), import_picocolors$8 = /* @__PURE__ */ __toESM(require_picocolors(), 1), import_usingCtx$4 = /* @__PURE__ */ __toESM(require_usingCtx(), 1);
820
+ })), import_picocolors$5 = /* @__PURE__ */ __toESM(require_picocolors(), 1), import_usingCtx$3 = /* @__PURE__ */ __toESM(require_usingCtx(), 1);
821
821
  function extractExplicitArgs(tokens) {
822
822
  const explicit = {};
823
823
  for (const token of tokens) if (typeof token === "object" && token !== null) {
@@ -1157,7 +1157,7 @@ const sharedArgs = {
1157
1157
  type: "string",
1158
1158
  short: "l",
1159
1159
  description: "Locale for date/time formatting (e.g., en-US, ja-JP, de-DE)",
1160
- default: "en-CA"
1160
+ default: DEFAULT_LOCALE
1161
1161
  },
1162
1162
  jq: {
1163
1163
  type: "string",
@@ -2467,7 +2467,7 @@ function stringWidth(string, options = {}) {
2467
2467
  }
2468
2468
  return width;
2469
2469
  }
2470
- var import_usingCtx$3 = /* @__PURE__ */ __toESM(require_usingCtx(), 1), ResponsiveTable = class {
2470
+ var ResponsiveTable = class {
2471
2471
  head;
2472
2472
  rows = [];
2473
2473
  colAligns;
@@ -2497,9 +2497,9 @@ var import_usingCtx$3 = /* @__PURE__ */ __toESM(require_usingCtx(), 1), Responsi
2497
2497
  };
2498
2498
  }
2499
2499
  getCompactIndices() {
2500
- return this.compactHead == null || !this.compactMode ? Array.from({ length: this.head.length }, (_, i) => i) : this.compactHead.map((compactHeader) => {
2500
+ return this.compactHead == null || !this.compactMode ? Array.from({ length: this.head.length }, (_$1, i) => i) : this.compactHead.map((compactHeader) => {
2501
2501
  const index = this.head.indexOf(compactHeader);
2502
- return index < 0 ? (console.warn(`Warning: Compact header "${compactHeader}" not found in table headers [${this.head.join(", ")}]. Using first column as fallback.`), 0) : index;
2502
+ return index < 0 ? (logger.warn(`Warning: Compact header "${compactHeader}" not found in table headers [${this.head.join(", ")}]. Using first column as fallback.`), 0) : index;
2503
2503
  });
2504
2504
  }
2505
2505
  isCompactMode() {
@@ -2510,7 +2510,7 @@ var import_usingCtx$3 = /* @__PURE__ */ __toESM(require_usingCtx(), 1), Responsi
2510
2510
  this.compactMode = this.forceCompact || terminalWidth < this.compactThreshold && this.compactHead != null;
2511
2511
  const { head, colAligns } = this.getCurrentTableConfig(), compactIndices = this.getCompactIndices(), dataRows = this.rows.filter((row) => !this.isSeparatorRow(row)), processedDataRows = this.compactMode ? dataRows.map((row) => this.filterRowToCompact(row, compactIndices)) : dataRows, allRows = [head.map(String), ...processedDataRows.map((row) => row.map((cell) => {
2512
2512
  return typeof cell === "object" && cell != null && "content" in cell ? String(cell.content) : String(cell ?? "");
2513
- }))], contentWidths = head.map((_, colIndex) => {
2513
+ }))], contentWidths = head.map((_$1, colIndex) => {
2514
2514
  const maxLength = Math.max(...allRows.map((row) => stringWidth(String(row[colIndex] ?? ""))));
2515
2515
  return maxLength;
2516
2516
  }), numColumns = head.length, tableOverhead = 3 * numColumns + 1, availableWidth = terminalWidth - tableOverhead, columnWidths = contentWidths.map((width, index) => {
@@ -2592,16 +2592,86 @@ function pushBreakdownRows(table, breakdowns, extraColumns = 1, trailingColumns
2592
2592
  const row = [` └─ ${formatModelName(breakdown.modelName)}`];
2593
2593
  for (let i = 0; i < extraColumns; i++) row.push("");
2594
2594
  const totalTokens = breakdown.inputTokens + breakdown.outputTokens + breakdown.cacheCreationTokens + breakdown.cacheReadTokens;
2595
- row.push(import_picocolors$8.default.gray(formatNumber(breakdown.inputTokens)), import_picocolors$8.default.gray(formatNumber(breakdown.outputTokens)), import_picocolors$8.default.gray(formatNumber(breakdown.cacheCreationTokens)), import_picocolors$8.default.gray(formatNumber(breakdown.cacheReadTokens)), import_picocolors$8.default.gray(formatNumber(totalTokens)), import_picocolors$8.default.gray(formatCurrency(breakdown.cost)));
2595
+ row.push(import_picocolors$5.default.gray(formatNumber(breakdown.inputTokens)), import_picocolors$5.default.gray(formatNumber(breakdown.outputTokens)), import_picocolors$5.default.gray(formatNumber(breakdown.cacheCreationTokens)), import_picocolors$5.default.gray(formatNumber(breakdown.cacheReadTokens)), import_picocolors$5.default.gray(formatNumber(totalTokens)), import_picocolors$5.default.gray(formatCurrency(breakdown.cost)));
2596
2596
  for (let i = 0; i < trailingColumns; i++) row.push("");
2597
2597
  table.push(row);
2598
2598
  }
2599
2599
  }
2600
- async function getFileModifiedTime(filePath) {
2601
- return pipe(try_({
2602
- try: stat(filePath),
2603
- catch: (error) => error
2604
- }), map((stats) => stats.mtime.getTime()), unwrap(0));
2600
+ function createUsageReportTable(config) {
2601
+ const baseHeaders = [
2602
+ config.firstColumnName,
2603
+ "Models",
2604
+ "Input",
2605
+ "Output",
2606
+ "Cache Create",
2607
+ "Cache Read",
2608
+ "Total Tokens",
2609
+ "Cost (USD)"
2610
+ ], baseAligns = [
2611
+ "left",
2612
+ "left",
2613
+ "right",
2614
+ "right",
2615
+ "right",
2616
+ "right",
2617
+ "right",
2618
+ "right"
2619
+ ], compactHeaders = [
2620
+ config.firstColumnName,
2621
+ "Models",
2622
+ "Input",
2623
+ "Output",
2624
+ "Cost (USD)"
2625
+ ], compactAligns = [
2626
+ "left",
2627
+ "left",
2628
+ "right",
2629
+ "right",
2630
+ "right"
2631
+ ];
2632
+ if (config.includeLastActivity ?? false) baseHeaders.push("Last Activity"), baseAligns.push("left"), compactHeaders.push("Last Activity"), compactAligns.push("left");
2633
+ return new ResponsiveTable({
2634
+ head: baseHeaders,
2635
+ style: { head: ["cyan"] },
2636
+ colAligns: baseAligns,
2637
+ dateFormatter: config.dateFormatter,
2638
+ compactHead: compactHeaders,
2639
+ compactColAligns: compactAligns,
2640
+ compactThreshold: 100,
2641
+ forceCompact: config.forceCompact
2642
+ });
2643
+ }
2644
+ function formatUsageDataRow(firstColumnValue, data, lastActivity) {
2645
+ const totalTokens = data.inputTokens + data.outputTokens + data.cacheCreationTokens + data.cacheReadTokens, row = [
2646
+ firstColumnValue,
2647
+ data.modelsUsed != null ? formatModelsDisplayMultiline(data.modelsUsed) : "",
2648
+ formatNumber(data.inputTokens),
2649
+ formatNumber(data.outputTokens),
2650
+ formatNumber(data.cacheCreationTokens),
2651
+ formatNumber(data.cacheReadTokens),
2652
+ formatNumber(totalTokens),
2653
+ formatCurrency(data.totalCost)
2654
+ ];
2655
+ if (lastActivity !== void 0) row.push(lastActivity);
2656
+ return row;
2657
+ }
2658
+ function formatTotalsRow(totals, includeLastActivity = false) {
2659
+ const totalTokens = totals.inputTokens + totals.outputTokens + totals.cacheCreationTokens + totals.cacheReadTokens, row = [
2660
+ import_picocolors$5.default.yellow("Total"),
2661
+ "",
2662
+ import_picocolors$5.default.yellow(formatNumber(totals.inputTokens)),
2663
+ import_picocolors$5.default.yellow(formatNumber(totals.outputTokens)),
2664
+ import_picocolors$5.default.yellow(formatNumber(totals.cacheCreationTokens)),
2665
+ import_picocolors$5.default.yellow(formatNumber(totals.cacheReadTokens)),
2666
+ import_picocolors$5.default.yellow(formatNumber(totalTokens)),
2667
+ import_picocolors$5.default.yellow(formatCurrency(totals.totalCost))
2668
+ ];
2669
+ if (includeLastActivity) row.push("");
2670
+ return row;
2671
+ }
2672
+ function addEmptySeparatorRow(table, columnCount) {
2673
+ const emptyRow = Array.from({ length: columnCount }, () => "");
2674
+ table.push(emptyRow);
2605
2675
  }
2606
2676
  var Node = class {
2607
2677
  value;
@@ -2995,20 +3065,20 @@ const SAVE_CURSOR = "\x1B7", RESTORE_CURSOR = "\x1B8";
2995
3065
  function drawEmoji(emoji) {
2996
3066
  return `${SAVE_CURSOR}${emoji}${RESTORE_CURSOR}${cursorForward(stringWidth(emoji))}`;
2997
3067
  }
2998
- var import_picocolors$7 = /* @__PURE__ */ __toESM(require_picocolors(), 1);
3068
+ var import_picocolors$4 = /* @__PURE__ */ __toESM(require_picocolors(), 1);
2999
3069
  function getRateIndicator(burnRate) {
3000
3070
  if (burnRate == null) return "";
3001
3071
  switch (true) {
3002
- case burnRate.tokensPerMinuteForIndicator > BURN_RATE_THRESHOLDS.HIGH: return import_picocolors$7.default.red(`${drawEmoji("⚡")} HIGH`);
3003
- case burnRate.tokensPerMinuteForIndicator > BURN_RATE_THRESHOLDS.MODERATE: return import_picocolors$7.default.yellow(`${drawEmoji("⚡")} MODERATE`);
3004
- default: return import_picocolors$7.default.green(`${drawEmoji("✓")} NORMAL`);
3072
+ case burnRate.tokensPerMinuteForIndicator > BURN_RATE_THRESHOLDS.HIGH: return import_picocolors$4.default.red(`${drawEmoji("⚡")} HIGH`);
3073
+ case burnRate.tokensPerMinuteForIndicator > BURN_RATE_THRESHOLDS.MODERATE: return import_picocolors$4.default.yellow(`${drawEmoji("⚡")} MODERATE`);
3074
+ default: return import_picocolors$4.default.green(`${drawEmoji("✓")} NORMAL`);
3005
3075
  }
3006
3076
  }
3007
3077
  async function delayWithAbort(ms, signal) {
3008
3078
  await delay(ms, { signal });
3009
3079
  }
3010
3080
  async function renderWaitingState(terminal, config, signal) {
3011
- terminal.startBuffering(), terminal.write(cursorTo(0, 0)), terminal.write(eraseDown), terminal.write(import_picocolors$7.default.yellow("No active session block found. Waiting...\n")), terminal.write(cursorHide), terminal.flush(), await delayWithAbort(config.refreshInterval, signal);
3081
+ terminal.startBuffering(), terminal.write(cursorTo(0, 0)), terminal.write(eraseDown), terminal.write(import_picocolors$4.default.yellow("No active session block found. Waiting...\n")), terminal.write(cursorHide), terminal.flush(), await delayWithAbort(config.refreshInterval, signal);
3012
3082
  }
3013
3083
  function renderActiveBlock(terminal, activeBlock, config) {
3014
3084
  terminal.startBuffering(), terminal.write(cursorTo(0, 0)), terminal.write(eraseDown), renderLiveDisplay(terminal, activeBlock, config), terminal.write(cursorHide), terminal.flush();
@@ -3026,8 +3096,8 @@ function renderLiveDisplay(terminal, block, config) {
3026
3096
  }
3027
3097
  const boxWidth = Math.min(120, width - 2), boxMargin = Math.floor((width - boxWidth) / 2), marginStr = " ".repeat(boxMargin), sessionDuration = elapsed + remaining, sessionPercent = elapsed / sessionDuration * 100, sessionRightText = `${sessionPercent.toFixed(1).padStart(6)}%`, tokenPercent = config.tokenLimit != null && config.tokenLimit > 0 ? totalTokens / config.tokenLimit * 100 : 0, usageRightText = config.tokenLimit != null && config.tokenLimit > 0 ? `${tokenPercent.toFixed(1).padStart(6)}% (${formatTokensShort(totalTokens)}/${formatTokensShort(config.tokenLimit)})` : `(${formatTokensShort(totalTokens)} tokens)`, projection = projectBlockUsage(block), projectedPercent = projection != null && config.tokenLimit != null && config.tokenLimit > 0 ? projection.totalTokens / config.tokenLimit * 100 : 0, projectionRightText = projection != null ? config.tokenLimit != null && config.tokenLimit > 0 ? `${projectedPercent.toFixed(1).padStart(6)}% (${formatTokensShort(projection.totalTokens)}/${formatTokensShort(config.tokenLimit)})` : `(${formatTokensShort(projection.totalTokens)} tokens)` : "", maxRightTextWidth = Math.max(stringWidth(sessionRightText), stringWidth(usageRightText), projection != null ? stringWidth(projectionRightText) : 0), labelWidth = 14, spacing = 4, boxPadding = 4, barWidth = boxWidth - labelWidth - maxRightTextWidth - spacing - boxPadding, sessionProgressBar = createProgressBar(elapsed, sessionDuration, barWidth, {
3028
3098
  showPercentage: false,
3029
- fillChar: import_picocolors$7.default.cyan("█"),
3030
- emptyChar: import_picocolors$7.default.gray("░"),
3099
+ fillChar: import_picocolors$4.default.cyan("█"),
3100
+ emptyChar: import_picocolors$4.default.gray("░"),
3031
3101
  leftBracket: "[",
3032
3102
  rightBracket: "]"
3033
3103
  }), startTime = block.startTime.toLocaleTimeString(void 0, {
@@ -3041,10 +3111,10 @@ function renderLiveDisplay(terminal, block, config) {
3041
3111
  second: "2-digit",
3042
3112
  hour12: true
3043
3113
  }), detailsIndent = 3, detailsSpacing = 2, detailsAvailableWidth = boxWidth - 3 - detailsIndent;
3044
- terminal.write(`${marginStr}┌${"─".repeat(boxWidth - 2)}┐\n`), terminal.write(`${marginStr}│${import_picocolors$7.default.bold(centerText("CLAUDE CODE - LIVE TOKEN USAGE MONITOR", boxWidth - 2))}│\n`), terminal.write(`${marginStr}├${"─".repeat(boxWidth - 2)}┤\n`), terminal.write(`${marginStr}│${" ".repeat(boxWidth - 2)}│\n`);
3045
- const sessionLabel = `${drawEmoji("⏱️")}${import_picocolors$7.default.bold(" SESSION")}`, sessionLabelWidth = stringWidth(sessionLabel), sessionBarStr = `${sessionLabel}${"".padEnd(Math.max(0, labelWidth - sessionLabelWidth))} ${sessionProgressBar} ${sessionRightText}`, sessionBarPadded = sessionBarStr + " ".repeat(Math.max(0, boxWidth - 3 - stringWidth(sessionBarStr)));
3114
+ terminal.write(`${marginStr}┌${"─".repeat(boxWidth - 2)}┐\n`), terminal.write(`${marginStr}│${import_picocolors$4.default.bold(centerText("CLAUDE CODE - LIVE TOKEN USAGE MONITOR", boxWidth - 2))}│\n`), terminal.write(`${marginStr}├${"─".repeat(boxWidth - 2)}┤\n`), terminal.write(`${marginStr}│${" ".repeat(boxWidth - 2)}│\n`);
3115
+ const sessionLabel = `${drawEmoji("⏱️")}${import_picocolors$4.default.bold(" SESSION")}`, sessionLabelWidth = stringWidth(sessionLabel), sessionBarStr = `${sessionLabel}${"".padEnd(Math.max(0, labelWidth - sessionLabelWidth))} ${sessionProgressBar} ${sessionRightText}`, sessionBarPadded = sessionBarStr + " ".repeat(Math.max(0, boxWidth - 3 - stringWidth(sessionBarStr)));
3046
3116
  terminal.write(`${marginStr}│ ${sessionBarPadded}│\n`);
3047
- const sessionCol1 = `${import_picocolors$7.default.gray("Started:")} ${startTime}`, sessionCol2 = `${import_picocolors$7.default.gray("Elapsed:")} ${prettyMilliseconds(elapsed * 60 * 1e3, { compact: true })}`, sessionCol3 = `${import_picocolors$7.default.gray("Remaining:")} ${prettyMilliseconds(remaining * 60 * 1e3, { compact: true })} (${endTime})`;
3117
+ const sessionCol1 = `${import_picocolors$4.default.gray("Started:")} ${startTime}`, sessionCol2 = `${import_picocolors$4.default.gray("Elapsed:")} ${prettyMilliseconds(elapsed * 60 * 1e3, { compact: true })}`, sessionCol3 = `${import_picocolors$4.default.gray("Remaining:")} ${prettyMilliseconds(remaining * 60 * 1e3, { compact: true })} (${endTime})`;
3048
3118
  let sessionDetails = `${" ".repeat(detailsIndent)}${sessionCol1}${" ".repeat(detailsSpacing)}${sessionCol2}${" ".repeat(detailsSpacing)}${sessionCol3}`;
3049
3119
  const sessionDetailsWidth = stringWidth(sessionCol1) + stringWidth(sessionCol2) + stringWidth(sessionCol3) + detailsSpacing * 2;
3050
3120
  if (sessionDetailsWidth > detailsAvailableWidth) sessionDetails = `${" ".repeat(detailsIndent)}${sessionCol1}${" ".repeat(detailsSpacing)}${sessionCol3}`;
@@ -3055,33 +3125,33 @@ function renderLiveDisplay(terminal, block, config) {
3055
3125
  hour: "2-digit",
3056
3126
  minute: "2-digit",
3057
3127
  hour12: true
3058
- }) ?? null, usageLimitResetTime = resetTime !== null ? import_picocolors$7.default.red(`${drawEmoji("❌")} USAGE LIMIT. RESET AT ${resetTime}`) : "";
3128
+ }) ?? null, usageLimitResetTime = resetTime !== null ? import_picocolors$4.default.red(`${drawEmoji("❌")} USAGE LIMIT. RESET AT ${resetTime}`) : "";
3059
3129
  usageLimitResetTimePadded = resetTime !== null ? usageLimitResetTime + " ".repeat(Math.max(0, boxWidth - 3 - stringWidth(usageLimitResetTime))) : null;
3060
3130
  }
3061
3131
  if (terminal.write(`${marginStr}│ ${sessionDetailsPadded}│\n`), usageLimitResetTimePadded !== null) terminal.write(`${marginStr}│ ${usageLimitResetTimePadded}│\n`);
3062
3132
  terminal.write(`${marginStr}│${" ".repeat(boxWidth - 2)}│\n`), terminal.write(`${marginStr}├${"─".repeat(boxWidth - 2)}┤\n`), terminal.write(`${marginStr}│${" ".repeat(boxWidth - 2)}│\n`);
3063
- let barColor = import_picocolors$7.default.green;
3064
- if (tokenPercent > 100) barColor = import_picocolors$7.default.red;
3065
- else if (tokenPercent > 80) barColor = import_picocolors$7.default.yellow;
3133
+ let barColor = import_picocolors$4.default.green;
3134
+ if (tokenPercent > 100) barColor = import_picocolors$4.default.red;
3135
+ else if (tokenPercent > 80) barColor = import_picocolors$4.default.yellow;
3066
3136
  const usageBar = config.tokenLimit != null && config.tokenLimit > 0 ? createProgressBar(totalTokens, config.tokenLimit, barWidth, {
3067
3137
  showPercentage: false,
3068
3138
  fillChar: barColor("█"),
3069
- emptyChar: import_picocolors$7.default.gray("░"),
3139
+ emptyChar: import_picocolors$4.default.gray("░"),
3070
3140
  leftBracket: "[",
3071
3141
  rightBracket: "]"
3072
- }) : `[${import_picocolors$7.default.green("█".repeat(Math.floor(barWidth * .1)))}${import_picocolors$7.default.gray("░".repeat(barWidth - Math.floor(barWidth * .1)))}]`, burnRate = calculateBurnRate(block), rateIndicator = getRateIndicator(burnRate), buildRateDisplay = (useShort) => {
3073
- if (burnRate == null) return `${import_picocolors$7.default.bold("Burn Rate:")} N/A`;
3142
+ }) : `[${import_picocolors$4.default.green("█".repeat(Math.floor(barWidth * .1)))}${import_picocolors$4.default.gray("░".repeat(barWidth - Math.floor(barWidth * .1)))}]`, burnRate = calculateBurnRate(block), rateIndicator = getRateIndicator(burnRate), buildRateDisplay = (useShort) => {
3143
+ if (burnRate == null) return `${import_picocolors$4.default.bold("Burn Rate:")} N/A`;
3074
3144
  const rateValue = Math.round(burnRate.tokensPerMinute), formattedRate = useShort ? formatTokensShort(rateValue) : formatNumber(rateValue);
3075
- return `${import_picocolors$7.default.bold("Burn Rate:")} ${formattedRate} token/min ${rateIndicator}`;
3076
- }, usageLabel = `${drawEmoji("🔥")}${import_picocolors$7.default.bold(" USAGE")}`, usageLabelWidth = stringWidth(usageLabel), usageBarStr = `${usageLabel}${"".padEnd(Math.max(0, labelWidth - usageLabelWidth))} ${usageBar} ${usageRightText}`;
3077
- let rateDisplay = buildRateDisplay(false), usageCol1 = `${import_picocolors$7.default.gray("Tokens:")} ${formatTokenDisplay(totalTokens, false)} (${rateDisplay})`, usageCol2 = config.tokenLimit != null && config.tokenLimit > 0 ? `${import_picocolors$7.default.gray("Limit:")} ${formatTokenDisplay(config.tokenLimit, false)} tokens` : "";
3078
- const usageCol3 = `${import_picocolors$7.default.gray("Cost:")} ${formatCurrency(block.costUSD)}`;
3145
+ return `${import_picocolors$4.default.bold("Burn Rate:")} ${formattedRate} token/min ${rateIndicator}`;
3146
+ }, usageLabel = `${drawEmoji("🔥")}${import_picocolors$4.default.bold(" USAGE")}`, usageLabelWidth = stringWidth(usageLabel), usageBarStr = `${usageLabel}${"".padEnd(Math.max(0, labelWidth - usageLabelWidth))} ${usageBar} ${usageRightText}`;
3147
+ let rateDisplay = buildRateDisplay(false), usageCol1 = `${import_picocolors$4.default.gray("Tokens:")} ${formatTokenDisplay(totalTokens, false)} (${rateDisplay})`, usageCol2 = config.tokenLimit != null && config.tokenLimit > 0 ? `${import_picocolors$4.default.gray("Limit:")} ${formatTokenDisplay(config.tokenLimit, false)} tokens` : "";
3148
+ const usageCol3 = `${import_picocolors$4.default.gray("Cost:")} ${formatCurrency(block.costUSD)}`;
3079
3149
  let totalWidth = stringWidth(usageCol1);
3080
3150
  if (usageCol2.length > 0) totalWidth += detailsSpacing + stringWidth(usageCol2);
3081
3151
  totalWidth += detailsSpacing + stringWidth(usageCol3);
3082
3152
  let useTwoLineLayout = false;
3083
3153
  if (totalWidth > detailsAvailableWidth) {
3084
- if (useTwoLineLayout = true, rateDisplay = buildRateDisplay(true), usageCol1 = `${import_picocolors$7.default.gray("Tokens:")} ${formatTokenDisplay(totalTokens, true)} (${rateDisplay})`, usageCol2.length > 0) usageCol2 = `${import_picocolors$7.default.gray("Limit:")} ${formatTokenDisplay(config.tokenLimit, true)} tokens`;
3154
+ if (useTwoLineLayout = true, rateDisplay = buildRateDisplay(true), usageCol1 = `${import_picocolors$4.default.gray("Tokens:")} ${formatTokenDisplay(totalTokens, true)} (${rateDisplay})`, usageCol2.length > 0) usageCol2 = `${import_picocolors$4.default.gray("Limit:")} ${formatTokenDisplay(config.tokenLimit, true)} tokens`;
3085
3155
  }
3086
3156
  const usageBarPadded = usageBarStr + " ".repeat(Math.max(0, boxWidth - 3 - stringWidth(usageBarStr)));
3087
3157
  if (terminal.write(`${marginStr}│ ${usageBarPadded}│\n`), useTwoLineLayout) {
@@ -3100,22 +3170,22 @@ function renderLiveDisplay(terminal, block, config) {
3100
3170
  terminal.write(`${marginStr}│ ${usageDetailsPadded}│\n`);
3101
3171
  }
3102
3172
  if (terminal.write(`${marginStr}│${" ".repeat(boxWidth - 2)}│\n`), terminal.write(`${marginStr}├${"─".repeat(boxWidth - 2)}┤\n`), terminal.write(`${marginStr}│${" ".repeat(boxWidth - 2)}│\n`), projection != null) {
3103
- let projBarColor = import_picocolors$7.default.green;
3104
- if (projectedPercent > 100) projBarColor = import_picocolors$7.default.red;
3105
- else if (projectedPercent > 80) projBarColor = import_picocolors$7.default.yellow;
3173
+ let projBarColor = import_picocolors$4.default.green;
3174
+ if (projectedPercent > 100) projBarColor = import_picocolors$4.default.red;
3175
+ else if (projectedPercent > 80) projBarColor = import_picocolors$4.default.yellow;
3106
3176
  const projectionBar = config.tokenLimit != null && config.tokenLimit > 0 ? createProgressBar(projection.totalTokens, config.tokenLimit, barWidth, {
3107
3177
  showPercentage: false,
3108
3178
  fillChar: projBarColor("█"),
3109
- emptyChar: import_picocolors$7.default.gray("░"),
3179
+ emptyChar: import_picocolors$4.default.gray("░"),
3110
3180
  leftBracket: "[",
3111
3181
  rightBracket: "]"
3112
- }) : `[${import_picocolors$7.default.green("█".repeat(Math.floor(barWidth * .15)))}${import_picocolors$7.default.gray("░".repeat(barWidth - Math.floor(barWidth * .15)))}]`, limitStatus = config.tokenLimit != null && config.tokenLimit > 0 ? projectedPercent > 100 ? import_picocolors$7.default.red(`${drawEmoji("❌")} WILL EXCEED LIMIT`) : projectedPercent > 80 ? import_picocolors$7.default.yellow(`${drawEmoji("⚠️")} APPROACHING LIMIT`) : import_picocolors$7.default.green(`${drawEmoji("✓")} WITHIN LIMIT`) : import_picocolors$7.default.green(`${drawEmoji("✓")} ON TRACK`), projLabel = `${drawEmoji("📈")}${import_picocolors$7.default.bold(" PROJECTION")}`, projLabelWidth = stringWidth(projLabel), projBarStr = `${projLabel}${"".padEnd(Math.max(0, labelWidth - projLabelWidth))} ${projectionBar} ${projectionRightText}`, projBarPadded = projBarStr + " ".repeat(Math.max(0, boxWidth - 3 - stringWidth(projBarStr)));
3182
+ }) : `[${import_picocolors$4.default.green("█".repeat(Math.floor(barWidth * .15)))}${import_picocolors$4.default.gray("░".repeat(barWidth - Math.floor(barWidth * .15)))}]`, limitStatus = config.tokenLimit != null && config.tokenLimit > 0 ? projectedPercent > 100 ? import_picocolors$4.default.red(`${drawEmoji("❌")} WILL EXCEED LIMIT`) : projectedPercent > 80 ? import_picocolors$4.default.yellow(`${drawEmoji("⚠️")} APPROACHING LIMIT`) : import_picocolors$4.default.green(`${drawEmoji("✓")} WITHIN LIMIT`) : import_picocolors$4.default.green(`${drawEmoji("✓")} ON TRACK`), projLabel = `${drawEmoji("📈")}${import_picocolors$4.default.bold(" PROJECTION")}`, projLabelWidth = stringWidth(projLabel), projBarStr = `${projLabel}${"".padEnd(Math.max(0, labelWidth - projLabelWidth))} ${projectionBar} ${projectionRightText}`, projBarPadded = projBarStr + " ".repeat(Math.max(0, boxWidth - 3 - stringWidth(projBarStr)));
3113
3183
  terminal.write(`${marginStr}│ ${projBarPadded}│\n`);
3114
- const projCol1 = `${import_picocolors$7.default.gray("Status:")} ${limitStatus}`;
3115
- let projCol2 = `${import_picocolors$7.default.gray("Tokens:")} ${formatTokenDisplay(projection.totalTokens, false)}`;
3116
- const projCol3 = `${import_picocolors$7.default.gray("Cost:")} ${formatCurrency(projection.totalCost)}`, projTotalWidth = stringWidth(projCol1) + stringWidth(projCol2) + stringWidth(projCol3) + detailsSpacing * 2;
3184
+ const projCol1 = `${import_picocolors$4.default.gray("Status:")} ${limitStatus}`;
3185
+ let projCol2 = `${import_picocolors$4.default.gray("Tokens:")} ${formatTokenDisplay(projection.totalTokens, false)}`;
3186
+ const projCol3 = `${import_picocolors$4.default.gray("Cost:")} ${formatCurrency(projection.totalCost)}`, projTotalWidth = stringWidth(projCol1) + stringWidth(projCol2) + stringWidth(projCol3) + detailsSpacing * 2;
3117
3187
  let projUseTwoLineLayout = false;
3118
- if (projTotalWidth > detailsAvailableWidth) projUseTwoLineLayout = true, projCol2 = `${import_picocolors$7.default.gray("Tokens:")} ${formatTokenDisplay(projection.totalTokens, true)}`;
3188
+ if (projTotalWidth > detailsAvailableWidth) projUseTwoLineLayout = true, projCol2 = `${import_picocolors$4.default.gray("Tokens:")} ${formatTokenDisplay(projection.totalTokens, true)}`;
3119
3189
  if (projUseTwoLineLayout) {
3120
3190
  const projDetailsLine1 = `${" ".repeat(detailsIndent)}${projCol1}`, projDetailsLine1Padded = projDetailsLine1 + " ".repeat(Math.max(0, boxWidth - 3 - stringWidth(projDetailsLine1)));
3121
3191
  terminal.write(`${marginStr}│ ${projDetailsLine1Padded}│\n`);
@@ -3134,22 +3204,22 @@ function renderLiveDisplay(terminal, block, config) {
3134
3204
  }
3135
3205
  terminal.write(`${marginStr}├${"─".repeat(boxWidth - 2)}┤\n`);
3136
3206
  const refreshText = `${drawEmoji("↻")} Refreshing every ${config.refreshInterval / 1e3}s • Press Ctrl+C to stop`;
3137
- terminal.write(`${marginStr}│${import_picocolors$7.default.gray(centerText(refreshText, boxWidth - 2))}│\n`), terminal.write(`${marginStr}└${"─".repeat(boxWidth - 2)}┘\n`);
3207
+ terminal.write(`${marginStr}│${import_picocolors$4.default.gray(centerText(refreshText, boxWidth - 2))}│\n`), terminal.write(`${marginStr}└${"─".repeat(boxWidth - 2)}┘\n`);
3138
3208
  }
3139
3209
  function renderCompactLiveDisplay(terminal, block, config, totalTokens, elapsed, remaining) {
3140
3210
  const width = terminal.width;
3141
- terminal.write(`${import_picocolors$7.default.bold(centerText("LIVE MONITOR", width))}\n`), terminal.write(`${"─".repeat(width)}\n`);
3211
+ terminal.write(`${import_picocolors$4.default.bold(centerText("LIVE MONITOR", width))}\n`), terminal.write(`${"─".repeat(width)}\n`);
3142
3212
  const sessionPercent = elapsed / (elapsed + remaining) * 100;
3143
3213
  if (terminal.write(`Session: ${sessionPercent.toFixed(1)}% (${Math.floor(elapsed / 60)}h ${Math.floor(elapsed % 60)}m)\n`), config.tokenLimit != null && config.tokenLimit > 0) {
3144
- const tokenPercent = totalTokens / config.tokenLimit * 100, status = tokenPercent > 100 ? import_picocolors$7.default.red("OVER") : tokenPercent > 80 ? import_picocolors$7.default.yellow("WARN") : import_picocolors$7.default.green("OK");
3214
+ const tokenPercent = totalTokens / config.tokenLimit * 100, status = tokenPercent > 100 ? import_picocolors$4.default.red("OVER") : tokenPercent > 80 ? import_picocolors$4.default.yellow("WARN") : import_picocolors$4.default.green("OK");
3145
3215
  terminal.write(`Tokens: ${formatNumber(totalTokens)}/${formatNumber(config.tokenLimit)} ${status}\n`);
3146
3216
  } else terminal.write(`Tokens: ${formatNumber(totalTokens)}\n`);
3147
3217
  terminal.write(`Cost: ${formatCurrency(block.costUSD)}\n`);
3148
3218
  const burnRate = calculateBurnRate(block);
3149
3219
  if (burnRate != null) terminal.write(`Rate: ${formatNumber(burnRate.tokensPerMinute)}/min\n`);
3150
- terminal.write(`${"─".repeat(width)}\n`), terminal.write(import_picocolors$7.default.gray(`Refresh: ${config.refreshInterval / 1e3}s | Ctrl+C: stop\n`));
3220
+ terminal.write(`${"─".repeat(width)}\n`), terminal.write(import_picocolors$4.default.gray(`Refresh: ${config.refreshInterval / 1e3}s | Ctrl+C: stop\n`));
3151
3221
  }
3152
- var import_picocolors$6 = /* @__PURE__ */ __toESM(require_picocolors(), 1), import_usingCtx$1 = /* @__PURE__ */ __toESM(require_usingCtx(), 1);
3222
+ var import_picocolors$3 = /* @__PURE__ */ __toESM(require_picocolors(), 1), import_usingCtx$1 = /* @__PURE__ */ __toESM(require_usingCtx(), 1);
3153
3223
  async function startLiveMonitoring(config) {
3154
3224
  try {
3155
3225
  var _usingCtx = (0, import_usingCtx$1.default)();
@@ -3194,15 +3264,15 @@ async function startLiveMonitoring(config) {
3194
3264
  const error = monitoringResult.error;
3195
3265
  if ((error instanceof DOMException || error instanceof Error) && error.name === "AbortError") return;
3196
3266
  const errorMessage = error instanceof Error ? error.message : String(error);
3197
- terminal.startBuffering(), terminal.clearScreen(), terminal.write(import_picocolors$6.default.red(`Error: ${errorMessage}\n`)), terminal.flush(), logger.error(`Live monitoring error: ${errorMessage}`), await delayWithAbort(config.refreshInterval, abortController.signal).catch(() => {});
3267
+ terminal.startBuffering(), terminal.clearScreen(), terminal.write(import_picocolors$3.default.red(`Error: ${errorMessage}\n`)), terminal.flush(), logger.error(`Live monitoring error: ${errorMessage}`), await delayWithAbort(config.refreshInterval, abortController.signal).catch(() => {});
3198
3268
  }
3199
- } catch (_) {
3200
- _usingCtx.e = _;
3269
+ } catch (_$1) {
3270
+ _usingCtx.e = _$1;
3201
3271
  } finally {
3202
3272
  _usingCtx.d();
3203
3273
  }
3204
3274
  }
3205
- var import_picocolors$5 = /* @__PURE__ */ __toESM(require_picocolors(), 1);
3275
+ var import_picocolors$2 = /* @__PURE__ */ __toESM(require_picocolors(), 1);
3206
3276
  function formatBlockTime(block, compact = false, locale) {
3207
3277
  const start = compact ? block.startTime.toLocaleString(locale, {
3208
3278
  month: "2-digit",
@@ -3371,13 +3441,13 @@ const blocksCommand = define({
3371
3441
  const burnRate = calculateBurnRate(block), projection = projectBlockUsage(block);
3372
3442
  logger.box("Current Session Block Status");
3373
3443
  const now = /* @__PURE__ */ new Date(), elapsed = Math.round((now.getTime() - block.startTime.getTime()) / (1e3 * 60)), remaining = Math.round((block.endTime.getTime() - now.getTime()) / (1e3 * 60));
3374
- if (log(`Block Started: ${import_picocolors$5.default.cyan(block.startTime.toLocaleString())} (${import_picocolors$5.default.yellow(`${Math.floor(elapsed / 60)}h ${elapsed % 60}m`)} ago)`), log(`Time Remaining: ${import_picocolors$5.default.green(`${Math.floor(remaining / 60)}h ${remaining % 60}m`)}\n`), log(import_picocolors$5.default.bold("Current Usage:")), log(` Input Tokens: ${formatNumber(block.tokenCounts.inputTokens)}`), log(` Output Tokens: ${formatNumber(block.tokenCounts.outputTokens)}`), log(` Total Cost: ${formatCurrency(block.costUSD)}\n`), burnRate != null) log(import_picocolors$5.default.bold("Burn Rate:")), log(` Tokens/minute: ${formatNumber(burnRate.tokensPerMinute)}`), log(` Cost/hour: ${formatCurrency(burnRate.costPerHour)}\n`);
3444
+ if (log(`Block Started: ${import_picocolors$2.default.cyan(block.startTime.toLocaleString())} (${import_picocolors$2.default.yellow(`${Math.floor(elapsed / 60)}h ${elapsed % 60}m`)} ago)`), log(`Time Remaining: ${import_picocolors$2.default.green(`${Math.floor(remaining / 60)}h ${remaining % 60}m`)}\n`), log(import_picocolors$2.default.bold("Current Usage:")), log(` Input Tokens: ${formatNumber(block.tokenCounts.inputTokens)}`), log(` Output Tokens: ${formatNumber(block.tokenCounts.outputTokens)}`), log(` Total Cost: ${formatCurrency(block.costUSD)}\n`), burnRate != null) log(import_picocolors$2.default.bold("Burn Rate:")), log(` Tokens/minute: ${formatNumber(burnRate.tokensPerMinute)}`), log(` Cost/hour: ${formatCurrency(burnRate.costPerHour)}\n`);
3375
3445
  if (projection != null) {
3376
- if (log(import_picocolors$5.default.bold("Projected Usage (if current rate continues):")), log(` Total Tokens: ${formatNumber(projection.totalTokens)}`), log(` Total Cost: ${formatCurrency(projection.totalCost)}\n`), ctx.values.tokenLimit != null) {
3446
+ if (log(import_picocolors$2.default.bold("Projected Usage (if current rate continues):")), log(` Total Tokens: ${formatNumber(projection.totalTokens)}`), log(` Total Cost: ${formatCurrency(projection.totalCost)}\n`), ctx.values.tokenLimit != null) {
3377
3447
  const limit = parseTokenLimit(ctx.values.tokenLimit, maxTokensFromAll);
3378
3448
  if (limit != null && limit > 0) {
3379
- const currentTokens = getTotalTokens(block.tokenCounts), remainingTokens = Math.max(0, limit - currentTokens), percentUsed = projection.totalTokens / limit * 100, status = percentUsed > 100 ? import_picocolors$5.default.red("EXCEEDS LIMIT") : percentUsed > BLOCKS_WARNING_THRESHOLD * 100 ? import_picocolors$5.default.yellow("WARNING") : import_picocolors$5.default.green("OK");
3380
- log(import_picocolors$5.default.bold("Token Limit Status:")), log(` Limit: ${formatNumber(limit)} tokens`), log(` Current Usage: ${formatNumber(currentTokens)} (${(currentTokens / limit * 100).toFixed(1)}%)`), log(` Remaining: ${formatNumber(remainingTokens)} tokens`), log(` Projected Usage: ${percentUsed.toFixed(1)}% ${status}`);
3449
+ const currentTokens = getTotalTokens(block.tokenCounts), remainingTokens = Math.max(0, limit - currentTokens), percentUsed = projection.totalTokens / limit * 100, status = percentUsed > 100 ? import_picocolors$2.default.red("EXCEEDS LIMIT") : percentUsed > BLOCKS_WARNING_THRESHOLD * 100 ? import_picocolors$2.default.yellow("WARNING") : import_picocolors$2.default.green("OK");
3450
+ log(import_picocolors$2.default.bold("Token Limit Status:")), log(` Limit: ${formatNumber(limit)} tokens`), log(` Current Usage: ${formatNumber(currentTokens)} (${(currentTokens / limit * 100).toFixed(1)}%)`), log(` Remaining: ${formatNumber(remainingTokens)} tokens`), log(` Projected Usage: ${percentUsed.toFixed(1)}% ${status}`);
3381
3451
  }
3382
3452
  }
3383
3453
  }
@@ -3403,15 +3473,15 @@ const blocksCommand = define({
3403
3473
  }), terminalWidth = process$1.stdout.columns || BLOCKS_DEFAULT_TERMINAL_WIDTH, isNarrowTerminal = terminalWidth < BLOCKS_COMPACT_WIDTH_THRESHOLD, useCompactFormat = ctx.values.compact || isNarrowTerminal;
3404
3474
  for (const block of blocks) if (block.isGap ?? false) {
3405
3475
  const gapRow = [
3406
- import_picocolors$5.default.gray(formatBlockTime(block, useCompactFormat, ctx.values.locale)),
3407
- import_picocolors$5.default.gray("(inactive)"),
3408
- import_picocolors$5.default.gray("-"),
3409
- import_picocolors$5.default.gray("-")
3476
+ import_picocolors$2.default.gray(formatBlockTime(block, useCompactFormat, ctx.values.locale)),
3477
+ import_picocolors$2.default.gray("(inactive)"),
3478
+ import_picocolors$2.default.gray("-"),
3479
+ import_picocolors$2.default.gray("-")
3410
3480
  ];
3411
- if (actualTokenLimit != null && actualTokenLimit > 0) gapRow.push(import_picocolors$5.default.gray("-"));
3412
- gapRow.push(import_picocolors$5.default.gray("-")), table.push(gapRow);
3481
+ if (actualTokenLimit != null && actualTokenLimit > 0) gapRow.push(import_picocolors$2.default.gray("-"));
3482
+ gapRow.push(import_picocolors$2.default.gray("-")), table.push(gapRow);
3413
3483
  } else {
3414
- const totalTokens = getTotalTokens(block.tokenCounts), status = block.isActive ? import_picocolors$5.default.green("ACTIVE") : "", row = [
3484
+ const totalTokens = getTotalTokens(block.tokenCounts), status = block.isActive ? import_picocolors$2.default.green("ACTIVE") : "", row = [
3415
3485
  formatBlockTime(block, useCompactFormat, ctx.values.locale),
3416
3486
  status,
3417
3487
  formatModels(block.models),
@@ -3419,16 +3489,16 @@ const blocksCommand = define({
3419
3489
  ];
3420
3490
  if (actualTokenLimit != null && actualTokenLimit > 0) {
3421
3491
  const percentage = totalTokens / actualTokenLimit * 100, percentText = `${percentage.toFixed(1)}%`;
3422
- row.push(percentage > 100 ? import_picocolors$5.default.red(percentText) : percentText);
3492
+ row.push(percentage > 100 ? import_picocolors$2.default.red(percentText) : percentText);
3423
3493
  }
3424
3494
  if (row.push(formatCurrency(block.costUSD)), table.push(row), block.isActive) {
3425
3495
  if (actualTokenLimit != null && actualTokenLimit > 0) {
3426
- const currentTokens = getTotalTokens(block.tokenCounts), remainingTokens = Math.max(0, actualTokenLimit - currentTokens), remainingText = remainingTokens > 0 ? formatNumber(remainingTokens) : import_picocolors$5.default.red("0"), remainingPercent = (actualTokenLimit - currentTokens) / actualTokenLimit * 100, remainingPercentText = remainingPercent > 0 ? `${remainingPercent.toFixed(1)}%` : import_picocolors$5.default.red("0.0%"), remainingRow = [
3496
+ const currentTokens = getTotalTokens(block.tokenCounts), remainingTokens = Math.max(0, actualTokenLimit - currentTokens), remainingText = remainingTokens > 0 ? formatNumber(remainingTokens) : import_picocolors$2.default.red("0"), remainingPercent = (actualTokenLimit - currentTokens) / actualTokenLimit * 100, remainingPercentText = remainingPercent > 0 ? `${remainingPercent.toFixed(1)}%` : import_picocolors$2.default.red("0.0%"), remainingRow = [
3427
3497
  {
3428
- content: import_picocolors$5.default.gray(`(assuming ${formatNumber(actualTokenLimit)} token limit)`),
3498
+ content: import_picocolors$2.default.gray(`(assuming ${formatNumber(actualTokenLimit)} token limit)`),
3429
3499
  hAlign: "right"
3430
3500
  },
3431
- import_picocolors$5.default.blue("REMAINING"),
3501
+ import_picocolors$2.default.blue("REMAINING"),
3432
3502
  "",
3433
3503
  remainingText,
3434
3504
  remainingPercentText,
@@ -3438,12 +3508,12 @@ const blocksCommand = define({
3438
3508
  }
3439
3509
  const projection = projectBlockUsage(block);
3440
3510
  if (projection != null) {
3441
- const projectedTokens = formatNumber(projection.totalTokens), projectedText = actualTokenLimit != null && actualTokenLimit > 0 && projection.totalTokens > actualTokenLimit ? import_picocolors$5.default.red(projectedTokens) : projectedTokens, projectedRow = [
3511
+ const projectedTokens = formatNumber(projection.totalTokens), projectedText = actualTokenLimit != null && actualTokenLimit > 0 && projection.totalTokens > actualTokenLimit ? import_picocolors$2.default.red(projectedTokens) : projectedTokens, projectedRow = [
3442
3512
  {
3443
- content: import_picocolors$5.default.gray("(assuming current burn rate)"),
3513
+ content: import_picocolors$2.default.gray("(assuming current burn rate)"),
3444
3514
  hAlign: "right"
3445
3515
  },
3446
- import_picocolors$5.default.yellow("PROJECTED"),
3516
+ import_picocolors$2.default.yellow("PROJECTED"),
3447
3517
  "",
3448
3518
  projectedText
3449
3519
  ];
@@ -3522,7 +3592,7 @@ function formatProjectName(projectName, aliases) {
3522
3592
  const parsed = parseProjectName(projectName);
3523
3593
  return aliases != null && aliases.has(parsed) ? aliases.get(parsed) : parsed;
3524
3594
  }
3525
- var import_picocolors$4 = /* @__PURE__ */ __toESM(require_picocolors(), 1);
3595
+ var import_picocolors$1 = /* @__PURE__ */ __toESM(require_picocolors(), 1);
3526
3596
  const dailyCommand = define({
3527
3597
  name: "daily",
3528
3598
  description: "Show usage report grouped by date",
@@ -3599,46 +3669,11 @@ const dailyCommand = define({
3599
3669
  } else log(JSON.stringify(jsonOutput, null, 2));
3600
3670
  } else {
3601
3671
  logger.box("Claude Code Token Usage Report - Daily");
3602
- const table = new ResponsiveTable({
3603
- head: [
3604
- "Date",
3605
- "Models",
3606
- "Input",
3607
- "Output",
3608
- "Cache Create",
3609
- "Cache Read",
3610
- "Total Tokens",
3611
- "Cost (USD)"
3612
- ],
3613
- style: { head: ["cyan"] },
3614
- colAligns: [
3615
- "left",
3616
- "left",
3617
- "right",
3618
- "right",
3619
- "right",
3620
- "right",
3621
- "right",
3622
- "right"
3623
- ],
3672
+ const tableConfig = {
3673
+ firstColumnName: "Date",
3624
3674
  dateFormatter: (dateStr) => formatDateCompact(dateStr, mergedOptions.timezone, mergedOptions.locale ?? void 0),
3625
- compactHead: [
3626
- "Date",
3627
- "Models",
3628
- "Input",
3629
- "Output",
3630
- "Cost (USD)"
3631
- ],
3632
- compactColAligns: [
3633
- "left",
3634
- "left",
3635
- "right",
3636
- "right",
3637
- "right"
3638
- ],
3639
- compactThreshold: 100,
3640
3675
  forceCompact: ctx.values.compact
3641
- });
3676
+ }, table = createUsageReportTable(tableConfig);
3642
3677
  if (Boolean(mergedOptions.instances) && dailyData.some((d) => d.project != null)) {
3643
3678
  const projectGroups = groupDataByProject(dailyData);
3644
3679
  let isFirstProject = true;
@@ -3654,7 +3689,7 @@ const dailyCommand = define({
3654
3689
  ""
3655
3690
  ]);
3656
3691
  table.push([
3657
- import_picocolors$4.default.cyan(`Project: ${formatProjectName(projectName, projectAliases)}`),
3692
+ import_picocolors$1.default.cyan(`Project: ${formatProjectName(projectName, projectAliases)}`),
3658
3693
  "",
3659
3694
  "",
3660
3695
  "",
@@ -3663,47 +3698,39 @@ const dailyCommand = define({
3663
3698
  "",
3664
3699
  ""
3665
3700
  ]);
3666
- for (const data of projectData) if (table.push([
3667
- data.date,
3668
- formatModelsDisplayMultiline(data.modelsUsed),
3669
- formatNumber(data.inputTokens),
3670
- formatNumber(data.outputTokens),
3671
- formatNumber(data.cacheCreationTokens),
3672
- formatNumber(data.cacheReadTokens),
3673
- formatNumber(getTotalTokens(data)),
3674
- formatCurrency(data.totalCost)
3675
- ]), mergedOptions.breakdown) pushBreakdownRows(table, data.modelBreakdowns);
3701
+ for (const data of projectData) {
3702
+ const row = formatUsageDataRow(data.date, {
3703
+ inputTokens: data.inputTokens,
3704
+ outputTokens: data.outputTokens,
3705
+ cacheCreationTokens: data.cacheCreationTokens,
3706
+ cacheReadTokens: data.cacheReadTokens,
3707
+ totalCost: data.totalCost,
3708
+ modelsUsed: data.modelsUsed
3709
+ });
3710
+ if (table.push(row), mergedOptions.breakdown) pushBreakdownRows(table, data.modelBreakdowns);
3711
+ }
3676
3712
  isFirstProject = false;
3677
3713
  }
3678
- } else for (const data of dailyData) if (table.push([
3679
- data.date,
3680
- formatModelsDisplayMultiline(data.modelsUsed),
3681
- formatNumber(data.inputTokens),
3682
- formatNumber(data.outputTokens),
3683
- formatNumber(data.cacheCreationTokens),
3684
- formatNumber(data.cacheReadTokens),
3685
- formatNumber(getTotalTokens(data)),
3686
- formatCurrency(data.totalCost)
3687
- ]), mergedOptions.breakdown) pushBreakdownRows(table, data.modelBreakdowns);
3688
- if (table.push([
3689
- "",
3690
- "",
3691
- "",
3692
- "",
3693
- "",
3694
- "",
3695
- "",
3696
- ""
3697
- ]), table.push([
3698
- import_picocolors$4.default.yellow("Total"),
3699
- "",
3700
- import_picocolors$4.default.yellow(formatNumber(totals.inputTokens)),
3701
- import_picocolors$4.default.yellow(formatNumber(totals.outputTokens)),
3702
- import_picocolors$4.default.yellow(formatNumber(totals.cacheCreationTokens)),
3703
- import_picocolors$4.default.yellow(formatNumber(totals.cacheReadTokens)),
3704
- import_picocolors$4.default.yellow(formatNumber(getTotalTokens(totals))),
3705
- import_picocolors$4.default.yellow(formatCurrency(totals.totalCost))
3706
- ]), log(table.toString()), table.isCompactMode()) logger.info("\nRunning in Compact Mode"), logger.info("Expand terminal width to see cache metrics and total tokens");
3714
+ } else for (const data of dailyData) {
3715
+ const row = formatUsageDataRow(data.date, {
3716
+ inputTokens: data.inputTokens,
3717
+ outputTokens: data.outputTokens,
3718
+ cacheCreationTokens: data.cacheCreationTokens,
3719
+ cacheReadTokens: data.cacheReadTokens,
3720
+ totalCost: data.totalCost,
3721
+ modelsUsed: data.modelsUsed
3722
+ });
3723
+ if (table.push(row), mergedOptions.breakdown) pushBreakdownRows(table, data.modelBreakdowns);
3724
+ }
3725
+ addEmptySeparatorRow(table, 8);
3726
+ const totalsRow = formatTotalsRow({
3727
+ inputTokens: totals.inputTokens,
3728
+ outputTokens: totals.outputTokens,
3729
+ cacheCreationTokens: totals.cacheCreationTokens,
3730
+ cacheReadTokens: totals.cacheReadTokens,
3731
+ totalCost: totals.totalCost
3732
+ });
3733
+ if (table.push(totalsRow), log(table.toString()), table.isCompactMode()) logger.info("\nRunning in Compact Mode"), logger.info("Expand terminal width to see cache metrics and total tokens");
3707
3734
  }
3708
3735
  }
3709
3736
  });
@@ -4089,9 +4116,7 @@ const mcpCommand = define({
4089
4116
  }), logger.info(`MCP server is running on http://localhost:${port}`);
4090
4117
  }
4091
4118
  }
4092
- });
4093
- var import_picocolors$3 = /* @__PURE__ */ __toESM(require_picocolors(), 1);
4094
- const monthlyCommand = define({
4119
+ }), monthlyCommand = define({
4095
4120
  name: "monthly",
4096
4121
  description: "Show usage report grouped by month",
4097
4122
  ...sharedCommandConfig,
@@ -4143,75 +4168,31 @@ const monthlyCommand = define({
4143
4168
  } else log(JSON.stringify(jsonOutput, null, 2));
4144
4169
  } else {
4145
4170
  logger.box("Claude Code Token Usage Report - Monthly");
4146
- const table = new ResponsiveTable({
4147
- head: [
4148
- "Month",
4149
- "Models",
4150
- "Input",
4151
- "Output",
4152
- "Cache Create",
4153
- "Cache Read",
4154
- "Total Tokens",
4155
- "Cost (USD)"
4156
- ],
4157
- style: { head: ["cyan"] },
4158
- colAligns: [
4159
- "left",
4160
- "left",
4161
- "right",
4162
- "right",
4163
- "right",
4164
- "right",
4165
- "right",
4166
- "right"
4167
- ],
4168
- dateFormatter: (dateStr) => formatDateCompact(dateStr, mergedOptions.timezone, mergedOptions.locale ?? "en-CA"),
4169
- compactHead: [
4170
- "Month",
4171
- "Models",
4172
- "Input",
4173
- "Output",
4174
- "Cost (USD)"
4175
- ],
4176
- compactColAligns: [
4177
- "left",
4178
- "left",
4179
- "right",
4180
- "right",
4181
- "right"
4182
- ],
4183
- compactThreshold: 100,
4171
+ const tableConfig = {
4172
+ firstColumnName: "Month",
4173
+ dateFormatter: (dateStr) => formatDateCompact(dateStr, mergedOptions.timezone, mergedOptions.locale ?? DEFAULT_LOCALE),
4184
4174
  forceCompact: ctx.values.compact
4175
+ }, table = createUsageReportTable(tableConfig);
4176
+ for (const data of monthlyData) {
4177
+ const row = formatUsageDataRow(data.month, {
4178
+ inputTokens: data.inputTokens,
4179
+ outputTokens: data.outputTokens,
4180
+ cacheCreationTokens: data.cacheCreationTokens,
4181
+ cacheReadTokens: data.cacheReadTokens,
4182
+ totalCost: data.totalCost,
4183
+ modelsUsed: data.modelsUsed
4184
+ });
4185
+ if (table.push(row), mergedOptions.breakdown) pushBreakdownRows(table, data.modelBreakdowns);
4186
+ }
4187
+ addEmptySeparatorRow(table, 8);
4188
+ const totalsRow = formatTotalsRow({
4189
+ inputTokens: totals.inputTokens,
4190
+ outputTokens: totals.outputTokens,
4191
+ cacheCreationTokens: totals.cacheCreationTokens,
4192
+ cacheReadTokens: totals.cacheReadTokens,
4193
+ totalCost: totals.totalCost
4185
4194
  });
4186
- for (const data of monthlyData) if (table.push([
4187
- data.month,
4188
- formatModelsDisplayMultiline(data.modelsUsed),
4189
- formatNumber(data.inputTokens),
4190
- formatNumber(data.outputTokens),
4191
- formatNumber(data.cacheCreationTokens),
4192
- formatNumber(data.cacheReadTokens),
4193
- formatNumber(getTotalTokens(data)),
4194
- formatCurrency(data.totalCost)
4195
- ]), mergedOptions.breakdown) pushBreakdownRows(table, data.modelBreakdowns);
4196
- if (table.push([
4197
- "",
4198
- "",
4199
- "",
4200
- "",
4201
- "",
4202
- "",
4203
- "",
4204
- ""
4205
- ]), table.push([
4206
- import_picocolors$3.default.yellow("Total"),
4207
- "",
4208
- import_picocolors$3.default.yellow(formatNumber(totals.inputTokens)),
4209
- import_picocolors$3.default.yellow(formatNumber(totals.outputTokens)),
4210
- import_picocolors$3.default.yellow(formatNumber(totals.cacheCreationTokens)),
4211
- import_picocolors$3.default.yellow(formatNumber(totals.cacheReadTokens)),
4212
- import_picocolors$3.default.yellow(formatNumber(getTotalTokens(totals))),
4213
- import_picocolors$3.default.yellow(formatCurrency(totals.totalCost))
4214
- ]), log(table.toString()), table.isCompactMode()) logger.info("\nRunning in Compact Mode"), logger.info("Expand terminal width to see cache metrics and total tokens");
4195
+ if (table.push(totalsRow), log(table.toString()), table.isCompactMode()) logger.info("\nRunning in Compact Mode"), logger.info("Expand terminal width to see cache metrics and total tokens");
4215
4196
  }
4216
4197
  }
4217
4198
  });
@@ -4289,13 +4270,12 @@ function calculateSessionTotalTokens(entries) {
4289
4270
  return sum + usage.input_tokens + usage.output_tokens + (usage.cache_creation_input_tokens ?? 0) + (usage.cache_read_input_tokens ?? 0);
4290
4271
  }, 0);
4291
4272
  }
4292
- var import_picocolors$2 = /* @__PURE__ */ __toESM(require_picocolors(), 1);
4293
- const sessionCommand = define({
4273
+ const { order: _,...sharedArgs$1 } = sharedCommandConfig.args, sessionCommand = define({
4294
4274
  name: "session",
4295
4275
  description: "Show usage report grouped by conversation session",
4296
4276
  ...sharedCommandConfig,
4297
4277
  args: {
4298
- ...sharedCommandConfig.args,
4278
+ ...sharedArgs$1,
4299
4279
  id: {
4300
4280
  type: "string",
4301
4281
  short: "i",
@@ -4312,13 +4292,12 @@ const sessionCommand = define({
4312
4292
  offline: mergedOptions.offline,
4313
4293
  jq: mergedOptions.jq,
4314
4294
  timezone: mergedOptions.timezone,
4315
- locale: mergedOptions.locale ?? "en-CA"
4295
+ locale: mergedOptions.locale ?? DEFAULT_LOCALE
4316
4296
  } }, useJson);
4317
4297
  const sessionData = await loadSessionData({
4318
4298
  since: ctx.values.since,
4319
4299
  until: ctx.values.until,
4320
4300
  mode: ctx.values.mode,
4321
- order: ctx.values.order,
4322
4301
  offline: ctx.values.offline,
4323
4302
  timezone: ctx.values.timezone,
4324
4303
  locale: ctx.values.locale
@@ -4357,86 +4336,35 @@ const sessionCommand = define({
4357
4336
  } else log(JSON.stringify(jsonOutput, null, 2));
4358
4337
  } else {
4359
4338
  logger.box("Claude Code Token Usage Report - By Session");
4360
- const table = new ResponsiveTable({
4361
- head: [
4362
- "Session",
4363
- "Models",
4364
- "Input",
4365
- "Output",
4366
- "Cache Create",
4367
- "Cache Read",
4368
- "Total Tokens",
4369
- "Cost (USD)",
4370
- "Last Activity"
4371
- ],
4372
- style: { head: ["cyan"] },
4373
- colAligns: [
4374
- "left",
4375
- "left",
4376
- "right",
4377
- "right",
4378
- "right",
4379
- "right",
4380
- "right",
4381
- "right",
4382
- "left"
4383
- ],
4339
+ const tableConfig = {
4340
+ firstColumnName: "Session",
4341
+ includeLastActivity: true,
4384
4342
  dateFormatter: (dateStr) => formatDateCompact(dateStr, ctx.values.timezone, ctx.values.locale),
4385
- compactHead: [
4386
- "Session",
4387
- "Models",
4388
- "Input",
4389
- "Output",
4390
- "Cost (USD)",
4391
- "Last Activity"
4392
- ],
4393
- compactColAligns: [
4394
- "left",
4395
- "left",
4396
- "right",
4397
- "right",
4398
- "right",
4399
- "left"
4400
- ],
4401
- compactThreshold: 100,
4402
4343
  forceCompact: ctx.values.compact
4403
- });
4344
+ }, table = createUsageReportTable(tableConfig);
4404
4345
  let maxSessionLength = 0;
4405
4346
  for (const data of sessionData) {
4406
4347
  const sessionDisplay = data.sessionId.split("-").slice(-2).join("-");
4407
- if (maxSessionLength = Math.max(maxSessionLength, sessionDisplay.length), table.push([
4408
- sessionDisplay,
4409
- formatModelsDisplayMultiline(data.modelsUsed),
4410
- formatNumber(data.inputTokens),
4411
- formatNumber(data.outputTokens),
4412
- formatNumber(data.cacheCreationTokens),
4413
- formatNumber(data.cacheReadTokens),
4414
- formatNumber(getTotalTokens(data)),
4415
- formatCurrency(data.totalCost),
4416
- data.lastActivity
4417
- ]), ctx.values.breakdown) pushBreakdownRows(table, data.modelBreakdowns, 1, 1);
4348
+ maxSessionLength = Math.max(maxSessionLength, sessionDisplay.length);
4349
+ const row = formatUsageDataRow(sessionDisplay, {
4350
+ inputTokens: data.inputTokens,
4351
+ outputTokens: data.outputTokens,
4352
+ cacheCreationTokens: data.cacheCreationTokens,
4353
+ cacheReadTokens: data.cacheReadTokens,
4354
+ totalCost: data.totalCost,
4355
+ modelsUsed: data.modelsUsed
4356
+ }, data.lastActivity);
4357
+ if (table.push(row), ctx.values.breakdown) pushBreakdownRows(table, data.modelBreakdowns, 1, 1);
4418
4358
  }
4419
- if (table.push([
4420
- "",
4421
- "",
4422
- "",
4423
- "",
4424
- "",
4425
- "",
4426
- "",
4427
- "",
4428
- ""
4429
- ]), table.push([
4430
- import_picocolors$2.default.yellow("Total"),
4431
- "",
4432
- import_picocolors$2.default.yellow(formatNumber(totals.inputTokens)),
4433
- import_picocolors$2.default.yellow(formatNumber(totals.outputTokens)),
4434
- import_picocolors$2.default.yellow(formatNumber(totals.cacheCreationTokens)),
4435
- import_picocolors$2.default.yellow(formatNumber(totals.cacheReadTokens)),
4436
- import_picocolors$2.default.yellow(formatNumber(getTotalTokens(totals))),
4437
- import_picocolors$2.default.yellow(formatCurrency(totals.totalCost)),
4438
- ""
4439
- ]), log(table.toString()), table.isCompactMode()) logger.info("\nRunning in Compact Mode"), logger.info("Expand terminal width to see cache metrics and total tokens");
4359
+ addEmptySeparatorRow(table, 9);
4360
+ const totalsRow = formatTotalsRow({
4361
+ inputTokens: totals.inputTokens,
4362
+ outputTokens: totals.outputTokens,
4363
+ cacheCreationTokens: totals.cacheCreationTokens,
4364
+ cacheReadTokens: totals.cacheReadTokens,
4365
+ totalCost: totals.totalCost
4366
+ }, true);
4367
+ if (table.push(totalsRow), log(table.toString()), table.isCompactMode()) logger.info("\nRunning in Compact Mode"), logger.info("Expand terminal width to see cache metrics and total tokens");
4440
4368
  }
4441
4369
  }
4442
4370
  });
@@ -5309,7 +5237,7 @@ getStdin.buffer = async () => {
5309
5237
  for await (const chunk of stdin$1) result.push(chunk), length += chunk.length;
5310
5238
  return Buffer.concat(result, length);
5311
5239
  };
5312
- var import_picocolors$1 = /* @__PURE__ */ __toESM(require_picocolors(), 1), import_usingCtx = /* @__PURE__ */ __toESM(require_usingCtx(), 1);
5240
+ var import_picocolors = /* @__PURE__ */ __toESM(require_picocolors(), 1), import_usingCtx = /* @__PURE__ */ __toESM(require_usingCtx(), 1);
5313
5241
  function formatRemainingTime(remaining) {
5314
5242
  const remainingHours = Math.floor(remaining / 60), remainingMins = remaining % 60;
5315
5243
  return remainingHours > 0 ? `${remainingHours}h ${remainingMins}m left` : `${remainingMins}m left`;
@@ -5428,8 +5356,8 @@ const visualBurnRateChoices = [
5428
5356
  pid: currentPid
5429
5357
  };
5430
5358
  }
5431
- } catch (_) {
5432
- _usingCtx.e = _;
5359
+ } catch (_$1) {
5360
+ _usingCtx.e = _$1;
5433
5361
  } finally {
5434
5362
  _usingCtx.d();
5435
5363
  }
@@ -5462,7 +5390,7 @@ const visualBurnRateChoices = [
5462
5390
  const cost = await getCcusageCost();
5463
5391
  return { sessionCost: cost };
5464
5392
  }
5465
- return {};
5393
+ return unreachable(costSource), {};
5466
5394
  })(), today = /* @__PURE__ */ new Date(), todayStr = today.toISOString().split("T")[0]?.replace(/-/g, "") ?? "", todayCost = await pipe(try_({
5467
5395
  try: async () => loadDailyUsageData({
5468
5396
  since: todayStr,
@@ -5497,17 +5425,17 @@ const visualBurnRateChoices = [
5497
5425
  normal: {
5498
5426
  emoji: "🟢",
5499
5427
  textValue: "Normal",
5500
- coloredString: import_picocolors$1.default.green
5428
+ coloredString: import_picocolors.default.green
5501
5429
  },
5502
5430
  moderate: {
5503
5431
  emoji: "⚠️",
5504
5432
  textValue: "Moderate",
5505
- coloredString: import_picocolors$1.default.yellow
5433
+ coloredString: import_picocolors.default.yellow
5506
5434
  },
5507
5435
  high: {
5508
5436
  emoji: "🚨",
5509
5437
  textValue: "High",
5510
- coloredString: import_picocolors$1.default.red
5438
+ coloredString: import_picocolors.default.red
5511
5439
  }
5512
5440
  }, { emoji, textValue, coloredString } = burnStatusMappings[burnStatus], burnRateOutputSegments = [coloredString(costPerHourStr)];
5513
5441
  if (renderEmojiStatus) burnRateOutputSegments.push(emoji);
@@ -5531,7 +5459,7 @@ const visualBurnRateChoices = [
5531
5459
  catch: (error) => error
5532
5460
  }), inspectError((error) => logger.debug(`Failed to calculate context tokens: ${error instanceof Error ? error.message : String(error)}`)), map((contextResult) => {
5533
5461
  if (contextResult == null) return void 0;
5534
- const color = contextResult.percentage < ctx.values.contextLowThreshold ? import_picocolors$1.default.green : contextResult.percentage < ctx.values.contextMediumThreshold ? import_picocolors$1.default.yellow : import_picocolors$1.default.red, coloredPercentage = color(`${contextResult.percentage}%`), tokenDisplay = contextResult.inputTokens.toLocaleString();
5462
+ const color = contextResult.percentage < ctx.values.contextLowThreshold ? import_picocolors.default.green : contextResult.percentage < ctx.values.contextMediumThreshold ? import_picocolors.default.yellow : import_picocolors.default.red, coloredPercentage = color(`${contextResult.percentage}%`), tokenDisplay = contextResult.inputTokens.toLocaleString();
5535
5463
  return `${tokenDisplay} (${coloredPercentage})`;
5536
5464
  }), unwrap(void 0)), modelName = hookData.model.display_name, sessionDisplay = (() => {
5537
5465
  if (ccCost != null || ccusageCost != null) {
@@ -5559,8 +5487,8 @@ const visualBurnRateChoices = [
5559
5487
  pid: void 0
5560
5488
  };
5561
5489
  return;
5562
- } catch (_) {
5563
- _usingCtx3.e = _;
5490
+ } catch (_$1) {
5491
+ _usingCtx3.e = _$1;
5564
5492
  } finally {
5565
5493
  _usingCtx3.d();
5566
5494
  }
@@ -5571,15 +5499,13 @@ const visualBurnRateChoices = [
5571
5499
  if (logger.error("Error in statusline command:", mainProcessingResult.error), !mergedOptions.cache) return;
5572
5500
  const semaphore = _usingCtx4.u(getSemaphore(sessionId));
5573
5501
  if (semaphore.data != null) semaphore.data.isUpdating = false, semaphore.data.pid = void 0;
5574
- } catch (_) {
5575
- _usingCtx4.e = _;
5502
+ } catch (_$1) {
5503
+ _usingCtx4.e = _$1;
5576
5504
  } finally {
5577
5505
  _usingCtx4.d();
5578
5506
  }
5579
5507
  }
5580
- });
5581
- var import_picocolors = /* @__PURE__ */ __toESM(require_picocolors(), 1);
5582
- const weeklyCommand = define({
5508
+ }), weeklyCommand = define({
5583
5509
  name: "weekly",
5584
5510
  description: "Show usage report grouped by week",
5585
5511
  args: {
@@ -5641,75 +5567,31 @@ const weeklyCommand = define({
5641
5567
  } else log(JSON.stringify(jsonOutput, null, 2));
5642
5568
  } else {
5643
5569
  logger.box("Claude Code Token Usage Report - Weekly");
5644
- const table = new ResponsiveTable({
5645
- head: [
5646
- "Week",
5647
- "Models",
5648
- "Input",
5649
- "Output",
5650
- "Cache Create",
5651
- "Cache Read",
5652
- "Total Tokens",
5653
- "Cost (USD)"
5654
- ],
5655
- style: { head: ["cyan"] },
5656
- colAligns: [
5657
- "left",
5658
- "left",
5659
- "right",
5660
- "right",
5661
- "right",
5662
- "right",
5663
- "right",
5664
- "right"
5665
- ],
5570
+ const tableConfig = {
5571
+ firstColumnName: "Week",
5666
5572
  dateFormatter: (dateStr) => formatDateCompact(dateStr, mergedOptions.timezone, mergedOptions.locale ?? void 0),
5667
- compactHead: [
5668
- "Week",
5669
- "Models",
5670
- "Input",
5671
- "Output",
5672
- "Cost (USD)"
5673
- ],
5674
- compactColAligns: [
5675
- "left",
5676
- "left",
5677
- "right",
5678
- "right",
5679
- "right"
5680
- ],
5681
- compactThreshold: 100,
5682
5573
  forceCompact: ctx.values.compact
5574
+ }, table = createUsageReportTable(tableConfig);
5575
+ for (const data of weeklyData) {
5576
+ const row = formatUsageDataRow(data.week, {
5577
+ inputTokens: data.inputTokens,
5578
+ outputTokens: data.outputTokens,
5579
+ cacheCreationTokens: data.cacheCreationTokens,
5580
+ cacheReadTokens: data.cacheReadTokens,
5581
+ totalCost: data.totalCost,
5582
+ modelsUsed: data.modelsUsed
5583
+ });
5584
+ if (table.push(row), mergedOptions.breakdown) pushBreakdownRows(table, data.modelBreakdowns);
5585
+ }
5586
+ addEmptySeparatorRow(table, 8);
5587
+ const totalsRow = formatTotalsRow({
5588
+ inputTokens: totals.inputTokens,
5589
+ outputTokens: totals.outputTokens,
5590
+ cacheCreationTokens: totals.cacheCreationTokens,
5591
+ cacheReadTokens: totals.cacheReadTokens,
5592
+ totalCost: totals.totalCost
5683
5593
  });
5684
- for (const data of weeklyData) if (table.push([
5685
- data.week,
5686
- formatModelsDisplayMultiline(data.modelsUsed),
5687
- formatNumber(data.inputTokens),
5688
- formatNumber(data.outputTokens),
5689
- formatNumber(data.cacheCreationTokens),
5690
- formatNumber(data.cacheReadTokens),
5691
- formatNumber(getTotalTokens(data)),
5692
- formatCurrency(data.totalCost)
5693
- ]), mergedOptions.breakdown) pushBreakdownRows(table, data.modelBreakdowns);
5694
- if (table.push([
5695
- "",
5696
- "",
5697
- "",
5698
- "",
5699
- "",
5700
- "",
5701
- "",
5702
- ""
5703
- ]), table.push([
5704
- import_picocolors.default.yellow("Total"),
5705
- "",
5706
- import_picocolors.default.yellow(formatNumber(totals.inputTokens)),
5707
- import_picocolors.default.yellow(formatNumber(totals.outputTokens)),
5708
- import_picocolors.default.yellow(formatNumber(totals.cacheCreationTokens)),
5709
- import_picocolors.default.yellow(formatNumber(totals.cacheReadTokens)),
5710
- import_picocolors.default.yellow(formatNumber(getTotalTokens(totals))),
5711
- import_picocolors.default.yellow(formatCurrency(totals.totalCost))
5712
- ]), log(table.toString()), table.isCompactMode()) logger.info("\nRunning in Compact Mode"), logger.info("Expand terminal width to see cache metrics and total tokens");
5594
+ if (table.push(totalsRow), log(table.toString()), table.isCompactMode()) logger.info("\nRunning in Compact Mode"), logger.info("Expand terminal width to see cache metrics and total tokens");
5713
5595
  }
5714
5596
  }
5715
5597
  }), subCommandUnion = [