ccusage 14.1.2 → 15.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -15,6 +15,10 @@
15
15
  <img src="https://cdn.jsdelivr.net/gh/ryoppippi/ccusage@main/docs/screenshot.png">
16
16
  </div>
17
17
 
18
+ <div align="center">
19
+ <img src="https://cdn.jsdelivr.net/gh/ryoppippi/ccusage@main/docs/blocks-live.png">
20
+ </div>
21
+
18
22
  > **ccusage(claude-code-usage)**
19
23
 
20
24
  A CLI tool for analyzing Claude Code usage from local JSONL files.
@@ -48,6 +52,7 @@ This tool helps you understand the value you're getting from your subscription b
48
52
  - 📅 **Monthly Report**: View token usage and costs aggregated by month
49
53
  - 💬 **Session Report**: View usage grouped by conversation sessions
50
54
  - ⏰ **5-Hour Blocks Report**: Track usage within Claude's billing windows with active block monitoring
55
+ - 📈 **Live Monitoring**: Real-time dashboard showing active session progress, token burn rate, and cost projections with `blocks --live`
51
56
  - 🤖 **Model Tracking**: See which Claude models you're using (Opus, Sonnet, etc.)
52
57
  - 📊 **Model Breakdown**: View per-model cost breakdown with `--breakdown` flag
53
58
  - 📅 **Date Filtering**: Filter reports by date range using `--since` and `--until`
@@ -284,6 +289,13 @@ ccusage blocks -t 500000
284
289
  # Use the highest previous block as the token limit
285
290
  ccusage blocks -t max
286
291
 
292
+ # Live monitoring dashboard with real-time updates
293
+ ccusage blocks --live # automatically uses highest previous session as token limit (-t max)
294
+ ccusage blocks --live -t 500000 # with explicit token limit (500,000 tokens)
295
+ ccusage blocks --live -t max # explicitly use highest previous session limit
296
+ ccusage blocks --live --refresh-interval 5 # update every 5 seconds (default: 1s)
297
+ ccusage blocks --live -t 1000000 --refresh-interval 2 # 1M token limit, 2s refresh
298
+
287
299
  # Combine options
288
300
  ccusage blocks --recent -t max
289
301
 
@@ -307,11 +319,23 @@ The blocks report helps you understand Claude Code's 5-hour rolling session wind
307
319
  - Helps track if you're approaching token limits within a session
308
320
  - The `-t max` option automatically uses your highest previous block as the limit
309
321
 
322
+ **Live Monitoring Features:**
323
+
324
+ - Real-time dashboard updates every 1 second (configurable 1-60s)
325
+ - Automatic token limit detection from your usage history
326
+ - Session progress bar with time remaining and burn rate
327
+ - Cost projections based on current usage patterns
328
+ - Colorful progress indicators (green/yellow/red for quota warnings)
329
+ - Graceful shutdown with Ctrl+C
330
+
310
331
  #### Blocks-specific options
311
332
 
312
333
  - `-t, --token-limit <number|max>`: Set token limit for quota warnings (use "max" for highest previous block)
313
334
  - `-a, --active`: Show only active block with detailed projections
314
335
  - `-r, --recent`: Show blocks from last 3 days (including active)
336
+ - `-l, --session-length <hours>`: Session block duration in hours (default: 5)
337
+ - `--live`: Live monitoring mode with real-time dashboard (automatically uses `-t max` and shows active block only)
338
+ - `--refresh-interval <seconds>`: Refresh interval for live mode (default: 1, range: 1-60)
315
339
 
316
340
  ### Options
317
341
 
@@ -565,6 +589,7 @@ some projects use `ccusage` internally and provide additional features:
565
589
 
