ccusage 15.7.1 → 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-DWqNGcYq.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-D8Vy4evt.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-DWqNGcYq.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-CclfHqXI.js";
5
- import "./logger-D8Vy4evt.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-DWqNGcYq.js";
2
- import { getClaudePaths, glob, unwrap, usageDataSchema } from "./data-loader-CclfHqXI.js";
3
- import { logger } from "./logger-D8Vy4evt.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-DWqNGcYq.js";
1
+ import "./pricing-fetcher-S0o3dB03.js";
2
2
  import "./_token-utils-WjkbrjKv.js";
3
- import "./_types-ed8-0BH6.js";
4
- import "./data-loader-CclfHqXI.js";
5
- import "./logger-D8Vy4evt.js";
6
- import { detectMismatches, printMismatchReport } from "./debug-B3DW8asF.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-DWqNGcYq.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-CclfHqXI.js";
7
- import { description, log, logger, name, version } from "./logger-D8Vy4evt.js";
8
- import { detectMismatches, printMismatchReport } from "./debug-B3DW8asF.js";
9
- import { createMcpHttpApp, createMcpServer, startMcpServerStdio } from "./mcp-DCAyJs6a.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";
@@ -1273,6 +1273,7 @@ const sharedArgs = {
1273
1273
  },
1274
1274
  locale: {
1275
1275
  type: "string",
1276
+ short: "l",
1276
1277
  description: "Locale for date/time formatting (e.g., en-US, ja-JP, de-DE)",
1277
1278
  default: "en-CA"
1278
1279
  }
@@ -2949,7 +2950,7 @@ function stringWidth(string, options = {}) {
2949
2950
  return width;
2950
2951
  }
2951
2952
  var import_cli_table3 = __toESM(require_cli_table3(), 1);
2952
- var import_picocolors$7 = __toESM(require_picocolors(), 1);
2953
+ var import_picocolors$8 = __toESM(require_picocolors(), 1);
2953
2954
  /**
2954
2955
  * Responsive table class that adapts column widths based on terminal size
2955
2956
  * Automatically adjusts formatting and layout for different screen sizes
@@ -3185,7 +3186,7 @@ function pushBreakdownRows(table, breakdowns, extraColumns = 1, trailingColumns
3185
3186
  const row = [` └─ ${formatModelName(breakdown.modelName)}`];
3186
3187
  for (let i = 0; i < extraColumns; i++) row.push("");
3187
3188
  const totalTokens = breakdown.inputTokens + breakdown.outputTokens + breakdown.cacheCreationTokens + breakdown.cacheReadTokens;
3188
- 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)));
3189
3190
  for (let i = 0; i < trailingColumns; i++) row.push("");
3190
3191
  table.push(row);
3191
3192
  }
@@ -3699,16 +3700,16 @@ const RESTORE_CURSOR = "\x1B8";
3699
3700
  function drawEmoji(emoji) {
3700
3701
  return `${SAVE_CURSOR}${emoji}${RESTORE_CURSOR}${cursorForward(stringWidth(emoji))}`;
3701
3702
  }
3702
- var import_picocolors$6 = __toESM(require_picocolors(), 1);
3703
+ var import_picocolors$7 = __toESM(require_picocolors(), 1);
3703
3704
  /**
3704
3705
  * Get rate indicator (HIGH/MODERATE/NORMAL) based on burn rate
3705
3706
  */
