ccusage 15.8.0 → 15.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -55,6 +55,7 @@ ccusage daily # Daily token usage and costs
55
55
  ccusage monthly # Monthly aggregated report
56
56
  ccusage session # Usage by conversation session
57
57
  ccusage blocks # 5-hour billing windows
58
+ ccusage statusline # Compact status line for hooks (Beta)
58
59
 
59
60
  # Live monitoring
60
61
  ccusage blocks --live # Real-time usage dashboard
@@ -79,6 +80,7 @@ ccusage daily --instances --project myproject --json # Combined usage
79
80
  - 💬 **Session Report**: View usage grouped by conversation sessions
80
81
  - ⏰ **5-Hour Blocks Report**: Track usage within Claude's billing windows with active block monitoring
81
82
  - 📈 **Live Monitoring**: Real-time dashboard showing active session progress, token burn rate, and cost projections with `blocks --live`
83
+ - 🚀 **Statusline Integration**: Compact usage display for Claude Code status bar hooks (Beta)
82
84
  - 🤖 **Model Tracking**: See which Claude models you're using (Opus, Sonnet, etc.)
83
85
  - 📊 **Model Breakdown**: View per-model cost breakdown with `--breakdown` flag
84
86
  - 📅 **Date Filtering**: Filter reports by date range using `--since` and `--until`
@@ -3610,4 +3610,21 @@ const modelPricingSchema = objectType({
3610
3610
  cache_creation_input_token_cost: numberType().optional(),
3611
3611
  cache_read_input_token_cost: numberType().optional()
3612
3612
  });
3613
- export { CostModes, SortOrders, ZodFirstPartyTypeKind, ZodOptional, ZodType, activityDateSchema, arrayType, booleanType, createBucket, createDailyDate, createMonthlyDate, createProjectPath, createSessionId, createWeeklyDate, dailyDateSchema, discriminatedUnionType, enumType, filterDateSchema, isoTimestampSchema, literalType, messageIdSchema, modelNameSchema, modelPricingSchema, monthlyDateSchema, numberType, objectType, optionalType, projectPathSchema, recordType, requestIdSchema, sessionIdSchema, stringType, unionType, unknownType, versionSchema, weeklyDateSchema };
3613
+ /**
3614
+ * Zod schema for Claude Code statusline hook JSON data
3615
+ */
3616
+ const statuslineHookJsonSchema = objectType({
3617
+ session_id: stringType(),
3618
+ transcript_path: stringType(),
3619
+ cwd: stringType(),
3620
+ model: objectType({
3621
+ id: stringType(),
3622
+ display_name: stringType()
3623
+ }),
3624
+ workspace: objectType({
3625
+ current_dir: stringType(),
3626
+ project_dir: stringType()
3627
+ }),
3628
+ version: stringType().optional()
3629
+ });
3630
+ export { CostModes, SortOrders, ZodFirstPartyTypeKind, ZodOptional, ZodType, activityDateSchema, arrayType, booleanType, createBucket, createDailyDate, createMonthlyDate, createProjectPath, createSessionId, createWeeklyDate, dailyDateSchema, discriminatedUnionType, enumType, filterDateSchema, isoTimestampSchema, literalType, messageIdSchema, modelNameSchema, modelPricingSchema, monthlyDateSchema, numberType, objectType, optionalType, projectPathSchema, recordType, requestIdSchema, sessionIdSchema, statuslineHookJsonSchema, stringType, unionType, unknownType, versionSchema, weeklyDateSchema };
@@ -1,5 +1,5 @@
1
- import "./pricing-fetcher-AYfCy7g-.js";
2
- import { DailyUsage, MonthlyUsage, SessionUsage, WeeklyUsage } from "./data-loader-De3CFZ54.js";
1
+ import "./pricing-fetcher-C9P2YKDv.js";
2
+ import { DailyUsage, MonthlyUsage, SessionUsage, WeeklyUsage } from "./data-loader-PvTcFbip.js";
3
3
 
4
4
  //#region src/_token-utils.d.ts
5
5
 
@@ -1,4 +1,4 @@
1
1
  import { getTotalTokens } from "./_token-utils-WjkbrjKv.js";
2
- import "./_types-ed8-0BH6.js";
2
+ import "./_types-B-1t4mxD.js";
3
3
  import { calculateTotals, createTotalsObject } from "./calculate-cost-BDqO4yWA.js";
4
4
  export { calculateTotals, createTotalsObject, getTotalTokens };
@@ -1,7 +1,7 @@
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, isFailure, isPromise, require_usingCtx } from "./pricing-fetcher-CAYjaayN.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, isFailure, isPromise, require_usingCtx } from "./pricing-fetcher-S0o3dB03.js";
2
2
  import { getTotalTokens } from "./_token-utils-WjkbrjKv.js";
3
- import { activityDateSchema, arrayType, booleanType, createBucket, createDailyDate, createMonthlyDate, createProjectPath, createSessionId, createWeeklyDate, dailyDateSchema, isoTimestampSchema, messageIdSchema, modelNameSchema, monthlyDateSchema, numberType, objectType, projectPathSchema, requestIdSchema, sessionIdSchema, stringType, unionType, versionSchema, weeklyDateSchema } from "./_types-ed8-0BH6.js";
4
- import { logger } from "./logger-HOimBpSq.js";
3
+ import { activityDateSchema, arrayType, booleanType, createBucket, createDailyDate, createMonthlyDate, createProjectPath, createSessionId, createWeeklyDate, dailyDateSchema, isoTimestampSchema, messageIdSchema, modelNameSchema, monthlyDateSchema, numberType, objectType, projectPathSchema, requestIdSchema, sessionIdSchema, stringType, unionType, versionSchema, weeklyDateSchema } from "./_types-B-1t4mxD.js";
4
+ import { logger } from "./logger-DxuNm8GV.js";
5
5
  import a, { readFile } from "node:fs/promises";
6
6
  import path, { posix } from "node:path";
7
7
  import process$1 from "node:process";
