tokely 0.5.1 → 0.5.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/README.md CHANGED
@@ -24,17 +24,19 @@ tokely
24
24
  ## Usage
25
25
 
26
26
  ```bash
27
- tokely [--all] [--claude] [--codex] [--cursor] [--gemini] [--opencode] [--pi] [--dark] [--format png|svg|json] [--output ./heatmap-last-year.png]
27
+ tokely [--all] [--today] [--claude] [--codex] [--cursor] [--gemini] [--opencode] [--pi] [--dark] [--format png|svg|json] [--output ./heatmap-last-year.png]
28
28
  ```
29
29
 
30
30
  By default, the CLI:
31
31
 
32
32
  - scans all supported providers
33
+ - renders the top 4 providers with available data (priority: Claude Code → Codex → Cursor → Open Code)
33
34
  - writes `./heatmap-last-year.png`
34
35
  - infers the date window as the rolling last year ending today
35
36
 
36
37
  ## Options
37
38
 
39
+ - `--today`: show today's usage stats in terminal
38
40
  - `--claude`: include only Claude Code data
39
41
  - `--codex`: include only Codex data
40
42
  - `--cursor`: include only Cursor data
@@ -128,8 +130,9 @@ When Claude Code falls back to `history.jsonl`, those days are rendered as activ
128
130
 
129
131
  ## Exit behavior
130
132
 
131
- - If no provider flags are passed, `tokely` renders every provider with available data.
132
- - If `--all` is passed, `tokely` loads all providers and renders one combined graph with merged totals, streaks, and model rankings.
133
+ - By default, renders the top 4 providers with available data.
134
+ - Priority order: Claude Code Codex Cursor Open Code Amp Gemini CLI Pi Coding Agent.
135
+ - Use `--all` to merge all providers, or specify providers explicitly.
133
136
  - Pi Coding Agent usage is derived from assistant messages in Pi session logs, grouped by the model that handled each turn.
134
137
  - If provider flags are passed and a requested provider has no data, the command exits with an error.
135
138
  - If no provider has data, the command exits with an error.
package/dist/cli.js CHANGED
@@ -8307,10 +8307,11 @@ var HELP_TEXT = `tokely
8307
8307
  Generate rolling 1-year usage heatmap image(s) (today is the latest day).
8308
8308
 
8309
8309
  Usage:
8310
- tokely [--all] [--amp] [--claude] [--codex] [--cursor] [--gemini] [--opencode] [--pi] [--dark] [--format png|svg|json] [--output ./heatmap-last-year.png]
8310
+ tokely [--all] [--today] [--amp] [--claude] [--codex] [--cursor] [--gemini] [--opencode] [--pi] [--dark] [--format png|svg|json] [--output ./heatmap-last-year.png]
8311
8311
 
8312
8312
  Options:
8313
8313
  --all Render one merged graph for all providers
8314
+ --today Show today's usage stats in terminal
8314
8315
  --amp Render Amp graph
8315
8316
  --claude Render Claude Code graph
8316
8317
  --codex Render Codex graph
@@ -8335,6 +8336,7 @@ function validateArgs(values) {
8335
8336
  help: ow.boolean,
8336
8337
  dark: ow.boolean,
8337
8338
  all: ow.boolean,
8339
+ today: ow.boolean,
8338
8340
  amp: ow.boolean,
8339
8341
  claude: ow.boolean,
8340
8342
  codex: ow.boolean,
@@ -8487,6 +8489,62 @@ function printRunSummary(outputPath, format, colorMode, startDate, endDate, rend
8487
8489
  `
8488
8490
  );
8489
8491
  }
8492
+ function formatTokens(value) {
8493
+ const units = [
8494
+ { size: 1e12, suffix: "T" },
8495
+ { size: 1e9, suffix: "B" },
8496
+ { size: 1e6, suffix: "M" },
8497
+ { size: 1e3, suffix: "K" }
8498
+ ];
8499
+ for (const unit of units) {
8500
+ if (value >= unit.size) {
8501
+ const scaled = value / unit.size;
8502
+ const precision = scaled >= 100 ? 0 : scaled >= 10 ? 1 : 2;
8503
+ const compact = scaled.toFixed(precision).replace(/\.0+$/, "").replace(/(\.\d*[1-9])0+$/, "$1");
8504
+ return `${compact}${unit.suffix}`;
8505
+ }
8506
+ }
8507
+ return new Intl.NumberFormat("en-US").format(value);
8508
+ }
8509
+ function printTodayStats(rowsByProvider, providers) {
8510
+ const today = formatLocalDate(/* @__PURE__ */ new Date());
8511
+ const rows = [];
8512
+ for (const provider of providers) {
8513
+ const summary = rowsByProvider[provider];
8514
+ if (!summary) {
8515
+ continue;
8516
+ }
8517
+ const todayRow = summary.daily.find(
8518
+ (row) => formatLocalDate(row.date) === today
8519
+ );
8520
+ if (!todayRow || todayRow.total <= 0 && (todayRow.displayValue ?? 0) <= 0) {
8521
+ continue;
8522
+ }
8523
+ const topModel = todayRow.breakdown.length > 0 ? `${todayRow.breakdown[0].name} (${formatTokens(todayRow.breakdown[0].tokens.total)})` : "-";
8524
+ rows.push({
8525
+ provider: providerStatusLabel[provider],
8526
+ input: formatTokens(todayRow.input),
8527
+ output: formatTokens(todayRow.output),
8528
+ total: formatTokens(todayRow.total),
8529
+ topModel
8530
+ });
8531
+ }
8532
+ if (rows.length === 0) {
8533
+ process.stdout.write(`
8534
+ No usage data found for today (${today}).
8535
+ `);
8536
+ return;
8537
+ }
8538
+ const header = "| Provider | Input | Output | Total | Top Model |\n| --- | --- | --- | --- | --- |";
8539
+ const body = rows.map(
8540
+ (row) => `| ${row.provider} | ${row.input} | ${row.output} | ${row.total} | ${row.topModel} |`
8541
+ ).join("\n");
8542
+ process.stdout.write(`
8543
+ ${header}
8544
+ ${body}
8545
+
8546
+ `);
8547
+ }
8490
8548
  async function main() {
8491
8549
  let spinner;
8492
8550
  const parsed = parseArgs({
@@ -8496,6 +8554,7 @@ async function main() {
8496
8554
  help: { type: "boolean", short: "h", default: false },
8497
8555
  dark: { type: "boolean", default: false },
8498
8556
  all: { type: "boolean", default: false },
8557
+ today: { type: "boolean", default: false },
8499
8558
  amp: { type: "boolean", default: false },
8500
8559
  claude: { type: "boolean", default: false },
8501
8560
  codex: { type: "boolean", default: false },
@@ -8533,7 +8592,13 @@ async function main() {
8533
8592
  process.stderr.write(`${warning}
8534
8593
  `);
8535
8594
  }
8536
- printProviderAvailability(availabilityByProvider, inspectedProviders);
8595
+ if (!values.today) {
8596
+ printProviderAvailability(availabilityByProvider, inspectedProviders);
8597
+ }
8598
+ if (values.today) {
8599
+ printTodayStats(rowsByProvider, inspectedProviders);
8600
+ return;
8601
+ }
8537
8602
  const exportProviders = getOutputProviders(
8538
8603
  values,
8539
8604
  availabilityByProvider,