3706
3707
  function getRateIndicator(burnRate) {
3707
3708
  if (burnRate == null) return "";
3708
3709
  switch (true) {
3709
- case burnRate.tokensPerMinuteForIndicator > BURN_RATE_THRESHOLDS.HIGH: return import_picocolors$6.default.red(`${drawEmoji("⚡")} HIGH`);
3710
- case burnRate.tokensPerMinuteForIndicator > BURN_RATE_THRESHOLDS.MODERATE: return import_picocolors$6.default.yellow(`${drawEmoji("⚡")} MODERATE`);
3711
- 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`);
3712
3713
  }
3713
3714
  }
3714
3715
  /**
@@ -3725,7 +3726,7 @@ async function renderWaitingState(terminal, config, signal) {
3725
3726
  terminal.startBuffering();
3726
3727
  terminal.write(cursorTo(0, 0));
3727
3728
  terminal.write(eraseDown);
3728
- 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"));
3729
3730
  terminal.write(cursorHide);
3730
3731
  terminal.flush();
3731
3732
  await delayWithAbort(config.refreshInterval, signal);
@@ -3783,8 +3784,8 @@ function renderLiveDisplay(terminal, block, config) {
3783
3784
  const barWidth = boxWidth - labelWidth - maxRightTextWidth - spacing - boxPadding;
3784
3785
  const sessionProgressBar = createProgressBar(elapsed, sessionDuration, barWidth, {
3785
3786
  showPercentage: false,
3786
- fillChar: import_picocolors$6.default.cyan("█"),
3787
- emptyChar: import_picocolors$6.default.gray("░"),
3787
+ fillChar: import_picocolors$7.default.cyan("█"),
3788
+ emptyChar: import_picocolors$7.default.gray("░"),
3788
3789
  leftBracket: "[",
3789
3790
  rightBracket: "]"
3790
3791
  });
@@ -3804,17 +3805,17 @@ function renderLiveDisplay(terminal, block, config) {
3804
3805
  const detailsSpacing = 2;
3805
3806
  const detailsAvailableWidth = boxWidth - 3 - detailsIndent;
3806
3807
  terminal.write(`${marginStr}┌${"─".repeat(boxWidth - 2)}┐\n`);
3807
- 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`);
3808
3809
  terminal.write(`${marginStr}├${"─".repeat(boxWidth - 2)}┤\n`);
3809
3810
  terminal.write(`${marginStr}│${" ".repeat(boxWidth - 2)}│\n`);
3810
- const sessionLabel = `${drawEmoji("⏱️")}${import_picocolors$6.default.bold(" SESSION")}`;
3811
+ const sessionLabel = `${drawEmoji("⏱️")}${import_picocolors$7.default.bold(" SESSION")}`;
3811
3812
  const sessionLabelWidth = stringWidth(sessionLabel);
3812
3813
  const sessionBarStr = `${sessionLabel}${"".padEnd(Math.max(0, labelWidth - sessionLabelWidth))} ${sessionProgressBar} ${sessionRightText}`;
3813
3814
  const sessionBarPadded = sessionBarStr + " ".repeat(Math.max(0, boxWidth - 3 - stringWidth(sessionBarStr)));
3814
3815
  terminal.write(`${marginStr}│ ${sessionBarPadded}│\n`);
3815
- const sessionCol1 = `${import_picocolors$6.default.gray("Started:")} ${startTime}`;
3816
- const sessionCol2 = `${import_picocolors$6.default.gray("Elapsed:")} ${prettyMilliseconds(elapsed * 60 * 1e3, { compact: true })}`;
3817
- 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})`;
3818
3819
  let sessionDetails = `${" ".repeat(detailsIndent)}${sessionCol1}${" ".repeat(detailsSpacing)}${sessionCol2}${" ".repeat(detailsSpacing)}${sessionCol3}`;
3819
3820
  const sessionDetailsWidth = stringWidth(sessionCol1) + stringWidth(sessionCol2) + stringWidth(sessionCol3) + detailsSpacing * 2;
3820
3821
  if (sessionDetailsWidth > detailsAvailableWidth) sessionDetails = `${" ".repeat(detailsIndent)}${sessionCol1}${" ".repeat(detailsSpacing)}${sessionCol3}`;
@@ -3826,7 +3827,7 @@ function renderLiveDisplay(terminal, block, config) {
3826
3827
  minute: "2-digit",
3827
3828
  hour12: true
3828
3829
  }) ?? null;
3829
- 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}`) : "";
3830
3831
  usageLimitResetTimePadded = resetTime !== null ? usageLimitResetTime + " ".repeat(Math.max(0, boxWidth - 3 - stringWidth(usageLimitResetTime))) : null;