@@ -3347,6 +3347,8 @@ function extractProjectFromPath(jsonlPath) {
3347
3347
  * Zod schema for validating Claude usage data from JSONL files
3348
3348
  */
3349
3349
  const usageDataSchema = objectType({
3350
+ cwd: stringType().optional(),
3351
+ sessionId: sessionIdSchema.optional(),
3350
3352
  timestamp: isoTimestampSchema,
3351
3353
  version: versionSchema.optional(),
3352
3354
  message: objectType({
@@ -3951,6 +3953,49 @@ async function loadWeeklyUsageData(options) {
3951
3953
  ...rest
3952
3954
  })));
3953
3955
  }
3956
+ /**
3957
+ * Load usage data for a specific session by sessionId
3958
+ * Searches for a JSONL file named {sessionId}.jsonl in all Claude project directories
3959
+ * @param sessionId - The session ID to load data for (matches the JSONL filename)
3960
+ * @param options - Options for loading data
3961
+ * @param options.mode - Cost calculation mode (auto, calculate, display)
3962
+ * @param options.offline - Whether to use offline pricing data
3963
+ * @returns Usage data for the specific session or null if not found
3964
+ */
3965
+ async function loadSessionUsageById(sessionId, options) {
3966
+ try {
3967
+ var _usingCtx4 = (0, import_usingCtx.default)();
3968
+ const claudePaths = getClaudePaths();
3969
+ const patterns = claudePaths.map((p) => path.join(p, "projects", "**", `${sessionId}.jsonl`));
3970
+ const jsonlFiles = await glob(patterns);
3971
+ if (jsonlFiles.length === 0) return null;
3972
+ const file = jsonlFiles[0];
3973
+ if (file == null) return null;
3974
+ const content = await readFile(file, "utf-8");
3975
+ const lines = content.trim().split("\n").filter((line) => line.length > 0);
3976
+ const mode = options?.mode ?? "auto";
3977
+ const fetcher = _usingCtx4.u(mode === "display" ? null : new PricingFetcher(options?.offline));
3978
+ const entries = [];
3979
+ let totalCost = 0;
3980
+ for (const line of lines) try {
3981
+ const parsed = JSON.parse(line);
3982
+ const result = usageDataSchema.safeParse(parsed);
3983
+ if (!result.success) continue;
3984
+ const data = result.data;
3985
+ const cost = fetcher != null ? await calculateCostForEntry(data, mode, fetcher) : data.costUSD ?? 0;
3986
+ totalCost += cost;
3987
+ entries.push(data);
3988
+ } catch {}
3989
+ return {
3990
+ totalCost,
3991
+ entries
3992
+ };
3993
+ } catch (_) {
3994
+ _usingCtx4.e = _;
3995
+ } finally {
3996
+ _usingCtx4.d();
3997
+ }
3998
+ }
3954
3999
  async function loadBucketUsageData(groupingFn, options) {
3955
4000
  const dailyData = await loadDailyUsageData(options);
3956
4001
  const needsProjectGrouping = options?.groupByProject === true || options?.project != null;
@@ -4002,7 +4047,7 @@ async function loadBucketUsageData(groupingFn, options) {
4002
4047
  */
4003
4048
  async function loadSessionBlockData(options) {
4004
4049
  try {
4005
- var _usingCtx4 = (0, import_usingCtx.default)();
4050
+ var _usingCtx5 = (0, import_usingCtx.default)();
4006
4051
  const claudePaths = toArray(options?.claudePath ?? getClaudePaths());
4007
4052
  const allFiles = [];
4008
4053
  for (const claudePath of claudePaths) {
@@ -4017,7 +4062,7 @@ async function loadSessionBlockData(options) {
4017
4062
  const blocksFilteredFiles = filterByProject(allFiles, (filePath) => extractProjectFromPath(filePath), options?.project);
4018
4063
  const sortedFiles = await sortFilesByTimestamp(blocksFilteredFiles);
4019
4064
  const mode = options?.mode ?? "auto";
4020
- const fetcher = _usingCtx4.u(mode === "display" ? null : new PricingFetcher(options?.offline));
4065
+ const fetcher = _usingCtx5.u(mode === "display" ? null : new PricingFetcher(options?.offline));
4021
4066
  const processedHashes = new Set();
4022
4067
  const allEntries = [];
4023
4068
  for (const file of sortedFiles) {
@@ -4059,9 +4104,9 @@ async function loadSessionBlockData(options) {
4059
4104
  }) : blocks;
4060
4105
  return sortByDate(dateFiltered, (block) => block.startTime, options?.order);
4061
4106
  } catch (_) {
4062
- _usingCtx4.e = _;
4107
+ _usingCtx5.e = _;
4063
4108
  } finally {
4064
- _usingCtx4.d();
4109
+ _usingCtx5.d();
4065
4110
  }
4066
4111
  }
4067
- export { DEFAULT_SESSION_DURATION_HOURS, bucketUsageSchema, calculateBurnRate, calculateCostForEntry, createUniqueHash, dailyUsageSchema, extractProjectFromPath, filterRecentBlocks, formatDate, formatDateCompact, getClaudePaths, getEarliestTimestamp, getUsageLimitResetTime, glob, globUsageFiles, identifySessionBlocks, loadBucketUsageData, loadDailyUsageData, loadMonthlyUsageData, loadSessionBlockData, loadSessionData, loadWeeklyUsageData, modelBreakdownSchema, monthlyUsageSchema, projectBlockUsage, sessionUsageSchema, sortFilesByTimestamp, uniq, unwrap, usageDataSchema, weeklyUsageSchema };
4112
+ export { DEFAULT_SESSION_DURATION_HOURS, bucketUsageSchema, calculateBurnRate, calculateCostForEntry, createUniqueHash, dailyUsageSchema, extractProjectFromPath, filterRecentBlocks, formatDate, formatDateCompact, getClaudePaths, getEarliestTimestamp, getUsageLimitResetTime, glob, globUsageFiles, identifySessionBlocks, loadBucketUsageData, loadDailyUsageData, loadMonthlyUsageData, loadSessionBlockData, loadSessionData, loadSessionUsageById, loadWeeklyUsageData, modelBreakdownSchema, monthlyUsageSchema, projectBlockUsage, sessionUsageSchema, sortFilesByTimestamp, uniq, unwrap, usageDataSchema, weeklyUsageSchema };
@@ -1,4 +1,4 @@
1
- import { Bucket, CostMode, PricingFetcher$1 as PricingFetcher, SortOrder, TupleToUnion } from "./pricing-fetcher-AYfCy7g-.js";
1
+ import { Bucket, CostMode, PricingFetcher$1 as PricingFetcher, SortOrder, TupleToUnion } from "./pricing-fetcher-C9P2YKDv.js";
2
2
  import { z } from "zod";
3
3
 
4
4
  //#region src/_consts.d.ts
@@ -72,6 +72,8 @@ declare function extractProjectFromPath(jsonlPath: string): string;
72
72
  * Zod schema for validating Claude usage data from JSONL files
73
73
  */
74
74
  declare const usageDataSchema: z.ZodObject<{
75
+ cwd: z.ZodOptional<z.ZodString>;
76
+ sessionId: z.ZodOptional<z.ZodBranded<z.ZodString, "SessionId">>;
75
77
  timestamp: z.ZodBranded<z.ZodString, "ISOTimestamp">;
76
78
  version: z.ZodOptional<z.ZodBranded<z.ZodString, "Version">>;
77
79
  message: z.ZodObject<{
@@ -129,6 +131,8 @@ declare const usageDataSchema: z.ZodObject<{
129
131
  requestId: z.ZodOptional<z.ZodBranded<z.ZodString, "RequestId">>;
130
132
  isApiErrorMessage: z.ZodOptional<z.ZodBoolean>;
131
133
  }, "strip", z.ZodTypeAny, {
134
+ cwd?: string | undefined;
135
+ sessionId?: (string & z.BRAND<"SessionId">) | undefined;
132
136
  timestamp: string & z.BRAND<"ISOTimestamp">;
133
137
  version?: (string & z.BRAND<"Version">) | undefined;
134
138
  message: {
@@ -148,6 +152,8 @@ declare const usageDataSchema: z.ZodObject<{
148
152
  requestId?: (string & z.BRAND<"RequestId">) | undefined;
149
153
  isApiErrorMessage?: boolean | undefined;
150
154
  }, {
155
+ cwd?: string | undefined;
156
+ sessionId?: string | undefined;
151
157
  timestamp: string;
152
158
  version?: string | undefined;
153
159
  message: {
@@ -673,6 +679,22 @@ declare function loadSessionData(options?: LoadOptions): Promise<SessionUsage[]>
673
679
  */
674
680
  declare function loadMonthlyUsageData(options?: LoadOptions): Promise<MonthlyUsage[]>;
675
681
  declare function loadWeeklyUsageData(options?: LoadOptions): Promise<WeeklyUsage[]>;
682
+ /**
683
+ * Load usage data for a specific session by sessionId
684
+ * Searches for a JSONL file named {sessionId}.jsonl in all Claude project directories
685
+ * @param sessionId - The session ID to load data for (matches the JSONL filename)
686
+ * @param options - Options for loading data
687
+ * @param options.mode - Cost calculation mode (auto, calculate, display)
688
+ * @param options.offline - Whether to use offline pricing data
689
+ * @returns Usage data for the specific session or null if not found
690
+ */
691
+ declare function loadSessionUsageById(sessionId: string, options?: {
692
+ mode?: CostMode;
693
+ offline?: boolean;
694
+ }): Promise<{
695
+ totalCost: number;
696
+ entries: UsageData[];
697
+ } | null>;
676
698
  declare function loadBucketUsageData(groupingFn: (data: DailyUsage) => Bucket, options?: LoadOptions): Promise<BucketUsage[]>;
677
699
  /**
678
700
  * Loads usage data and organizes it into session blocks (typically 5-hour billing periods)
@@ -682,4 +704,4 @@ declare function loadBucketUsageData(groupingFn: (data: DailyUsage) => Bucket, o
682
704
  */
683
705
  declare function loadSessionBlockData(options?: LoadOptions): Promise<SessionBlock[]>;
684
706
  //#endregion
685
- export { BucketUsage, DailyUsage, DateFilter, GlobResult, LoadOptions, ModelBreakdown, MonthlyUsage, SessionUsage, UsageData, WeeklyUsage, bucketUsageSchema as bucketUsageSchema$1, calculateCostForEntry as calculateCostForEntry$1, createUniqueHash as createUniqueHash$1, dailyUsageSchema as dailyUsageSchema$1, extractProjectFromPath as extractProjectFromPath$1, formatDate as formatDate$1, formatDateCompact as formatDateCompact$1, getClaudePaths as getClaudePaths$1, getEarliestTimestamp as getEarliestTimestamp$1, getUsageLimitResetTime as getUsageLimitResetTime$1, globUsageFiles as globUsageFiles$1, loadBucketUsageData as loadBucketUsageData$1, loadDailyUsageData as loadDailyUsageData$1, loadMonthlyUsageData as loadMonthlyUsageData$1, loadSessionBlockData as loadSessionBlockData$1, loadSessionData as loadSessionData$1, loadWeeklyUsageData as loadWeeklyUsageData$1, modelBreakdownSchema as modelBreakdownSchema$1, monthlyUsageSchema as monthlyUsageSchema$1, sessionUsageSchema as sessionUsageSchema$1, sortFilesByTimestamp as sortFilesByTimestamp$1, usageDataSchema as usageDataSchema$1, weeklyUsageSchema as weeklyUsageSchema$1 };
707
+ export { BucketUsage, DailyUsage, DateFilter, GlobResult, LoadOptions, ModelBreakdown, MonthlyUsage, SessionUsage, UsageData, WeeklyUsage, bucketUsageSchema as bucketUsageSchema$1, calculateCostForEntry as calculateCostForEntry$1, createUniqueHash as createUniqueHash$1, dailyUsageSchema as dailyUsageSchema$1, extractProjectFromPath as extractProjectFromPath$1, formatDate as formatDate$1, formatDateCompact as formatDateCompact$1, getClaudePaths as getClaudePaths$1, getEarliestTimestamp as getEarliestTimestamp$1, getUsageLimitResetTime as getUsageLimitResetTime$1, globUsageFiles as globUsageFiles$1, loadBucketUsageData as loadBucketUsageData$1, loadDailyUsageData as loadDailyUsageData$1, loadMonthlyUsageData as loadMonthlyUsageData$1, loadSessionBlockData as loadSessionBlockData$1, loadSessionData as loadSessionData$1, loadSessionUsageById as loadSessionUsageById$1, loadWeeklyUsageData as loadWeeklyUsageData$1, modelBreakdownSchema as modelBreakdownSchema$1, monthlyUsageSchema as monthlyUsageSchema$1, sessionUsageSchema as sessionUsageSchema$1, sortFilesByTimestamp as sortFilesByTimestamp$1, usageDataSchema as usageDataSchema$1, weeklyUsageSchema as weeklyUsageSchema$1 };
@@ -1,3 +1,3 @@
1
- import "./pricing-fetcher-AYfCy7g-.js";
2
- import { BucketUsage, DailyUsage, DateFilter, GlobResult, LoadOptions, ModelBreakdown, MonthlyUsage, SessionUsage, UsageData, WeeklyUsage, bucketUsageSchema$1 as bucketUsageSchema, calculateCostForEntry$1 as calculateCostForEntry, createUniqueHash$1 as createUniqueHash, dailyUsageSchema$1 as dailyUsageSchema, extractProjectFromPath$1 as extractProjectFromPath, formatDate$1 as formatDate, formatDateCompact$1 as formatDateCompact, getClaudePaths$1 as getClaudePaths, getEarliestTimestamp$1 as getEarliestTimestamp, getUsageLimitResetTime$1 as getUsageLimitResetTime, globUsageFiles$1 as globUsageFiles, loadBucketUsageData$1 as loadBucketUsageData, loadDailyUsageData$1 as loadDailyUsageData, loadMonthlyUsageData$1 as loadMonthlyUsageData, loadSessionBlockData$1 as loadSessionBlockData, loadSessionData$1 as loadSessionData, loadWeeklyUsageData$1 as loadWeeklyUsageData, modelBreakdownSchema$1 as modelBreakdownSchema, monthlyUsageSchema$1 as monthlyUsageSchema, sessionUsageSchema$1 as sessionUsageSchema, sortFilesByTimestamp$1 as sortFilesByTimestamp, usageDataSchema$1 as usageDataSchema, weeklyUsageSchema$1 as weeklyUsageSchema } from "./data-loader-De3CFZ54.js";
3
- export { BucketUsage, DailyUsage, DateFilter, GlobResult, LoadOptions, ModelBreakdown, MonthlyUsage, SessionUsage, UsageData, WeeklyUsage, bucketUsageSchema, calculateCostForEntry, createUniqueHash, dailyUsageSchema, extractProjectFromPath, formatDate, formatDateCompact, getClaudePaths, getEarliestTimestamp, getUsageLimitResetTime, globUsageFiles, loadBucketUsageData, loadDailyUsageData, loadMonthlyUsageData, loadSessionBlockData, loadSessionData, loadWeeklyUsageData, modelBreakdownSchema, monthlyUsageSchema, sessionUsageSchema, sortFilesByTimestamp, usageDataSchema, weeklyUsageSchema };
1
+ import "./pricing-fetcher-C9P2YKDv.js";
2
+ import { BucketUsage, DailyUsage, DateFilter, GlobResult, LoadOptions, ModelBreakdown, MonthlyUsage, SessionUsage, UsageData, WeeklyUsage, bucketUsageSchema$1 as bucketUsageSchema, calculateCostForEntry$1 as calculateCostForEntry, createUniqueHash$1 as createUniqueHash, dailyUsageSchema$1 as dailyUsageSchema, extractProjectFromPath$1 as extractProjectFromPath, formatDate$1 as formatDate, formatDateCompact$1 as formatDateCompact, getClaudePaths$1 as getClaudePaths, getEarliestTimestamp$1 as getEarliestTimestamp, getUsageLimitResetTime$1 as getUsageLimitResetTime, globUsageFiles$1 as globUsageFiles, loadBucketUsageData$1 as loadBucketUsageData, loadDailyUsageData$1 as loadDailyUsageData, loadMonthlyUsageData$1 as loadMonthlyUsageData, loadSessionBlockData$1 as loadSessionBlockData, loadSessionData$1 as loadSessionData, loadSessionUsageById$1 as loadSessionUsageById, loadWeeklyUsageData$1 as loadWeeklyUsageData, modelBreakdownSchema$1 as modelBreakdownSchema, monthlyUsageSchema$1 as monthlyUsageSchema, sessionUsageSchema$1 as sessionUsageSchema, sortFilesByTimestamp$1 as sortFilesByTimestamp, usageDataSchema$1 as usageDataSchema, weeklyUsageSchema$1 as weeklyUsageSchema } from "./data-loader-PvTcFbip.js";
3
+ export { BucketUsage, DailyUsage, DateFilter, GlobResult, LoadOptions, ModelBreakdown, MonthlyUsage, SessionUsage, UsageData, WeeklyUsage, bucketUsageSchema, calculateCostForEntry, createUniqueHash, dailyUsageSchema, extractProjectFromPath, formatDate, formatDateCompact, getClaudePaths, getEarliestTimestamp, getUsageLimitResetTime, globUsageFiles, loadBucketUsageData, loadDailyUsageData, loadMonthlyUsageData, loadSessionBlockData, loadSessionData, loadSessionUsageById, loadWeeklyUsageData, modelBreakdownSchema, monthlyUsageSchema, sessionUsageSchema, sortFilesByTimestamp, usageDataSchema, weeklyUsageSchema };
@@ -1,6 +1,6 @@
1
- import "./pricing-fetcher-CAYjaayN.js";
1
+ import "./pricing-fetcher-S0o3dB03.js";
2
2
  import "./_token-utils-WjkbrjKv.js";
3
- import "./_types-ed8-0BH6.js";
4
- import { bucketUsageSchema, calculateCostForEntry, createUniqueHash, dailyUsageSchema, extractProjectFromPath, formatDate, formatDateCompact, getClaudePaths, getEarliestTimestamp, getUsageLimitResetTime, globUsageFiles, loadBucketUsageData, loadDailyUsageData, loadMonthlyUsageData, loadSessionBlockData, loadSessionData, loadWeeklyUsageData, modelBreakdownSchema, monthlyUsageSchema, sessionUsageSchema, sortFilesByTimestamp, usageDataSchema, weeklyUsageSchema } from "./data-loader-DbAQLtpd.js";
5
- import "./logger-HOimBpSq.js";
6
- export { bucketUsageSchema, calculateCostForEntry, createUniqueHash, dailyUsageSchema, extractProjectFromPath, formatDate, formatDateCompact, getClaudePaths, getEarliestTimestamp, getUsageLimitResetTime, globUsageFiles, loadBucketUsageData, loadDailyUsageData, loadMonthlyUsageData, loadSessionBlockData, loadSessionData, loadWeeklyUsageData, modelBreakdownSchema, monthlyUsageSchema, sessionUsageSchema, sortFilesByTimestamp, usageDataSchema, weeklyUsageSchema };
3
+ import "./_types-B-1t4mxD.js";
4
+ import { bucketUsageSchema, calculateCostForEntry, createUniqueHash, dailyUsageSchema, extractProjectFromPath, formatDate, formatDateCompact, getClaudePaths, getEarliestTimestamp, getUsageLimitResetTime, globUsageFiles, loadBucketUsageData, loadDailyUsageData, loadMonthlyUsageData, loadSessionBlockData, loadSessionData, loadSessionUsageById, loadWeeklyUsageData, modelBreakdownSchema, monthlyUsageSchema, sessionUsageSchema, sortFilesByTimestamp, usageDataSchema, weeklyUsageSchema } from "./data-loader-CKAeM9ir.js";
5
+ import "./logger-DxuNm8GV.js";
6
+ export { bucketUsageSchema, calculateCostForEntry, createUniqueHash, dailyUsageSchema, extractProjectFromPath, formatDate, formatDateCompact, getClaudePaths, getEarliestTimestamp, getUsageLimitResetTime, globUsageFiles, loadBucketUsageData, loadDailyUsageData, loadMonthlyUsageData, loadSessionBlockData, loadSessionData, loadSessionUsageById, loadWeeklyUsageData, modelBreakdownSchema, monthlyUsageSchema, sessionUsageSchema, sortFilesByTimestamp, usageDataSchema, weeklyUsageSchema };
@@ -1,6 +1,6 @@
1
- import { CLAUDE_PROJECTS_DIR_NAME, DEBUG_MATCH_THRESHOLD_PERCENT, PricingFetcher, USAGE_DATA_GLOB_PATTERN, __toESM, isFailure, require_usingCtx, try_ } from "./pricing-fetcher-CAYjaayN.js";
2
- import { getClaudePaths, glob, unwrap, usageDataSchema } from "./data-loader-DbAQLtpd.js";
3
- import { logger } from "./logger-HOimBpSq.js";
1
+ import { CLAUDE_PROJECTS_DIR_NAME, DEBUG_MATCH_THRESHOLD_PERCENT, PricingFetcher, USAGE_DATA_GLOB_PATTERN, __toESM, isFailure, require_usingCtx, try_ } from "./pricing-fetcher-S0o3dB03.js";
2
+ import { getClaudePaths, glob, unwrap, usageDataSchema } from "./data-loader-CKAeM9ir.js";
3
+ import { logger } from "./logger-DxuNm8GV.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,7 +1,7 @@
1
- import "./pricing-fetcher-CAYjaayN.js";
1
+ import "./pricing-fetcher-S0o3dB03.js";
2
2
  import "./_token-utils-WjkbrjKv.js";
3
- import "./_types-ed8-0BH6.js";
4
- import "./data-loader-DbAQLtpd.js";
5
- import "./logger-HOimBpSq.js";
6
- import { detectMismatches, printMismatchReport } from "./debug-jL56ZeA8.js";
3
+ import "./_types-B-1t4mxD.js";
4
+ import "./data-loader-CKAeM9ir.js";
5
+ import "./logger-DxuNm8GV.js";
6
+ import { detectMismatches, printMismatchReport } from "./debug-DMwiBRRn.js";
7
7
  export { detectMismatches, printMismatchReport };
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, DEFAULT_RECENT_DAYS, DEFAULT_REFRESH_INTERVAL_SECONDS, MAX_REFRESH_INTERVAL_SECONDS, MCP_DEFAULT_PORT, MIN_REFRESH_INTERVAL_SECONDS, MIN_RENDER_INTERVAL_MS, PROJECT_ALIASES_ENV, PricingFetcher, WEEK_DAYS, __commonJSMin, __require, __toESM, isFailure, require_usingCtx, try_ } from "./pricing-fetcher-CAYjaayN.js";
2
+ import { BLOCKS_COMPACT_WIDTH_THRESHOLD, BLOCKS_DEFAULT_TERMINAL_WIDTH, BLOCKS_WARNING_THRESHOLD, BURN_RATE_THRESHOLDS, DEFAULT_RECENT_DAYS, DEFAULT_REFRESH_INTERVAL_SECONDS, MAX_REFRESH_INTERVAL_SECONDS, MCP_DEFAULT_PORT, MIN_REFRESH_INTERVAL_SECONDS, MIN_RENDER_INTERVAL_MS, PROJECT_ALIASES_ENV, PricingFetcher, WEEK_DAYS, __commonJSMin, __require, __toESM, isFailure, require_usingCtx, try_ } from "./pricing-fetcher-S0o3dB03.js";
3
3
  import { getTotalTokens } from "./_token-utils-WjkbrjKv.js";
4
- import { CostModes, SortOrders, filterDateSchema } from "./_types-ed8-0BH6.js";
4
+ import { CostModes, SortOrders, filterDateSchema, statuslineHookJsonSchema } from "./_types-B-1t4mxD.js";
5
5
  import { calculateTotals, createTotalsObject } from "./calculate-cost-BDqO4yWA.js";
6
- import { DEFAULT_SESSION_DURATION_HOURS, calculateBurnRate, calculateCostForEntry, createUniqueHash, filterRecentBlocks, formatDateCompact, getClaudePaths, getEarliestTimestamp, getUsageLimitResetTime, globUsageFiles, identifySessionBlocks, loadDailyUsageData, loadMonthlyUsageData, loadSessionBlockData, loadSessionData, loadWeeklyUsageData, projectBlockUsage, sortFilesByTimestamp, uniq, usageDataSchema } from "./data-loader-DbAQLtpd.js";
7
- import { description, log, logger, name, version } from "./logger-HOimBpSq.js";
8
- import { detectMismatches, printMismatchReport } from "./debug-jL56ZeA8.js";
9
- import { createMcpHttpApp, createMcpServer, startMcpServerStdio } from "./mcp-DVxqAEVW.js";
6
+ import { DEFAULT_SESSION_DURATION_HOURS, calculateBurnRate, calculateCostForEntry, createUniqueHash, filterRecentBlocks, formatDateCompact, getClaudePaths, getEarliestTimestamp, getUsageLimitResetTime, globUsageFiles, identifySessionBlocks, loadDailyUsageData, loadMonthlyUsageData, loadSessionBlockData, loadSessionData, loadSessionUsageById, loadWeeklyUsageData, projectBlockUsage, sortFilesByTimestamp, uniq, usageDataSchema } from "./data-loader-CKAeM9ir.js";
7
+ import { description, log, logger, name, version } from "./logger-DxuNm8GV.js";
8
+ import { detectMismatches, printMismatchReport } from "./debug-DMwiBRRn.js";
9
+ import { createMcpHttpApp, createMcpServer, startMcpServerStdio } from "./mcp-pA-Z7D2o.js";
10
10
  import { readFile } from "node:fs/promises";
11
11
  import process$1 from "node:process";
12
12
  import { createServer } from "node:http";
@@ -2950,7 +2950,7 @@ function stringWidth(string, options = {}) {
2950
2950
  return width;
2951
2951
  }
2952
2952
  var import_cli_table3 = __toESM(require_cli_table3(), 1);
2953
- var import_picocolors$7 = __toESM(require_picocolors(), 1);
2953
+ var import_picocolors$8 = __toESM(require_picocolors(), 1);
2954
2954
  /**
2955
2955
  * Responsive table class that adapts column widths based on terminal size
2956
2956
  * Automatically adjusts formatting and layout for different screen sizes
@@ -3186,7 +3186,7 @@ function pushBreakdownRows(table, breakdowns, extraColumns = 1, trailingColumns
3186
3186
  const row = [` └─ ${formatModelName(breakdown.modelName)}`];
3187
3187
  for (let i = 0; i < extraColumns; i++) row.push("");
3188
3188
  const totalTokens = breakdown.inputTokens + breakdown.outputTokens + breakdown.cacheCreationTokens + breakdown.cacheReadTokens;
3189
- row.push(import_picocolors$7.default.gray(formatNumber(breakdown.inputTokens)), import_picocolors$7.default.gray(formatNumber(breakdown.outputTokens)), import_picocolors$7.default.gray(formatNumber(breakdown.cacheCreationTokens)), import_picocolors$7.default.gray(formatNumber(breakdown.cacheReadTokens)), import_picocolors$7.default.gray(formatNumber(totalTokens)), import_picocolors$7.default.gray(formatCurrency(breakdown.cost)));
3189
+ 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)));
3190
3190
  for (let i = 0; i < trailingColumns; i++) row.push("");
3191
3191
  table.push(row);
3192
3192
  }
@@ -3700,16 +3700,16 @@ const RESTORE_CURSOR = "\x1B8";
3700
3700
  function drawEmoji(emoji) {
3701
3701
  return `${SAVE_CURSOR}${emoji}${RESTORE_CURSOR}${cursorForward(stringWidth(emoji))}`;
3702
3702
  }
3703
- var import_picocolors$6 = __toESM(require_picocolors(), 1);
3703
+ var import_picocolors$7 = __toESM(require_picocolors(), 1);
3704
3704
  /**
3705
3705
  * Get rate indicator (HIGH/MODERATE/NORMAL) based on burn rate
3706
3706
  */
3707
3707
  function getRateIndicator(burnRate) {
3708
3708
  if (burnRate == null) return "";
3709
3709
  switch (true) {
3710
- case burnRate.tokensPerMinuteForIndicator > BURN_RATE_THRESHOLDS.HIGH: return import_picocolors$6.default.red(`${drawEmoji("⚡")} HIGH`);
3711
- case burnRate.tokensPerMinuteForIndicator > BURN_RATE_THRESHOLDS.MODERATE: return import_picocolors$6.default.yellow(`${drawEmoji("⚡")} MODERATE`);
3712
- default: return import_picocolors$6.default.green(`${drawEmoji("✓")} NORMAL`);
3710
+ case burnRate.tokensPerMinuteForIndicator > BURN_RATE_THRESHOLDS.HIGH: return import_picocolors$7.default.red(`${drawEmoji("⚡")} HIGH`);
3711
+ case burnRate.tokensPerMinuteForIndicator > BURN_RATE_THRESHOLDS.MODERATE: return import_picocolors$7.default.yellow(`${drawEmoji("⚡")} MODERATE`);
3712
+ default: return import_picocolors$7.default.green(`${drawEmoji("✓")} NORMAL`);
3713
3713
  }
3714
3714
  }
3715
3715
  /**
@@ -3726,7 +3726,7 @@ async function renderWaitingState(terminal, config, signal) {
3726
3726
  terminal.startBuffering();
3727
3727
  terminal.write(cursorTo(0, 0));
3728
3728
  terminal.write(eraseDown);
3729
- terminal.write(import_picocolors$6.default.yellow("No active session block found. Waiting...\n"));
3729
+ terminal.write(import_picocolors$7.default.yellow("No active session block found. Waiting...\n"));
3730
3730
  terminal.write(cursorHide);
3731
3731
  terminal.flush();
3732
3732
  await delayWithAbort(config.refreshInterval, signal);
@@ -3784,8 +3784,8 @@ function renderLiveDisplay(terminal, block, config) {
3784
3784
  const barWidth = boxWidth - labelWidth - maxRightTextWidth - spacing - boxPadding;
3785
3785
  const sessionProgressBar = createProgressBar(elapsed, sessionDuration, barWidth, {
3786
3786
  showPercentage: false,
3787
- fillChar: import_picocolors$6.default.cyan("█"),
3788
- emptyChar: import_picocolors$6.default.gray("░"),
3787
+ fillChar: import_picocolors$7.default.cyan("█"),
3788
+ emptyChar: import_picocolors$7.default.gray("░"),
3789
3789
  leftBracket: "[",
3790
3790
  rightBracket: "]"
3791
3791
  });
@@ -3805,17 +3805,17 @@ function renderLiveDisplay(terminal, block, config) {
3805
3805
  const detailsSpacing = 2;
3806
3806
  const detailsAvailableWidth = boxWidth - 3 - detailsIndent;
3807
3807
  terminal.write(`${marginStr}┌${"─".repeat(boxWidth - 2)}┐\n`);
3808
- terminal.write(`${marginStr}│${import_picocolors$6.default.bold(centerText("CLAUDE CODE - LIVE TOKEN USAGE MONITOR", boxWidth - 2))}│\n`);
3808
+ terminal.write(`${marginStr}│${import_picocolors$7.default.bold(centerText("CLAUDE CODE - LIVE TOKEN USAGE MONITOR", boxWidth - 2))}│\n`);
3809
3809
  terminal.write(`${marginStr}├${"─".repeat(boxWidth - 2)}┤\n`);
3810
3810
  terminal.write(`${marginStr}│${" ".repeat(boxWidth - 2)}│\n`);
3811
- const sessionLabel = `${drawEmoji("⏱️")}${import_picocolors$6.default.bold(" SESSION")}`;
3811
+ const sessionLabel = `${drawEmoji("⏱️")}${import_picocolors$7.default.bold(" SESSION")}`;
3812
3812
  const sessionLabelWidth = stringWidth(sessionLabel);
3813
3813
  const sessionBarStr = `${sessionLabel}${"".padEnd(Math.max(0, labelWidth - sessionLabelWidth))} ${sessionProgressBar} ${sessionRightText}`;
3814
3814
  const sessionBarPadded = sessionBarStr + " ".repeat(Math.max(0, boxWidth - 3 - stringWidth(sessionBarStr)));
3815
3815
  terminal.write(`${marginStr}│ ${sessionBarPadded}│\n`);
3816
- const sessionCol1 = `${import_picocolors$6.default.gray("Started:")} ${startTime}`;
3817
- const sessionCol2 = `${import_picocolors$6.default.gray("Elapsed:")} ${prettyMilliseconds(elapsed * 60 * 1e3, { compact: true })}`;
3818
- const sessionCol3 = `${import_picocolors$6.default.gray("Remaining:")} ${prettyMilliseconds(remaining * 60 * 1e3, { compact: true })} (${endTime})`;
3816
+ const sessionCol1 = `${import_picocolors$7.default.gray("Started:")} ${startTime}`;
3817
+ const sessionCol2 = `${import_picocolors$7.default.gray("Elapsed:")} ${prettyMilliseconds(elapsed * 60 * 1e3, { compact: true })}`;
3818
+ const sessionCol3 = `${import_picocolors$7.default.gray("Remaining:")} ${prettyMilliseconds(remaining * 60 * 1e3, { compact: true })} (${endTime})`;
3819
3819
  let sessionDetails = `${" ".repeat(detailsIndent)}${sessionCol1}${" ".repeat(detailsSpacing)}${sessionCol2}${" ".repeat(detailsSpacing)}${sessionCol3}`;
3820
3820
  const sessionDetailsWidth = stringWidth(sessionCol1) + stringWidth(sessionCol2) + stringWidth(sessionCol3) + detailsSpacing * 2;
3821
3821
  if (sessionDetailsWidth > detailsAvailableWidth) sessionDetails = `${" ".repeat(detailsIndent)}${sessionCol1}${" ".repeat(detailsSpacing)}${sessionCol3}`;
@@ -3827,7 +3827,7 @@ function renderLiveDisplay(terminal, block, config) {
3827
3827
  minute: "2-digit",
3828
3828
  hour12: true
3829
3829
  }) ?? null;
3830
- const usageLimitResetTime = resetTime !== null ? import_picocolors$6.default.red(`${drawEmoji("❌")} USAGE LIMIT. RESET AT ${resetTime}`) : "";
3830
+ const usageLimitResetTime = resetTime !== null ? import_picocolors$7.default.red(`${drawEmoji("❌")} USAGE LIMIT. RESET AT ${resetTime}`) : "";
3831
3831
  usageLimitResetTimePadded = resetTime !== null ? usageLimitResetTime + " ".repeat(Math.max(0, boxWidth - 3 - stringWidth(usageLimitResetTime))) : null;
3832
3832
  }
3833
3833
  terminal.write(`${marginStr}│ ${sessionDetailsPadded}│\n`);
@@ -3835,31 +3835,31 @@ function renderLiveDisplay(terminal, block, config) {
3835
3835
  terminal.write(`${marginStr}│${" ".repeat(boxWidth - 2)}│\n`);
3836
3836
  terminal.write(`${marginStr}├${"─".repeat(boxWidth - 2)}┤\n`);
3837
3837
  terminal.write(`${marginStr}│${" ".repeat(boxWidth - 2)}│\n`);
3838
- let barColor = import_picocolors$6.default.green;
3839
- if (tokenPercent > 100) barColor = import_picocolors$6.default.red;
3840
- else if (tokenPercent > 80) barColor = import_picocolors$6.default.yellow;
3838
+ let barColor = import_picocolors$7.default.green;
3839
+ if (tokenPercent > 100) barColor = import_picocolors$7.default.red;
3840
+ else if (tokenPercent > 80) barColor = import_picocolors$7.default.yellow;
3841
3841
  const usageBar = config.tokenLimit != null && config.tokenLimit > 0 ? createProgressBar(totalTokens, config.tokenLimit, barWidth, {
3842
3842
  showPercentage: false,
3843
3843
  fillChar: barColor("█"),
3844
- emptyChar: import_picocolors$6.default.gray("░"),
3844
+ emptyChar: import_picocolors$7.default.gray("░"),
3845
3845
  leftBracket: "[",
3846
3846
  rightBracket: "]"
3847
- }) : `[${import_picocolors$6.default.green("█".repeat(Math.floor(barWidth * .1)))}${import_picocolors$6.default.gray("░".repeat(barWidth - Math.floor(barWidth * .1)))}]`;
3847
+ }) : `[${import_picocolors$7.default.green("█".repeat(Math.floor(barWidth * .1)))}${import_picocolors$7.default.gray("░".repeat(barWidth - Math.floor(barWidth * .1)))}]`;
3848
3848
  const burnRate = calculateBurnRate(block);
3849
3849
  const rateIndicator = getRateIndicator(burnRate);
3850
3850
  const buildRateDisplay = (useShort) => {
3851
- if (burnRate == null) return `${import_picocolors$6.default.bold("Burn Rate:")} N/A`;
3851
+ if (burnRate == null) return `${import_picocolors$7.default.bold("Burn Rate:")} N/A`;
3852
3852
  const rateValue = Math.round(burnRate.tokensPerMinute);
3853
3853
  const formattedRate = useShort ? formatTokensShort(rateValue) : formatNumber(rateValue);
3854
- return `${import_picocolors$6.default.bold("Burn Rate:")} ${formattedRate} token/min ${rateIndicator}`;
3854
+ return `${import_picocolors$7.default.bold("Burn Rate:")} ${formattedRate} token/min ${rateIndicator}`;
3855
3855
  };
3856
- const usageLabel = `${drawEmoji("🔥")}${import_picocolors$6.default.bold(" USAGE")}`;
3856
+ const usageLabel = `${drawEmoji("🔥")}${import_picocolors$7.default.bold(" USAGE")}`;
3857
3857
  const usageLabelWidth = stringWidth(usageLabel);
3858
3858
  const usageBarStr = `${usageLabel}${"".padEnd(Math.max(0, labelWidth - usageLabelWidth))} ${usageBar} ${usageRightText}`;
3859
3859
  let rateDisplay = buildRateDisplay(false);
3860
- let usageCol1 = `${import_picocolors$6.default.gray("Tokens:")} ${formatTokenDisplay(totalTokens, false)} (${rateDisplay})`;
3861
- let usageCol2 = config.tokenLimit != null && config.tokenLimit > 0 ? `${import_picocolors$6.default.gray("Limit:")} ${formatTokenDisplay(config.tokenLimit, false)} tokens` : "";
3862
- const usageCol3 = `${import_picocolors$6.default.gray("Cost:")} ${formatCurrency(block.costUSD)}`;
3860
+ let usageCol1 = `${import_picocolors$7.default.gray("Tokens:")} ${formatTokenDisplay(totalTokens, false)} (${rateDisplay})`;
3861
+ let usageCol2 = config.tokenLimit != null && config.tokenLimit > 0 ? `${import_picocolors$7.default.gray("Limit:")} ${formatTokenDisplay(config.tokenLimit, false)} tokens` : "";
3862
+ const usageCol3 = `${import_picocolors$7.default.gray("Cost:")} ${formatCurrency(block.costUSD)}`;
3863
3863
  let totalWidth = stringWidth(usageCol1);
3864
3864
  if (usageCol2.length > 0) totalWidth += detailsSpacing + stringWidth(usageCol2);
3865
3865
  totalWidth += detailsSpacing + stringWidth(usageCol3);
@@ -3867,8 +3867,8 @@ function renderLiveDisplay(terminal, block, config) {
3867
3867
  if (totalWidth > detailsAvailableWidth) {
3868
3868
  useTwoLineLayout = true;
3869
3869
  rateDisplay = buildRateDisplay(true);
3870
- usageCol1 = `${import_picocolors$6.default.gray("Tokens:")} ${formatTokenDisplay(totalTokens, true)} (${rateDisplay})`;
3871
- if (usageCol2.length > 0) usageCol2 = `${import_picocolors$6.default.gray("Limit:")} ${formatTokenDisplay(config.tokenLimit, true)} tokens`;
3870
+ usageCol1 = `${import_picocolors$7.default.gray("Tokens:")} ${formatTokenDisplay(totalTokens, true)} (${rateDisplay})`;
3871
+ if (usageCol2.length > 0) usageCol2 = `${import_picocolors$7.default.gray("Limit:")} ${formatTokenDisplay(config.tokenLimit, true)} tokens`;
3872
3872
  }
3873
3873
  const usageBarPadded = usageBarStr + " ".repeat(Math.max(0, boxWidth - 3 - stringWidth(usageBarStr)));
3874
3874
  terminal.write(`${marginStr}│ ${usageBarPadded}│\n`);
@@ -3892,30 +3892,30 @@ function renderLiveDisplay(terminal, block, config) {
3892
3892
  terminal.write(`${marginStr}├${"─".repeat(boxWidth - 2)}┤\n`);
3893
3893
  terminal.write(`${marginStr}│${" ".repeat(boxWidth - 2)}│\n`);
3894
3894
  if (projection != null) {
3895
- let projBarColor = import_picocolors$6.default.green;
3896
- if (projectedPercent > 100) projBarColor = import_picocolors$6.default.red;
3897
- else if (projectedPercent > 80) projBarColor = import_picocolors$6.default.yellow;
3895
+ let projBarColor = import_picocolors$7.default.green;
3896
+ if (projectedPercent > 100) projBarColor = import_picocolors$7.default.red;
3897
+ else if (projectedPercent > 80) projBarColor = import_picocolors$7.default.yellow;
3898
3898
  const projectionBar = config.tokenLimit != null && config.tokenLimit > 0 ? createProgressBar(projection.totalTokens, config.tokenLimit, barWidth, {
3899
3899
  showPercentage: false,
3900
3900
  fillChar: projBarColor("█"),
3901
- emptyChar: import_picocolors$6.default.gray("░"),
3901
+ emptyChar: import_picocolors$7.default.gray("░"),
3902
3902
  leftBracket: "[",
3903
3903
  rightBracket: "]"
3904
- }) : `[${import_picocolors$6.default.green("█".repeat(Math.floor(barWidth * .15)))}${import_picocolors$6.default.gray("░".repeat(barWidth - Math.floor(barWidth * .15)))}]`;
3905
- const limitStatus = config.tokenLimit != null && config.tokenLimit > 0 ? projectedPercent > 100 ? import_picocolors$6.default.red(`${drawEmoji("❌")} WILL EXCEED LIMIT`) : projectedPercent > 80 ? import_picocolors$6.default.yellow(`${drawEmoji("⚠️")} APPROACHING LIMIT`) : import_picocolors$6.default.green(`${drawEmoji("✓")} WITHIN LIMIT`) : import_picocolors$6.default.green(`${drawEmoji("✓")} ON TRACK`);
3906
- const projLabel = `${drawEmoji("📈")}${import_picocolors$6.default.bold(" PROJECTION")}`;
3904
+ }) : `[${import_picocolors$7.default.green("█".repeat(Math.floor(barWidth * .15)))}${import_picocolors$7.default.gray("░".repeat(barWidth - Math.floor(barWidth * .15)))}]`;
3905
+ const 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`);
3906
+ const projLabel = `${drawEmoji("📈")}${import_picocolors$7.default.bold(" PROJECTION")}`;
3907
3907
  const projLabelWidth = stringWidth(projLabel);
3908
3908
  const projBarStr = `${projLabel}${"".padEnd(Math.max(0, labelWidth - projLabelWidth))} ${projectionBar} ${projectionRightText}`;
3909
3909
  const projBarPadded = projBarStr + " ".repeat(Math.max(0, boxWidth - 3 - stringWidth(projBarStr)));
3910
3910
  terminal.write(`${marginStr}│ ${projBarPadded}│\n`);
3911
- const projCol1 = `${import_picocolors$6.default.gray("Status:")} ${limitStatus}`;
3912
- let projCol2 = `${import_picocolors$6.default.gray("Tokens:")} ${formatTokenDisplay(projection.totalTokens, false)}`;
3913
- const projCol3 = `${import_picocolors$6.default.gray("Cost:")} ${formatCurrency(projection.totalCost)}`;
3911
+ const projCol1 = `${import_picocolors$7.default.gray("Status:")} ${limitStatus}`;
3912
+ let projCol2 = `${import_picocolors$7.default.gray("Tokens:")} ${formatTokenDisplay(projection.totalTokens, false)}`;
3913
+ const projCol3 = `${import_picocolors$7.default.gray("Cost:")} ${formatCurrency(projection.totalCost)}`;
3914
3914
  const projTotalWidth = stringWidth(projCol1) + stringWidth(projCol2) + stringWidth(projCol3) + detailsSpacing * 2;
3915
3915
  let projUseTwoLineLayout = false;
3916
3916
  if (projTotalWidth > detailsAvailableWidth) {
3917
3917
  projUseTwoLineLayout = true;
3918
- projCol2 = `${import_picocolors$6.default.gray("Tokens:")} ${formatTokenDisplay(projection.totalTokens, true)}`;
3918
+ projCol2 = `${import_picocolors$7.default.gray("Tokens:")} ${formatTokenDisplay(projection.totalTokens, true)}`;
3919
3919
  }
3920
3920
  if (projUseTwoLineLayout) {
3921
3921
  const projDetailsLine1 = `${" ".repeat(detailsIndent)}${projCol1}`;
@@ -3939,7 +3939,7 @@ function renderLiveDisplay(terminal, block, config) {
3939
3939
  }
3940
3940
  terminal.write(`${marginStr}├${"─".repeat(boxWidth - 2)}┤\n`);
3941
3941
  const refreshText = `${drawEmoji("↻")} Refreshing every ${config.refreshInterval / 1e3}s • Press Ctrl+C to stop`;
3942
- terminal.write(`${marginStr}│${import_picocolors$6.default.gray(centerText(refreshText, boxWidth - 2))}│\n`);
3942
+ terminal.write(`${marginStr}│${import_picocolors$7.default.gray(centerText(refreshText, boxWidth - 2))}│\n`);
3943
3943
  terminal.write(`${marginStr}└${"─".repeat(boxWidth - 2)}┘\n`);
3944
3944
  }
3945
3945
  /**
@@ -3947,22 +3947,22 @@ function renderLiveDisplay(terminal, block, config) {
3947
3947
  */
3948
3948
  function renderCompactLiveDisplay(terminal, block, config, totalTokens, elapsed, remaining) {
3949
3949
  const width = terminal.width;
3950
- terminal.write(`${import_picocolors$6.default.bold(centerText("LIVE MONITOR", width))}\n`);
3950
+ terminal.write(`${import_picocolors$7.default.bold(centerText("LIVE MONITOR", width))}\n`);
3951
3951
  terminal.write(`${"─".repeat(width)}\n`);
3952
3952
  const sessionPercent = elapsed / (elapsed + remaining) * 100;
3953
3953
  terminal.write(`Session: ${sessionPercent.toFixed(1)}% (${Math.floor(elapsed / 60)}h ${Math.floor(elapsed % 60)}m)\n`);
3954
3954
  if (config.tokenLimit != null && config.tokenLimit > 0) {
3955
3955
  const tokenPercent = totalTokens / config.tokenLimit * 100;
3956
- const status = tokenPercent > 100 ? import_picocolors$6.default.red("OVER") : tokenPercent > 80 ? import_picocolors$6.default.yellow("WARN") : import_picocolors$6.default.green("OK");
3956
+ const status = tokenPercent > 100 ? import_picocolors$7.default.red("OVER") : tokenPercent > 80 ? import_picocolors$7.default.yellow("WARN") : import_picocolors$7.default.green("OK");
3957
3957
  terminal.write(`Tokens: ${formatNumber(totalTokens)}/${formatNumber(config.tokenLimit)} ${status}\n`);
3958
3958
  } else terminal.write(`Tokens: ${formatNumber(totalTokens)}\n`);
3959
3959
  terminal.write(`Cost: ${formatCurrency(block.costUSD)}\n`);
3960
3960
  const burnRate = calculateBurnRate(block);
3961
3961
  if (burnRate != null) terminal.write(`Rate: ${formatNumber(burnRate.tokensPerMinute)}/min\n`);
3962
3962
  terminal.write(`${"─".repeat(width)}\n`);
3963
- terminal.write(import_picocolors$6.default.gray(`Refresh: ${config.refreshInterval / 1e3}s | Ctrl+C: stop\n`));
3963
+ terminal.write(import_picocolors$7.default.gray(`Refresh: ${config.refreshInterval / 1e3}s | Ctrl+C: stop\n`));
3964
3964
  }
3965
- var import_picocolors$5 = __toESM(require_picocolors(), 1);
3965
+ var import_picocolors$6 = __toESM(require_picocolors(), 1);
3966
3966
  var import_usingCtx = __toESM(require_usingCtx(), 1);
3967
3967
  async function startLiveMonitoring(config) {
3968
3968
  try {
@@ -4025,7 +4025,7 @@ async function startLiveMonitoring(config) {
4025
4025
  const errorMessage = error instanceof Error ? error.message : String(error);
4026
4026
  terminal.startBuffering();
4027
4027
  terminal.clearScreen();
4028
- terminal.write(import_picocolors$5.default.red(`Error: ${errorMessage}\n`));
4028
+ terminal.write(import_picocolors$6.default.red(`Error: ${errorMessage}\n`));
4029
4029
  terminal.flush();
4030
4030
  logger.error(`Live monitoring error: ${errorMessage}`);
4031
4031
  await delayWithAbort(config.refreshInterval, abortController.signal).catch(() => {});
@@ -4036,7 +4036,7 @@ async function startLiveMonitoring(config) {
4036
4036
  _usingCtx.d();
4037
4037
  }
4038
4038
  }
4039
- var import_picocolors$4 = __toESM(require_picocolors(), 1);
4039
+ var import_picocolors$5 = __toESM(require_picocolors(), 1);
4040
4040
  /**
4041
4041
  * Formats the time display for a session block
4042
4042
  * @param block - Session block to format
@@ -4245,19 +4245,19 @@ const blocksCommand = define({
4245
4245
  const now = new Date();
4246
4246
  const elapsed = Math.round((now.getTime() - block.startTime.getTime()) / (1e3 * 60));
4247
4247
  const remaining = Math.round((block.endTime.getTime() - now.getTime()) / (1e3 * 60));
4248
- log(`Block Started: ${import_picocolors$4.default.cyan(block.startTime.toLocaleString())} (${import_picocolors$4.default.yellow(`${Math.floor(elapsed / 60)}h ${elapsed % 60}m`)} ago)`);
4249
- log(`Time Remaining: ${import_picocolors$4.default.green(`${Math.floor(remaining / 60)}h ${remaining % 60}m`)}\n`);
4250
- log(import_picocolors$4.default.bold("Current Usage:"));
4248
+ 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)`);
4249
+ log(`Time Remaining: ${import_picocolors$5.default.green(`${Math.floor(remaining / 60)}h ${remaining % 60}m`)}\n`);
4250
+ log(import_picocolors$5.default.bold("Current Usage:"));
4251
4251
  log(` Input Tokens: ${formatNumber(block.tokenCounts.inputTokens)}`);
4252
4252
  log(` Output Tokens: ${formatNumber(block.tokenCounts.outputTokens)}`);
4253
4253
  log(` Total Cost: ${formatCurrency(block.costUSD)}\n`);
4254
4254
  if (burnRate != null) {
4255
- log(import_picocolors$4.default.bold("Burn Rate:"));
4255
+ log(import_picocolors$5.default.bold("Burn Rate:"));
4256
4256
  log(` Tokens/minute: ${formatNumber(burnRate.tokensPerMinute)}`);
4257
4257
  log(` Cost/hour: ${formatCurrency(burnRate.costPerHour)}\n`);
4258
4258
  }
4259
4259
  if (projection != null) {
4260
- log(import_picocolors$4.default.bold("Projected Usage (if current rate continues):"));
4260
+ log(import_picocolors$5.default.bold("Projected Usage (if current rate continues):"));
4261
4261
  log(` Total Tokens: ${formatNumber(projection.totalTokens)}`);
4262
4262
  log(` Total Cost: ${formatCurrency(projection.totalCost)}\n`);
4263
4263
  if (ctx.values.tokenLimit != null) {
@@ -4266,8 +4266,8 @@ const blocksCommand = define({
4266
4266
  const currentTokens = getTotalTokens(block.tokenCounts);
4267
4267
  const remainingTokens = Math.max(0, limit - currentTokens);
4268
4268
  const percentUsed = projection.totalTokens / limit * 100;
4269
- const status = percentUsed > 100 ? import_picocolors$4.default.red("EXCEEDS LIMIT") : percentUsed > BLOCKS_WARNING_THRESHOLD * 100 ? import_picocolors$4.default.yellow("WARNING") : import_picocolors$4.default.green("OK");
4270
- log(import_picocolors$4.default.bold("Token Limit Status:"));
4269
+ const 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");
4270
+ log(import_picocolors$5.default.bold("Token Limit Status:"));
4271
4271
  log(` Limit: ${formatNumber(limit)} tokens`);
4272
4272
  log(` Current Usage: ${formatNumber(currentTokens)} (${(currentTokens / limit * 100).toFixed(1)}%)`);
4273
4273
  log(` Remaining: ${formatNumber(remainingTokens)} tokens`);
@@ -4305,17 +4305,17 @@ const blocksCommand = define({
4305
4305
  const useCompactFormat = terminalWidth < BLOCKS_COMPACT_WIDTH_THRESHOLD;
4306
4306
  for (const block of blocks) if (block.isGap ?? false) {
4307
4307
  const gapRow = [
4308
- import_picocolors$4.default.gray(formatBlockTime(block, useCompactFormat, ctx.values.locale)),
4309
- import_picocolors$4.default.gray("(inactive)"),
4310
- import_picocolors$4.default.gray("-"),
4311
- import_picocolors$4.default.gray("-")
4308
+ import_picocolors$5.default.gray(formatBlockTime(block, useCompactFormat, ctx.values.locale)),
4309
+ import_picocolors$5.default.gray("(inactive)"),
4310
+ import_picocolors$5.default.gray("-"),
4311
+ import_picocolors$5.default.gray("-")
4312
4312
  ];
4313
- if (actualTokenLimit != null && actualTokenLimit > 0) gapRow.push(import_picocolors$4.default.gray("-"));
4314
- gapRow.push(import_picocolors$4.default.gray("-"));
4313
+ if (actualTokenLimit != null && actualTokenLimit > 0) gapRow.push(import_picocolors$5.default.gray("-"));
4314
+ gapRow.push(import_picocolors$5.default.gray("-"));
4315
4315
  table.push(gapRow);
4316
4316
  } else {
4317
4317
  const totalTokens = getTotalTokens(block.tokenCounts);
4318
- const status = block.isActive ? import_picocolors$4.default.green("ACTIVE") : "";
4318
+ const status = block.isActive ? import_picocolors$5.default.green("ACTIVE") : "";
4319
4319
  const row = [
4320
4320
  formatBlockTime(block, useCompactFormat, ctx.values.locale),
4321
4321
  status,
@@ -4325,7 +4325,7 @@ const blocksCommand = define({
4325
4325
  if (actualTokenLimit != null && actualTokenLimit > 0) {
4326
4326
  const percentage = totalTokens / actualTokenLimit * 100;
4327
4327
  const percentText = `${percentage.toFixed(1)}%`;
4328
- row.push(percentage > 100 ? import_picocolors$4.default.red(percentText) : percentText);
4328
+ row.push(percentage > 100 ? import_picocolors$5.default.red(percentText) : percentText);
4329
4329
  }
4330
4330
  row.push(formatCurrency(block.costUSD));
4331
4331
  table.push(row);
@@ -4333,15 +4333,15 @@ const blocksCommand = define({
4333
4333
  if (actualTokenLimit != null && actualTokenLimit > 0) {
4334
4334
  const currentTokens = getTotalTokens(block.tokenCounts);
4335
4335
  const remainingTokens = Math.max(0, actualTokenLimit - currentTokens);
4336
- const remainingText = remainingTokens > 0 ? formatNumber(remainingTokens) : import_picocolors$4.default.red("0");
4336
+ const remainingText = remainingTokens > 0 ? formatNumber(remainingTokens) : import_picocolors$5.default.red("0");
4337
4337
  const remainingPercent = (actualTokenLimit - currentTokens) / actualTokenLimit * 100;
4338
- const remainingPercentText = remainingPercent > 0 ? `${remainingPercent.toFixed(1)}%` : import_picocolors$4.default.red("0.0%");
4338
+ const remainingPercentText = remainingPercent > 0 ? `${remainingPercent.toFixed(1)}%` : import_picocolors$5.default.red("0.0%");
4339
4339
  const remainingRow = [
4340
4340
  {
4341
- content: import_picocolors$4.default.gray(`(assuming ${formatNumber(actualTokenLimit)} token limit)`),
4341
+ content: import_picocolors$5.default.gray(`(assuming ${formatNumber(actualTokenLimit)} token limit)`),
4342
4342
  hAlign: "right"
4343
4343
  },
4344
- import_picocolors$4.default.blue("REMAINING"),
4344
+ import_picocolors$5.default.blue("REMAINING"),
4345
4345
  "",
4346
4346
  remainingText,
4347
4347
  remainingPercentText,
@@ -4352,13 +4352,13 @@ const blocksCommand = define({
4352
4352
  const projection = projectBlockUsage(block);
4353
4353
  if (projection != null) {
4354
4354
  const projectedTokens = formatNumber(projection.totalTokens);
4355
- const projectedText = actualTokenLimit != null && actualTokenLimit > 0 && projection.totalTokens > actualTokenLimit ? import_picocolors$4.default.red(projectedTokens) : projectedTokens;
4355
+ const projectedText = actualTokenLimit != null && actualTokenLimit > 0 && projection.totalTokens > actualTokenLimit ? import_picocolors$5.default.red(projectedTokens) : projectedTokens;
4356
4356
  const projectedRow = [
4357
4357
  {
4358
- content: import_picocolors$4.default.gray("(assuming current burn rate)"),
4358
+ content: import_picocolors$5.default.gray("(assuming current burn rate)"),
4359
4359
  hAlign: "right"
4360
4360
  },
4361
- import_picocolors$4.default.yellow("PROJECTED"),
4361
+ import_picocolors$5.default.yellow("PROJECTED"),
4362
4362
  "",
4363
4363
  projectedText
4364
4364
  ];
@@ -4513,7 +4513,7 @@ function formatProjectName(projectName) {
4513
4513
  if (aliases.has(parsed)) return aliases.get(parsed);
4514
4514
  return parsed;
4515
4515
  }
4516
- var import_picocolors$3 = __toESM(require_picocolors(), 1);
4516
+ var import_picocolors$4 = __toESM(require_picocolors(), 1);
4517
4517
  const dailyCommand = define({
4518
4518
  name: "daily",
4519
4519
  description: "Show usage report grouped by date",
@@ -4631,7 +4631,7 @@ const dailyCommand = define({
4631
4631
  ""
4632
4632
  ]);
4633
4633
  table.push([
4634
- import_picocolors$3.default.cyan(`Project: ${formatProjectName(projectName)}`),
4634
+ import_picocolors$4.default.cyan(`Project: ${formatProjectName(projectName)}`),
4635
4635
  "",
4636
4636
  "",
4637
4637
  "",
@@ -4679,14 +4679,14 @@ const dailyCommand = define({
4679
4679
  ""
4680
4680
  ]);
4681
4681
  table.push([
4682
- import_picocolors$3.default.yellow("Total"),
4682
+ import_picocolors$4.default.yellow("Total"),
4683
4683
  "",
4684
- import_picocolors$3.default.yellow(formatNumber(totals.inputTokens)),
4685
- import_picocolors$3.default.yellow(formatNumber(totals.outputTokens)),
4686
- import_picocolors$3.default.yellow(formatNumber(totals.cacheCreationTokens)),
4687
- import_picocolors$3.default.yellow(formatNumber(totals.cacheReadTokens)),
4688
- import_picocolors$3.default.yellow(formatNumber(getTotalTokens(totals))),
4689
- import_picocolors$3.default.yellow(formatCurrency(totals.totalCost))
4684
+ import_picocolors$4.default.yellow(formatNumber(totals.inputTokens)),
4685
+ import_picocolors$4.default.yellow(formatNumber(totals.outputTokens)),
4686
+ import_picocolors$4.default.yellow(formatNumber(totals.cacheCreationTokens)),
4687
+ import_picocolors$4.default.yellow(formatNumber(totals.cacheReadTokens)),
4688
+ import_picocolors$4.default.yellow(formatNumber(getTotalTokens(totals))),
4689
+ import_picocolors$4.default.yellow(formatCurrency(totals.totalCost))
4690
4690
  ]);
4691
4691
  log(table.toString());
4692
4692
  if (table.isCompactMode()) {
@@ -5170,7 +5170,7 @@ const mcpCommand = define({
5170
5170
  }
5171
5171
  }
5172
5172
  });
5173
- var import_picocolors$2 = __toESM(require_picocolors(), 1);
5173
+ var import_picocolors$3 = __toESM(require_picocolors(), 1);
5174
5174
  const monthlyCommand = define({
5175
5175
  name: "monthly",
5176
5176
  description: "Show usage report grouped by month",
@@ -5289,14 +5289,14 @@ const monthlyCommand = define({
5289
5289
  ""
5290
5290
  ]);
5291
5291
  table.push([
5292
- import_picocolors$2.default.yellow("Total"),
5292
+ import_picocolors$3.default.yellow("Total"),
5293
5293
  "",
5294
- import_picocolors$2.default.yellow(formatNumber(totals.inputTokens)),
5295
- import_picocolors$2.default.yellow(formatNumber(totals.outputTokens)),
5296
- import_picocolors$2.default.yellow(formatNumber(totals.cacheCreationTokens)),
5297
- import_picocolors$2.default.yellow(formatNumber(totals.cacheReadTokens)),
5298
- import_picocolors$2.default.yellow(formatNumber(getTotalTokens(totals))),
5299
- import_picocolors$2.default.yellow(formatCurrency(totals.totalCost))
5294
+ import_picocolors$3.default.yellow(formatNumber(totals.inputTokens)),
5295
+ import_picocolors$3.default.yellow(formatNumber(totals.outputTokens)),
5296
+ import_picocolors$3.default.yellow(formatNumber(totals.cacheCreationTokens)),
5297
+ import_picocolors$3.default.yellow(formatNumber(totals.cacheReadTokens)),
5298
+ import_picocolors$3.default.yellow(formatNumber(getTotalTokens(totals))),
5299
+ import_picocolors$3.default.yellow(formatCurrency(totals.totalCost))
5300
5300
  ]);
5301
5301
  log(table.toString());
5302
5302
  if (table.isCompactMode()) {
@@ -5306,7 +5306,7 @@ const monthlyCommand = define({
5306
5306
  }
5307
5307
  }
5308
5308
  });
5309
- var import_picocolors$1 = __toESM(require_picocolors(), 1);
5309
+ var import_picocolors$2 = __toESM(require_picocolors(), 1);
5310
5310
  const sessionCommand = define({
5311
5311
  name: "session",
5312
5312
  description: "Show usage report grouped by conversation session",
@@ -5424,14 +5424,14 @@ const sessionCommand = define({
5424
5424
  ""
5425
5425
  ]);
5426
5426
  table.push([
5427
- import_picocolors$1.default.yellow("Total"),
5427
+ import_picocolors$2.default.yellow("Total"),
5428
5428
  "",
5429
- import_picocolors$1.default.yellow(formatNumber(totals.inputTokens)),
5430
- import_picocolors$1.default.yellow(formatNumber(totals.outputTokens)),
5431
- import_picocolors$1.default.yellow(formatNumber(totals.cacheCreationTokens)),
5432
- import_picocolors$1.default.yellow(formatNumber(totals.cacheReadTokens)),
5433
- import_picocolors$1.default.yellow(formatNumber(getTotalTokens(totals))),
5434
- import_picocolors$1.default.yellow(formatCurrency(totals.totalCost)),
5429
+ import_picocolors$2.default.yellow(formatNumber(totals.inputTokens)),
5430
+ import_picocolors$2.default.yellow(formatNumber(totals.outputTokens)),
5431
+ import_picocolors$2.default.yellow(formatNumber(totals.cacheCreationTokens)),
5432
+ import_picocolors$2.default.yellow(formatNumber(totals.cacheReadTokens)),
5433
+ import_picocolors$2.default.yellow(formatNumber(getTotalTokens(totals))),
5434
+ import_picocolors$2.default.yellow(formatCurrency(totals.totalCost)),
5435
5435
  ""
5436
5436
  ]);
5437
5437
  log(table.toString());
@@ -5442,6 +5442,121 @@ const sessionCommand = define({
5442
5442
  }
5443
5443
  }
5444
5444
  });
5445
+ const { stdin: stdin$1 } = process;
5446
+ async function getStdin() {
5447
+ let result = "";
5448
+ if (stdin$1.isTTY) return result;
5449
+ stdin$1.setEncoding("utf8");
5450
+ for await (const chunk of stdin$1) result += chunk;
5451
+ return result;
5452
+ }
5453
+ getStdin.buffer = async () => {
5454
+ const result = [];
5455
+ let length = 0;
5456
+ if (stdin$1.isTTY) return Buffer.concat([]);
5457
+ for await (const chunk of stdin$1) {
5458
+ result.push(chunk);
5459
+ length += chunk.length;
5460
+ }
5461
+ return Buffer.concat(result, length);
5462
+ };
5463
+ var import_picocolors$1 = __toESM(require_picocolors(), 1);
5464
+ /**
5465
+ /**
5466
+ * Formats the remaining time for display
5467
+ * @param remaining - Remaining minutes
5468
+ * @returns Formatted time string
5469
+ */
5470
+ function formatRemainingTime(remaining) {
5471
+ const remainingHours = Math.floor(remaining / 60);
5472
+ const remainingMins = remaining % 60;
5473
+ if (remainingHours > 0) return `${remainingHours}h ${remainingMins}m left`;
5474
+ return `${remainingMins}m left`;
5475
+ }
5476
+ const statuslineCommand = define({
5477
+ name: "statusline",
5478
+ description: "Display compact status line for Claude Code hooks (Beta)",
5479
+ args: {},
5480
+ async run() {
5481
+ logger.level = 0;
5482
+ const stdin$2 = await getStdin();
5483
+ if (stdin$2.length === 0) {
5484
+ log("❌ No input provided");
5485
+ process$1.exit(1);
5486
+ }
5487
+ const hookDataJson = JSON.parse(stdin$2.trim());
5488
+ const hookDataParseResult = statuslineHookJsonSchema.safeParse(hookDataJson);
5489
+ if (!hookDataParseResult.success) {
5490
+ log("❌ Invalid input format:", hookDataParseResult.error.message);
5491
+ process$1.exit(1);
5492
+ }
5493
+ const hookData = hookDataParseResult.data;
5494
+ const claudePaths = getClaudePaths();
5495
+ if (claudePaths.length === 0) {
5496
+ log("❌ No Claude data directory found");
5497
+ process$1.exit(1);
5498
+ }
5499
+ const sessionId = hookData.session_id;
5500
+ let sessionCost = null;
5501
+ try {
5502
+ const sessionData = await loadSessionUsageById(sessionId, { mode: "auto" });
5503
+ if (sessionData != null) sessionCost = sessionData.totalCost;
5504
+ } catch (error) {
5505
+ logger.error("Failed to load session data:", error);
5506
+ }
5507
+ const today = new Date();
5508
+ const todayStr = today.toISOString().split("T")[0];
5509
+ let todayCost = 0;
5510
+ try {
5511
+ const dailyData = await loadDailyUsageData({
5512
+ since: todayStr,
5513
+ until: todayStr,
5514
+ mode: "auto"
5515
+ });
5516
+ if (dailyData.length > 0) {
5517
+ const totals = calculateTotals(dailyData);
5518
+ todayCost = totals.totalCost;
5519
+ }
5520
+ } catch (error) {
5521
+ logger.error("Failed to load daily data:", error);
5522
+ }
5523
+ let blockInfo = "";
5524
+ let burnRateInfo = "";
5525
+ try {
5526
+ const blocks = await loadSessionBlockData({ mode: "auto" });
5527
+ if (blocks.length === 0) blockInfo = "No active block";
5528
+ else {
5529
+ const activeBlock = blocks.find((block) => {
5530
+ if (!block.isActive) return false;
5531
+ return true;
5532
+ });
5533
+ if (activeBlock != null) {
5534
+ const now = new Date();
5535
+ const remaining = Math.round((activeBlock.endTime.getTime() - now.getTime()) / (1e3 * 60));
5536
+ const blockCost = activeBlock.costUSD;
5537
+ blockInfo = `${formatCurrency(blockCost)} block (${formatRemainingTime(remaining)})`;
5538
+ const burnRate = calculateBurnRate(activeBlock);
5539
+ if (burnRate != null) {
5540
+ const costPerHour = burnRate.costPerHour;
5541
+ const costPerHourStr = `${formatCurrency(costPerHour)}/hr`;
5542
+ let coloredBurnRate = costPerHourStr;
5543
+ if (burnRate.tokensPerMinuteForIndicator < 2e3) coloredBurnRate = import_picocolors$1.default.green(costPerHourStr);
5544
+ else if (burnRate.tokensPerMinuteForIndicator < 5e3) coloredBurnRate = import_picocolors$1.default.yellow(costPerHourStr);
5545
+ else coloredBurnRate = import_picocolors$1.default.red(costPerHourStr);
5546
+ burnRateInfo = ` | 🔥 ${coloredBurnRate}`;
5547
+ }
5548
+ } else blockInfo = "No active block";
5549
+ }
5550
+ } catch (error) {
5551
+ logger.error("Failed to load block data:", error);
5552
+ blockInfo = "No active block";
5553
+ }
5554
+ const modelName = hookData.model.display_name;
5555
+ const sessionDisplay = sessionCost !== null ? formatCurrency(sessionCost) : "N/A";
5556
+ const statusLine = `🤖 ${modelName} | 💰 ${sessionDisplay} session / ${formatCurrency(todayCost)} today / ${blockInfo}${burnRateInfo}`;
5557
+ log(statusLine);
5558
+ }
5559
+ });
5445
5560
  var import_picocolors = __toESM(require_picocolors(), 1);
5446
5561
  const weeklyCommand = define({
5447
5562
  name: "weekly",
@@ -5599,6 +5714,7 @@ subCommands.set("weekly", weeklyCommand);
5599
5714
  subCommands.set("session", sessionCommand);
5600
5715
  subCommands.set("blocks", blocksCommand);
5601
5716
  subCommands.set("mcp", mcpCommand);
5717
+ subCommands.set("statusline", statuslineCommand);
5602
5718
  /**
5603
5719
  * Default command when no subcommand is specified (defaults to daily)
5604
5720
  */
@@ -951,7 +951,7 @@ function _getDefaultLogLevel() {
951
951
  }
952
952
  const consola = createConsola();
953
953
  var name = "ccusage";
954
- var version = "15.8.0";
954
+ var version = "15.9.0";
955
955
  var description = "Usage analysis tool for Claude Code";
956
956
  /**
957
957
  * Application logger instance with package name tag
package/dist/logger.js CHANGED
@@ -1,2 +1,2 @@
1
- import { log, logger } from "./logger-HOimBpSq.js";
1
+ import { log, logger } from "./logger-DxuNm8GV.js";
2
2
  export { log, logger };
@@ -1,9 +1,9 @@
1
- import { __commonJSMin, __toESM, require_usingCtx } from "./pricing-fetcher-CAYjaayN.js";
1
+ import { __commonJSMin, __toESM, require_usingCtx } from "./pricing-fetcher-S0o3dB03.js";
2
2
  import { getTotalTokens } from "./_token-utils-WjkbrjKv.js";
3
- import { ZodFirstPartyTypeKind, ZodOptional, ZodType, arrayType, booleanType, discriminatedUnionType, enumType, filterDateSchema, literalType, numberType, objectType, optionalType, recordType, stringType, unionType, unknownType } from "./_types-ed8-0BH6.js";
3
+ import { ZodFirstPartyTypeKind, ZodOptional, ZodType, arrayType, booleanType, discriminatedUnionType, enumType, filterDateSchema, literalType, numberType, objectType, optionalType, recordType, stringType, unionType, unknownType } from "./_types-B-1t4mxD.js";
4
4
  import { calculateTotals, createTotalsObject } from "./calculate-cost-BDqO4yWA.js";
5
- import { getClaudePaths, loadDailyUsageData, loadMonthlyUsageData, loadSessionBlockData, loadSessionData } from "./data-loader-DbAQLtpd.js";
6
- import { name, version } from "./logger-HOimBpSq.js";
5
+ import { getClaudePaths, loadDailyUsageData, loadMonthlyUsageData, loadSessionBlockData, loadSessionData } from "./data-loader-CKAeM9ir.js";
6
+ import { name, version } from "./logger-DxuNm8GV.js";
7
7
  import process from "node:process";
8
8
  const LATEST_PROTOCOL_VERSION = "2025-06-18";
9
9
  const SUPPORTED_PROTOCOL_VERSIONS = [
package/dist/mcp.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import "./pricing-fetcher-AYfCy7g-.js";
2
- import { LoadOptions } from "./data-loader-De3CFZ54.js";
1
+ import "./pricing-fetcher-C9P2YKDv.js";
2
+ import { LoadOptions } from "./data-loader-PvTcFbip.js";
3
3
  import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
4
4
  import { Hono } from "hono/tiny";
5
5
 
package/dist/mcp.js CHANGED
@@ -1,8 +1,8 @@
1
- import "./pricing-fetcher-CAYjaayN.js";
1
+ import "./pricing-fetcher-S0o3dB03.js";
2
2
  import "./_token-utils-WjkbrjKv.js";
3
- import "./_types-ed8-0BH6.js";
3
+ import "./_types-B-1t4mxD.js";
4
4
  import "./calculate-cost-BDqO4yWA.js";
5
- import "./data-loader-DbAQLtpd.js";
6
- import "./logger-HOimBpSq.js";
7
- import { createMcpHttpApp, createMcpServer, startMcpServerStdio } from "./mcp-DVxqAEVW.js";
5
+ import "./data-loader-CKAeM9ir.js";
6
+ import "./logger-DxuNm8GV.js";
7
+ import { createMcpHttpApp, createMcpServer, startMcpServerStdio } from "./mcp-pA-Z7D2o.js";
8
8
  export { createMcpHttpApp, createMcpServer, startMcpServerStdio };
@@ -122,6 +122,9 @@ declare const modelPricingSchema: z.ZodObject<{
122
122
  * Type definition for model pricing information
123
123
  */
124
124
  type ModelPricing = z.infer<typeof modelPricingSchema>;
125
+ /**
126
+ * Zod schema for Claude Code statusline hook JSON data
127
+ */
125
128
  //#endregion
126
129
  //#region src/pricing-fetcher.d.ts
127
130
  /**
@@ -1,5 +1,5 @@
1
- import { modelPricingSchema } from "./_types-ed8-0BH6.js";
2
- import { logger } from "./logger-HOimBpSq.js";
1
+ import { modelPricingSchema } from "./_types-B-1t4mxD.js";
2
+ import { logger } from "./logger-DxuNm8GV.js";
3
3
  import { createRequire } from "node:module";
4
4
  import path from "node:path";
5
5
  import F, { homedir } from "node:os";
@@ -406,6 +406,12 @@ var PricingFetcher = class {
406
406
  "cache_creation_input_token_cost": 1875e-8,
407
407
  "cache_read_input_token_cost": 15e-7
408
408
  },
409
+ "claude-opus-4-1": {
410
+ "input_cost_per_token": 15e-6,
411
+ "output_cost_per_token": 75e-6,
412
+ "cache_creation_input_token_cost": 1875e-8,
413
+ "cache_read_input_token_cost": 15e-7
414
+ },
409
415
  "claude-opus-4-1-20250805": {
410
416
  "input_cost_per_token": 15e-6,
411
417
  "output_cost_per_token": 75e-6,
@@ -1,2 +1,2 @@
1
- import { PricingFetcher$1 as PricingFetcher } from "./pricing-fetcher-AYfCy7g-.js";
1
+ import { PricingFetcher$1 as PricingFetcher } from "./pricing-fetcher-C9P2YKDv.js";
2
2
  export { PricingFetcher };
@@ -1,4 +1,4 @@
1
- import { PricingFetcher } from "./pricing-fetcher-CAYjaayN.js";
2
- import "./_types-ed8-0BH6.js";
3
- import "./logger-HOimBpSq.js";
1
+ import { PricingFetcher } from "./pricing-fetcher-S0o3dB03.js";
2
+ import "./_types-B-1t4mxD.js";
3
+ import "./logger-DxuNm8GV.js";
4
4
  export { PricingFetcher };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ccusage",
3
- "version": "15.8.0",
3
+ "version": "15.9.0",
4
4
  "description": "Usage analysis tool for Claude Code",
5
5
  "homepage": "https://github.com/ryoppippi/ccusage#readme",
6
6
  "bugs": {