566
590
  - [claude-usage-tracker-for-mac](https://github.com/penicillin0/claude-usage-tracker-for-mac) – macOS menu bar app to visualize Claude Code usage costs by [@penicillin0](https://github.com/penicillin0).
567
591
  - [ccusage Raycast Extension](https://www.raycast.com/nyatinte/ccusage) – Raycast extension to view Claude Code usage reports in Raycast by [@nyatinte](https://github.com/nyatinte).
592
+ - [ClaudeCode_Dashboard](https://github.com/m-sigepon/ClaudeCode_Dashboard) – Web dashboard to visualize Claude Code usage with charts and USD/JPY conversion by [@m-sigepon](https://github.com/m-sigepon).
568
593
 
569
594
  ## Acknowledgments
570
595
 
@@ -574,7 +599,7 @@ Thanks to [@milliondev](https://note.com/milliondev) for the original concept an
574
599
 
575
600
  <p align="center">
576
601
  <a href="https://github.com/sponsors/ryoppippi">
577
- <img src="https://cdn.jsdelivr.net/gh/ryoppippi/sponsors/sponsors.svg">
602
+ <img src="https://cdn.jsdelivr.net/gh/ryoppippi/sponsors@main/sponsors.svg">
578
603
  </a>
579
604
  </p>
580
605
 
@@ -1,5 +1,5 @@
1
1
  import "./pricing-fetcher-CXnYw4TA.js";
2
- import { DailyUsage, MonthlyUsage, SessionUsage } from "./data-loader-C1n0ww95.js";
2
+ import { DailyUsage, MonthlyUsage, SessionUsage } from "./data-loader-Bll0wMdK.js";
3
3
 
4
4
  //#region src/calculate-cost.d.ts
5
5
  /**
@@ -91,8 +91,8 @@ declare const usageDataSchema: z.ZodObject<{
91
91
  cache_creation_input_tokens?: number | undefined;
92
92
  cache_read_input_tokens?: number | undefined;
93
93
  };
94
- model?: string & z.BRAND<"ModelName"> | undefined;
95
- id?: string & z.BRAND<"MessageId"> | undefined;
94
+ model?: (string & z.BRAND<"ModelName">) | undefined;
95
+ id?: (string & z.BRAND<"MessageId">) | undefined;
96
96
  }, {
97
97
  usage: {
98
98
  input_tokens: number;
@@ -107,7 +107,7 @@ declare const usageDataSchema: z.ZodObject<{
107
107
  requestId: z.ZodOptional<z.ZodBranded<z.ZodString, "RequestId">>;
108
108
  }, "strip", z.ZodTypeAny, {
109
109
  timestamp: string & z.BRAND<"ISOTimestamp">;
110
- version?: string & z.BRAND<"Version"> | undefined;
110
+ version?: (string & z.BRAND<"Version">) | undefined;
111
111
  message: {
112
112
  usage: {
113
113
  input_tokens: number;
@@ -115,11 +115,11 @@ declare const usageDataSchema: z.ZodObject<{
115
115
  cache_creation_input_tokens?: number | undefined;
116
116
  cache_read_input_tokens?: number | undefined;
117
117
  };
118
- model?: string & z.BRAND<"ModelName"> | undefined;
119
- id?: string & z.BRAND<"MessageId"> | undefined;
118
+ model?: (string & z.BRAND<"ModelName">) | undefined;
119
+ id?: (string & z.BRAND<"MessageId">) | undefined;
120
120
  };
121
121
  costUSD?: number | undefined;
122
- requestId?: string & z.BRAND<"RequestId"> | undefined;
122
+ requestId?: (string & z.BRAND<"RequestId">) | undefined;
123
123
  }, {
124
124
  timestamp: string;
125
125
  version?: string | undefined;
@@ -1,6 +1,6 @@
1
- import { CLAUDE_CONFIG_DIR_ENV, CLAUDE_PROJECTS_DIR_NAME, DEFAULT_CLAUDE_CODE_PATH, DEFAULT_CLAUDE_CONFIG_PATH, DEFAULT_RECENT_DAYS, PricingFetcher, USAGE_DATA_GLOB_PATTERN, USER_HOME_DIR, __commonJSMin, __require, __toESM, require_usingCtx } from "./pricing-fetcher-XdvIG0to.js";
1
+ import { CLAUDE_CONFIG_DIR_ENV, CLAUDE_PROJECTS_DIR_NAME, DEFAULT_CLAUDE_CODE_PATH, DEFAULT_CLAUDE_CONFIG_PATH, DEFAULT_RECENT_DAYS, PricingFetcher, USAGE_DATA_GLOB_PATTERN, USER_HOME_DIR, __commonJSMin, __require, __toESM, require_usingCtx } from "./pricing-fetcher-DBzWmU38.js";
2
2
  import { activityDateSchema, arrayType, createDailyDate, createMonthlyDate, createProjectPath, createSessionId, dailyDateSchema, isoTimestampSchema, messageIdSchema, modelNameSchema, monthlyDateSchema, numberType, objectType, projectPathSchema, requestIdSchema, sessionIdSchema, versionSchema } from "./_types-Cr2YEzKm.js";
3
- import { logger } from "./logger-CIYlc309.js";
3
+ import { logger } from "./logger-r_DhIB_J.js";
4
4
  import a, { readFile } from "node:fs/promises";
5
5
  import F, { homedir } from "node:os";
6
6
  import path, { posix } from "node:path";
@@ -3065,6 +3065,16 @@ async function glob(patternsOrOptions, options) {
3065
3065
  */
3066
3066
  const DEFAULT_SESSION_DURATION_HOURS = 5;
3067
3067
  /**
3068
+ * Floors a timestamp to the beginning of the hour in UTC
3069
+ * @param timestamp - The timestamp to floor
3070
+ * @returns New Date object floored to the UTC hour
3071
+ */
3072
+ function floorToHour(timestamp) {
3073
+ const floored = new Date(timestamp);
3074
+ floored.setUTCMinutes(0, 0, 0);
3075
+ return floored;
3076
+ }
3077
+ /**
3068
3078
  * Identifies and creates session blocks from usage entries
3069
3079
  * Groups entries into time-based blocks (typically 5-hour periods) with gap detection
3070
3080
  * @param entries - Array of usage entries to process
@@ -3082,7 +3092,7 @@ function identifySessionBlocks(entries, sessionDurationHours = DEFAULT_SESSION_D
3082
3092
  for (const entry of sortedEntries) {
3083
3093
  const entryTime = entry.timestamp;
3084
3094
  if (currentBlockStart == null) {
3085
- currentBlockStart = entryTime;
3095
+ currentBlockStart = floorToHour(entryTime);
3086
3096
  currentBlockEntries = [entry];
3087
3097
  } else {
3088
3098
  const timeSinceBlockStart = entryTime.getTime() - currentBlockStart.getTime();
@@ -3097,7 +3107,7 @@ function identifySessionBlocks(entries, sessionDurationHours = DEFAULT_SESSION_D
3097
3107
  const gapBlock = createGapBlock(lastEntryTime, entryTime, sessionDurationMs);
3098
3108
  if (gapBlock != null) blocks.push(gapBlock);
3099
3109
  }
3100
- currentBlockStart = entryTime;
3110
+ currentBlockStart = floorToHour(entryTime);
3101
3111
  currentBlockEntries = [entry];
3102
3112
  } else currentBlockEntries.push(entry);
3103
3113
  }
@@ -3869,4 +3879,4 @@ async function loadSessionBlockData(options) {
3869
3879
  _usingCtx4.d();
3870
3880
  }
3871
3881
  }
3872
- export { DEFAULT_SESSION_DURATION_HOURS, calculateBurnRate, calculateCostForEntry, createUniqueHash, dailyUsageSchema, filterRecentBlocks, formatDate, formatDateCompact, getClaudePaths, getDefaultClaudePath, getEarliestTimestamp, glob, loadDailyUsageData, loadMonthlyUsageData, loadSessionBlockData, loadSessionData, modelBreakdownSchema, monthlyUsageSchema, projectBlockUsage, sessionUsageSchema, sortFilesByTimestamp, uniq, usageDataSchema };
3882
+ export { DEFAULT_SESSION_DURATION_HOURS, calculateBurnRate, calculateCostForEntry, createUniqueHash, dailyUsageSchema, filterRecentBlocks, formatDate, formatDateCompact, getClaudePaths, getDefaultClaudePath, getEarliestTimestamp, glob, identifySessionBlocks, loadDailyUsageData, loadMonthlyUsageData, loadSessionBlockData, loadSessionData, modelBreakdownSchema, monthlyUsageSchema, projectBlockUsage, sessionUsageSchema, sortFilesByTimestamp, uniq, usageDataSchema };
@@ -1,3 +1,3 @@
1
1
  import "./pricing-fetcher-CXnYw4TA.js";
2
- import { DailyUsage, DateFilter, LoadOptions, ModelBreakdown, MonthlyUsage, SessionUsage, UsageData, calculateCostForEntry, createUniqueHash, dailyUsageSchema, formatDate, formatDateCompact, getClaudePaths, getDefaultClaudePath, getEarliestTimestamp, loadDailyUsageData, loadMonthlyUsageData, loadSessionBlockData, loadSessionData, modelBreakdownSchema, monthlyUsageSchema, sessionUsageSchema, sortFilesByTimestamp, usageDataSchema } from "./data-loader-C1n0ww95.js";
2
+ import { DailyUsage, DateFilter, LoadOptions, ModelBreakdown, MonthlyUsage, SessionUsage, UsageData, calculateCostForEntry, createUniqueHash, dailyUsageSchema, formatDate, formatDateCompact, getClaudePaths, getDefaultClaudePath, getEarliestTimestamp, loadDailyUsageData, loadMonthlyUsageData, loadSessionBlockData, loadSessionData, modelBreakdownSchema, monthlyUsageSchema, sessionUsageSchema, sortFilesByTimestamp, usageDataSchema } from "./data-loader-Bll0wMdK.js";
3
3
  export { DailyUsage, DateFilter, LoadOptions, ModelBreakdown, MonthlyUsage, SessionUsage, UsageData, calculateCostForEntry, createUniqueHash, dailyUsageSchema, formatDate, formatDateCompact, getClaudePaths, getDefaultClaudePath, getEarliestTimestamp, loadDailyUsageData, loadMonthlyUsageData, loadSessionBlockData, loadSessionData, modelBreakdownSchema, monthlyUsageSchema, sessionUsageSchema, sortFilesByTimestamp, usageDataSchema };
@@ -1,5 +1,5 @@
1
- import "./pricing-fetcher-XdvIG0to.js";
1
+ import "./pricing-fetcher-DBzWmU38.js";
2
2
  import "./_types-Cr2YEzKm.js";
3
- import { calculateCostForEntry, createUniqueHash, dailyUsageSchema, formatDate, formatDateCompact, getClaudePaths, getDefaultClaudePath, getEarliestTimestamp, loadDailyUsageData, loadMonthlyUsageData, loadSessionBlockData, loadSessionData, modelBreakdownSchema, monthlyUsageSchema, sessionUsageSchema, sortFilesByTimestamp, usageDataSchema } from "./data-loader-BFS_JSqd.js";
4
- import "./logger-CIYlc309.js";
3
+ import { calculateCostForEntry, createUniqueHash, dailyUsageSchema, formatDate, formatDateCompact, getClaudePaths, getDefaultClaudePath, getEarliestTimestamp, loadDailyUsageData, loadMonthlyUsageData, loadSessionBlockData, loadSessionData, modelBreakdownSchema, monthlyUsageSchema, sessionUsageSchema, sortFilesByTimestamp, usageDataSchema } from "./data-loader-DQftfBz9.js";
4
+ import "./logger-r_DhIB_J.js";
5
5
  export { calculateCostForEntry, createUniqueHash, dailyUsageSchema, formatDate, formatDateCompact, getClaudePaths, getDefaultClaudePath, getEarliestTimestamp, loadDailyUsageData, loadMonthlyUsageData, loadSessionBlockData, loadSessionData, modelBreakdownSchema, monthlyUsageSchema, sessionUsageSchema, sortFilesByTimestamp, usageDataSchema };
@@ -1,6 +1,6 @@
1
- import { CLAUDE_PROJECTS_DIR_NAME, DEBUG_MATCH_THRESHOLD_PERCENT, PricingFetcher, USAGE_DATA_GLOB_PATTERN, __toESM, require_usingCtx } from "./pricing-fetcher-XdvIG0to.js";
2
- import { getDefaultClaudePath, glob, usageDataSchema } from "./data-loader-BFS_JSqd.js";
3
- import { logger } from "./logger-CIYlc309.js";
1
+ import { CLAUDE_PROJECTS_DIR_NAME, DEBUG_MATCH_THRESHOLD_PERCENT, PricingFetcher, USAGE_DATA_GLOB_PATTERN, __toESM, require_usingCtx } from "./pricing-fetcher-DBzWmU38.js";
2
+ import { getDefaultClaudePath, glob, usageDataSchema } from "./data-loader-DQftfBz9.js";
3
+ import { logger } from "./logger-r_DhIB_J.js";
4
4
  import { readFile } from "node:fs/promises";
5
5
  import path from "node:path";
6
6
  var import_usingCtx = __toESM(require_usingCtx(), 1);
package/dist/debug.js CHANGED
@@ -1,6 +1,6 @@
1
- import "./pricing-fetcher-XdvIG0to.js";
1
+ import "./pricing-fetcher-DBzWmU38.js";
2
2
  import "./_types-Cr2YEzKm.js";
3
- import "./data-loader-BFS_JSqd.js";
4
- import "./logger-CIYlc309.js";
5
- import { detectMismatches, printMismatchReport } from "./debug-DIfzQVQt.js";
3
+ import "./data-loader-DQftfBz9.js";
4
+ import "./logger-r_DhIB_J.js";
5
+ import { detectMismatches, printMismatchReport } from "./debug-CXtWvV0a.js";
6
6
  export { detectMismatches, printMismatchReport };