3831
3832
  }
3832
3833
  terminal.write(`${marginStr}│ ${sessionDetailsPadded}│\n`);
@@ -3834,31 +3835,31 @@ function renderLiveDisplay(terminal, block, config) {
3834
3835
  terminal.write(`${marginStr}│${" ".repeat(boxWidth - 2)}│\n`);
3835
3836
  terminal.write(`${marginStr}├${"─".repeat(boxWidth - 2)}┤\n`);
3836
3837
  terminal.write(`${marginStr}│${" ".repeat(boxWidth - 2)}│\n`);
3837
- let barColor = import_picocolors$6.default.green;
3838
- if (tokenPercent > 100) barColor = import_picocolors$6.default.red;
3839
- 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;
3840
3841
  const usageBar = config.tokenLimit != null && config.tokenLimit > 0 ? createProgressBar(totalTokens, config.tokenLimit, barWidth, {
3841
3842
  showPercentage: false,
3842
3843
  fillChar: barColor("█"),
3843
- emptyChar: import_picocolors$6.default.gray("░"),
3844
+ emptyChar: import_picocolors$7.default.gray("░"),
3844
3845
  leftBracket: "[",
3845
3846
  rightBracket: "]"
3846
- }) : `[${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)))}]`;
3847
3848
  const burnRate = calculateBurnRate(block);
3848
3849
  const rateIndicator = getRateIndicator(burnRate);
3849
3850
  const buildRateDisplay = (useShort) => {
3850
- 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`;
3851
3852
  const rateValue = Math.round(burnRate.tokensPerMinute);
3852
3853
  const formattedRate = useShort ? formatTokensShort(rateValue) : formatNumber(rateValue);
3853
- 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}`;
3854
3855
  };
3855
- const usageLabel = `${drawEmoji("🔥")}${import_picocolors$6.default.bold(" USAGE")}`;
3856
+ const usageLabel = `${drawEmoji("🔥")}${import_picocolors$7.default.bold(" USAGE")}`;
3856
3857
  const usageLabelWidth = stringWidth(usageLabel);
3857
3858
  const usageBarStr = `${usageLabel}${"".padEnd(Math.max(0, labelWidth - usageLabelWidth))} ${usageBar} ${usageRightText}`;
3858
3859
  let rateDisplay = buildRateDisplay(false);
3859
- let usageCol1 = `${import_picocolors$6.default.gray("Tokens:")} ${formatTokenDisplay(totalTokens, false)} (${rateDisplay})`;
3860
- let usageCol2 = config.tokenLimit != null && config.tokenLimit > 0 ? `${import_picocolors$6.default.gray("Limit:")} ${formatTokenDisplay(config.tokenLimit, false)} tokens` : "";
3861
- 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)}`;
3862
3863
  let totalWidth = stringWidth(usageCol1);
3863
3864
  if (usageCol2.length > 0) totalWidth += detailsSpacing + stringWidth(usageCol2);
3864
3865
  totalWidth += detailsSpacing + stringWidth(usageCol3);
@@ -3866,8 +3867,8 @@ function renderLiveDisplay(terminal, block, config) {
3866
3867
  if (totalWidth > detailsAvailableWidth) {
3867
3868
  useTwoLineLayout = true;
3868
3869
  rateDisplay = buildRateDisplay(true);
3869
- usageCol1 = `${import_picocolors$6.default.gray("Tokens:")} ${formatTokenDisplay(totalTokens, true)} (${rateDisplay})`;
3870
- 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`;
3871
3872
  }
3872
3873
  const usageBarPadded = usageBarStr + " ".repeat(Math.max(0, boxWidth - 3 - stringWidth(usageBarStr)));
3873
3874
  terminal.write(`${marginStr}│ ${usageBarPadded}│\n`);
@@ -3891,30 +3892,30 @@ function renderLiveDisplay(terminal, block, config) {
3891
3892
  terminal.write(`${marginStr}├${"─".repeat(boxWidth - 2)}┤\n`);
3892
3893
  terminal.write(`${marginStr}│${" ".repeat(boxWidth - 2)}│\n`);
3893
3894
  if (projection != null) {
3894
- let projBarColor = import_picocolors$6.default.green;
3895
- if (projectedPercent > 100) projBarColor = import_picocolors$6.default.red;
3896
- 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;
3897
3898
  const projectionBar = config.tokenLimit != null && config.tokenLimit > 0 ? createProgressBar(projection.totalTokens, config.tokenLimit, barWidth, {
3898
3899
  showPercentage: false,
3899
3900
  fillChar: projBarColor("█"),
3900
- emptyChar: import_picocolors$6.default.gray("░"),
3901
+ emptyChar: import_picocolors$7.default.gray("░"),
3901
3902
  leftBracket: "[",
3902
3903
  rightBracket: "]"
3903
- }) : `[${import_picocolors$6.default.green("█".repeat(Math.floor(barWidth * .15)))}${import_picocolors$6.default.gray("░".repeat(barWidth - Math.floor(barWidth * .15)))}]`;
3904
- 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`);
3905
- 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")}`;
3906
3907
  const projLabelWidth = stringWidth(projLabel);
3907
3908
  const projBarStr = `${projLabel}${"".padEnd(Math.max(0, labelWidth - projLabelWidth))} ${projectionBar} ${projectionRightText}`;
3908
3909
  const projBarPadded = projBarStr + " ".repeat(Math.max(0, boxWidth - 3 - stringWidth(projBarStr)));
3909
3910
  terminal.write(`${marginStr}│ ${projBarPadded}│\n`);
3910
- const projCol1 = `${import_picocolors$6.default.gray("Status:")} ${limitStatus}`;
3911
- let projCol2 = `${import_picocolors$6.default.gray("Tokens:")} ${formatTokenDisplay(projection.totalTokens, false)}`;
3912
- 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)}`;
3913
3914
  const projTotalWidth = stringWidth(projCol1) + stringWidth(projCol2) + stringWidth(projCol3) + detailsSpacing * 2;
3914
3915
  let projUseTwoLineLayout = false;
3915
3916
  if (projTotalWidth > detailsAvailableWidth) {
3916
3917
  projUseTwoLineLayout = true;
3917
- projCol2 = `${import_picocolors$6.default.gray("Tokens:")} ${formatTokenDisplay(projection.totalTokens, true)}`;
3918
+ projCol2 = `${import_picocolors$7.default.gray("Tokens:")} ${formatTokenDisplay(projection.totalTokens, true)}`;
3918
3919
  }
3919
3920
  if (projUseTwoLineLayout) {
3920
3921
  const projDetailsLine1 = `${" ".repeat(detailsIndent)}${projCol1}`;
@@ -3938,7 +3939,7 @@ function renderLiveDisplay(terminal, block, config) {
3938
3939
  }
3939
3940
  terminal.write(`${marginStr}├${"─".repeat(boxWidth - 2)}┤\n`);
3940
3941
  const refreshText = `${drawEmoji("↻")} Refreshing every ${config.refreshInterval / 1e3}s • Press Ctrl+C to stop`;
3941
- 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`);
3942
3943
  terminal.write(`${marginStr}└${"─".repeat(boxWidth - 2)}┘\n`);
3943
3944
  }
3944
3945
  /**
@@ -3946,22 +3947,22 @@ function renderLiveDisplay(terminal, block, config) {
3946
3947
  */
3947
3948
  function renderCompactLiveDisplay(terminal, block, config, totalTokens, elapsed, remaining) {
3948
3949
  const width = terminal.width;
3949
- 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`);
3950
3951
  terminal.write(`${"─".repeat(width)}\n`);
3951
3952
  const sessionPercent = elapsed / (elapsed + remaining) * 100;
3952
3953
  terminal.write(`Session: ${sessionPercent.toFixed(1)}% (${Math.floor(elapsed / 60)}h ${Math.floor(elapsed % 60)}m)\n`);
3953
3954
  if (config.tokenLimit != null && config.tokenLimit > 0) {
3954
3955
  const tokenPercent = totalTokens / config.tokenLimit * 100;
3955
- 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");
3956
3957
  terminal.write(`Tokens: ${formatNumber(totalTokens)}/${formatNumber(config.tokenLimit)} ${status}\n`);
3957
3958
  } else terminal.write(`Tokens: ${formatNumber(totalTokens)}\n`);
3958
3959
  terminal.write(`Cost: ${formatCurrency(block.costUSD)}\n`);
3959
3960
  const burnRate = calculateBurnRate(block);
3960
3961
  if (burnRate != null) terminal.write(`Rate: ${formatNumber(burnRate.tokensPerMinute)}/min\n`);
3961
3962
  terminal.write(`${"─".repeat(width)}\n`);
3962
- 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`));
3963
3964
  }
3964
- var import_picocolors$5 = __toESM(require_picocolors(), 1);
3965
+ var import_picocolors$6 = __toESM(require_picocolors(), 1);
3965
3966
  var import_usingCtx = __toESM(require_usingCtx(), 1);
3966
3967
  async function startLiveMonitoring(config) {
3967
3968
  try {
@@ -4024,7 +4025,7 @@ async function startLiveMonitoring(config) {
4024
4025
  const errorMessage = error instanceof Error ? error.message : String(error);
4025
4026
  terminal.startBuffering();
4026
4027
  terminal.clearScreen();
4027
- terminal.write(import_picocolors$5.default.red(`Error: ${errorMessage}\n`));
4028
+ terminal.write(import_picocolors$6.default.red(`Error: ${errorMessage}\n`));
4028
4029
  terminal.flush();
4029
4030
  logger.error(`Live monitoring error: ${errorMessage}`);
4030
4031
  await delayWithAbort(config.refreshInterval, abortController.signal).catch(() => {});
@@ -4035,7 +4036,7 @@ async function startLiveMonitoring(config) {
4035
4036
  _usingCtx.d();
4036
4037
  }
4037
4038
  }
4038
- var import_picocolors$4 = __toESM(require_picocolors(), 1);
4039
+ var import_picocolors$5 = __toESM(require_picocolors(), 1);
4039
4040
  /**
4040
4041
  * Formats the time display for a session block
4041
4042
  * @param block - Session block to format
@@ -4120,7 +4121,7 @@ const blocksCommand = define({
4120
4121
  },
4121
4122
  sessionLength: {
4122
4123
  type: "number",
4123
- short: "l",
4124
+ short: "n",
4124
4125
  description: `Session block duration in hours (default: ${DEFAULT_SESSION_DURATION_HOURS})`,
4125
4126
  default: DEFAULT_SESSION_DURATION_HOURS
4126
4127
  },
@@ -4244,19 +4245,19 @@ const blocksCommand = define({
4244
4245
  const now = new Date();
4245
4246
  const elapsed = Math.round((now.getTime() - block.startTime.getTime()) / (1e3 * 60));
4246
4247
  const remaining = Math.round((block.endTime.getTime() - now.getTime()) / (1e3 * 60));
4247
- 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)`);
4248
- log(`Time Remaining: ${import_picocolors$4.default.green(`${Math.floor(remaining / 60)}h ${remaining % 60}m`)}\n`);
4249
- 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:"));
4250
4251
  log(` Input Tokens: ${formatNumber(block.tokenCounts.inputTokens)}`);
4251
4252
  log(` Output Tokens: ${formatNumber(block.tokenCounts.outputTokens)}`);
4252
4253
  log(` Total Cost: ${formatCurrency(block.costUSD)}\n`);
4253
4254
  if (burnRate != null) {
4254
- log(import_picocolors$4.default.bold("Burn Rate:"));
4255
+ log(import_picocolors$5.default.bold("Burn Rate:"));
4255
4256
  log(` Tokens/minute: ${formatNumber(burnRate.tokensPerMinute)}`);
4256
4257
  log(` Cost/hour: ${formatCurrency(burnRate.costPerHour)}\n`);
4257
4258
  }
4258
4259
  if (projection != null) {
4259
- 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):"));
4260
4261
  log(` Total Tokens: ${formatNumber(projection.totalTokens)}`);
4261
4262
  log(` Total Cost: ${formatCurrency(projection.totalCost)}\n`);
4262
4263
  if (ctx.values.tokenLimit != null) {
@@ -4265,8 +4266,8 @@ const blocksCommand = define({
4265
4266
  const currentTokens = getTotalTokens(block.tokenCounts);
4266
4267
  const remainingTokens = Math.max(0, limit - currentTokens);
4267
4268
  const percentUsed = projection.totalTokens / limit * 100;
4268
- 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");
4269
- 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:"));
4270
4271
  log(` Limit: ${formatNumber(limit)} tokens`);
4271
4272
  log(` Current Usage: ${formatNumber(currentTokens)} (${(currentTokens / limit * 100).toFixed(1)}%)`);
4272
4273
  log(` Remaining: ${formatNumber(remainingTokens)} tokens`);
@@ -4304,17 +4305,17 @@ const blocksCommand = define({
4304
4305
  const useCompactFormat = terminalWidth < BLOCKS_COMPACT_WIDTH_THRESHOLD;
4305
4306
  for (const block of blocks) if (block.isGap ?? false) {
4306
4307
  const gapRow = [
4307
- import_picocolors$4.default.gray(formatBlockTime(block, useCompactFormat, ctx.values.locale)),
4308
- import_picocolors$4.default.gray("(inactive)"),
4309
- import_picocolors$4.default.gray("-"),
4310
- 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("-")
4311
4312
  ];
4312
- if (actualTokenLimit != null && actualTokenLimit > 0) gapRow.push(import_picocolors$4.default.gray("-"));
4313
- 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("-"));
4314
4315
  table.push(gapRow);
4315
4316
  } else {
4316
4317
  const totalTokens = getTotalTokens(block.tokenCounts);
4317
- const status = block.isActive ? import_picocolors$4.default.green("ACTIVE") : "";
4318
+ const status = block.isActive ? import_picocolors$5.default.green("ACTIVE") : "";
4318
4319
  const row = [
4319
4320
  formatBlockTime(block, useCompactFormat, ctx.values.locale),
4320
4321
  status,
@@ -4324,7 +4325,7 @@ const blocksCommand = define({
4324
4325
  if (actualTokenLimit != null && actualTokenLimit > 0) {
4325
4326
  const percentage = totalTokens / actualTokenLimit * 100;
4326
4327
  const percentText = `${percentage.toFixed(1)}%`;
4327
- row.push(percentage > 100 ? import_picocolors$4.default.red(percentText) : percentText);
4328
+ row.push(percentage > 100 ? import_picocolors$5.default.red(percentText) : percentText);
4328
4329
  }
4329
4330
  row.push(formatCurrency(block.costUSD));
4330
4331
  table.push(row);
@@ -4332,15 +4333,15 @@ const blocksCommand = define({
4332
4333
  if (actualTokenLimit != null && actualTokenLimit > 0) {
4333
4334
  const currentTokens = getTotalTokens(block.tokenCounts);
4334
4335
  const remainingTokens = Math.max(0, actualTokenLimit - currentTokens);
4335
- 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");
4336
4337
  const remainingPercent = (actualTokenLimit - currentTokens) / actualTokenLimit * 100;
4337
- 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%");
4338
4339
  const remainingRow = [
4339
4340
  {
4340
- content: import_picocolors$4.default.gray(`(assuming ${formatNumber(actualTokenLimit)} token limit)`),
4341
+ content: import_picocolors$5.default.gray(`(assuming ${formatNumber(actualTokenLimit)} token limit)`),
4341
4342
  hAlign: "right"
4342
4343
  },
4343
- import_picocolors$4.default.blue("REMAINING"),
4344
+ import_picocolors$5.default.blue("REMAINING"),
4344
4345
  "",
4345
4346
  remainingText,
4346
4347
  remainingPercentText,
@@ -4351,13 +4352,13 @@ const blocksCommand = define({
4351
4352
  const projection = projectBlockUsage(block);
4352
4353
  if (projection != null) {
4353
4354
  const projectedTokens = formatNumber(projection.totalTokens);
4354
- 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;
4355
4356
  const projectedRow = [
4356
4357
  {
4357
- content: import_picocolors$4.default.gray("(assuming current burn rate)"),
4358
+ content: import_picocolors$5.default.gray("(assuming current burn rate)"),
4358
4359
  hAlign: "right"
4359
4360
  },
4360
- import_picocolors$4.default.yellow("PROJECTED"),
4361
+ import_picocolors$5.default.yellow("PROJECTED"),
4361
4362
  "",
4362
4363
  projectedText
4363
4364
  ];
@@ -4512,7 +4513,7 @@ function formatProjectName(projectName) {
4512
4513
  if (aliases.has(parsed)) return aliases.get(parsed);
4513
4514
  return parsed;
4514
4515
  }
4515
- var import_picocolors$3 = __toESM(require_picocolors(), 1);
4516
+ var import_picocolors$4 = __toESM(require_picocolors(), 1);
4516
4517
  const dailyCommand = define({
4517
4518
  name: "daily",
4518
4519
  description: "Show usage report grouped by date",
@@ -4630,7 +4631,7 @@ const dailyCommand = define({
4630
4631
  ""
4631
4632
  ]);
4632
4633
  table.push([
4633
- import_picocolors$3.default.cyan(`Project: ${formatProjectName(projectName)}`),
4634
+ import_picocolors$4.default.cyan(`Project: ${formatProjectName(projectName)}`),
4634
4635
  "",
4635
4636
  "",
4636
4637
  "",
@@ -4678,14 +4679,14 @@ const dailyCommand = define({
4678
4679
  ""
4679
4680
  ]);
4680
4681
  table.push([
4681
- import_picocolors$3.default.yellow("Total"),
4682
+ import_picocolors$4.default.yellow("Total"),
4682
4683
  "",
4683
- import_picocolors$3.default.yellow(formatNumber(totals.inputTokens)),
4684
- import_picocolors$3.default.yellow(formatNumber(totals.outputTokens)),
4685
- import_picocolors$3.default.yellow(formatNumber(totals.cacheCreationTokens)),
4686
- import_picocolors$3.default.yellow(formatNumber(totals.cacheReadTokens)),
4687
- import_picocolors$3.default.yellow(formatNumber(getTotalTokens(totals))),
4688
- 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))
4689
4690
  ]);
4690
4691
  log(table.toString());
4691
4692
  if (table.isCompactMode()) {
@@ -5169,7 +5170,7 @@ const mcpCommand = define({
5169
5170
  }
5170
5171
  }
5171
5172
  });
5172
- var import_picocolors$2 = __toESM(require_picocolors(), 1);
5173
+ var import_picocolors$3 = __toESM(require_picocolors(), 1);
5173
5174
  const monthlyCommand = define({
5174
5175
  name: "monthly",
5175
5176
  description: "Show usage report grouped by month",
@@ -5288,14 +5289,14 @@ const monthlyCommand = define({
5288
5289
  ""
5289
5290
  ]);
5290
5291
  table.push([
5291
- import_picocolors$2.default.yellow("Total"),
5292
+ import_picocolors$3.default.yellow("Total"),
5292
5293
  "",
5293
- import_picocolors$2.default.yellow(formatNumber(totals.inputTokens)),
5294
- import_picocolors$2.default.yellow(formatNumber(totals.outputTokens)),
5295
- import_picocolors$2.default.yellow(formatNumber(totals.cacheCreationTokens)),
5296
- import_picocolors$2.default.yellow(formatNumber(totals.cacheReadTokens)),
5297
- import_picocolors$2.default.yellow(formatNumber(getTotalTokens(totals))),
5298
- 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))
5299
5300
  ]);
5300
5301
  log(table.toString());
5301
5302
  if (table.isCompactMode()) {
@@ -5305,7 +5306,7 @@ const monthlyCommand = define({
5305
5306
  }
5306
5307
  }
5307
5308
  });
5308
- var import_picocolors$1 = __toESM(require_picocolors(), 1);
5309
+ var import_picocolors$2 = __toESM(require_picocolors(), 1);
5309
5310
  const sessionCommand = define({
5310
5311
  name: "session",
5311
5312
  description: "Show usage report grouped by conversation session",
@@ -5423,14 +5424,14 @@ const sessionCommand = define({
5423
5424
  ""
5424
5425
  ]);
5425
5426
  table.push([
5426
- import_picocolors$1.default.yellow("Total"),
5427
+ import_picocolors$2.default.yellow("Total"),
5427
5428
  "",
5428
- import_picocolors$1.default.yellow(formatNumber(totals.inputTokens)),
5429
- import_picocolors$1.default.yellow(formatNumber(totals.outputTokens)),
5430
- import_picocolors$1.default.yellow(formatNumber(totals.cacheCreationTokens)),
5431
- import_picocolors$1.default.yellow(formatNumber(totals.cacheReadTokens)),
5432
- import_picocolors$1.default.yellow(formatNumber(getTotalTokens(totals))),
5433
- 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)),
5434
5435
  ""
5435
5436
  ]);
5436
5437
  log(table.toString());
@@ -5441,6 +5442,121 @@ const sessionCommand = define({
5441
5442
  }
5442
5443
  }
5443
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
+ });
5444
5560
  var import_picocolors = __toESM(require_picocolors(), 1);
5445
5561
  const weeklyCommand = define({
5446
5562
  name: "weekly",
@@ -5598,6 +5714,7 @@ subCommands.set("weekly", weeklyCommand);
5598
5714
  subCommands.set("session", sessionCommand);
5599
5715
  subCommands.set("blocks", blocksCommand);
5600
5716
  subCommands.set("mcp", mcpCommand);
5717
+ subCommands.set("statusline", statuslineCommand);
5601
5718
  /**
5602
5719
  * Default command when no subcommand is specified (defaults to daily)
5603
5720
  */
@@ -951,12 +951,16 @@ function _getDefaultLogLevel() {
951
951
  }
952
952
  const consola = createConsola();
953
953
  var name = "ccusage";
954
- var version = "15.7.1";
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
958
958
  */
959
959
  const logger = consola.withTag(name);
960
+ if (process$1.env.LOG_LEVEL != null) {
961
+ const level = Number.parseInt(process$1.env.LOG_LEVEL, 10);
962
+ if (!Number.isNaN(level)) logger.level = level;
963
+ }
960
964
  /**
961
965
  * Direct console.log function for cases where logger formatting is not desired
962
966
  */
package/dist/logger.js CHANGED
@@ -1,2 +1,2 @@
1
- import { log, logger } from "./logger-D8Vy4evt.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-DWqNGcYq.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-CclfHqXI.js";
6
- import { name, version } from "./logger-D8Vy4evt.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-DWqNGcYq.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-CclfHqXI.js";
6
- import "./logger-D8Vy4evt.js";
7
- import { createMcpHttpApp, createMcpServer, startMcpServerStdio } from "./mcp-DCAyJs6a.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-D8Vy4evt.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,18 @@ 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
+ },
415
+ "claude-opus-4-1-20250805": {
416
+ "input_cost_per_token": 15e-6,
417
+ "output_cost_per_token": 75e-6,
418
+ "cache_creation_input_token_cost": 1875e-8,
419
+ "cache_read_input_token_cost": 15e-7
420
+ },
409
421
  "claude-sonnet-4-20250514": {
410
422
  "input_cost_per_token": 3e-6,
411
423
  "output_cost_per_token": 15e-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-DWqNGcYq.js";
2
- import "./_types-ed8-0BH6.js";
3
- import "./logger-D8Vy4evt.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.7.1",
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": {