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 +2 -0
- package/dist/{_types-ed8-0BH6.js → _types-B-1t4mxD.js} +18 -1
- package/dist/calculate-cost.d.ts +2 -2
- package/dist/calculate-cost.js +1 -1
- package/dist/{data-loader-CclfHqXI.js → data-loader-CKAeM9ir.js} +53 -8
- package/dist/{data-loader-De3CFZ54.d.ts → data-loader-PvTcFbip.d.ts} +24 -2
- package/dist/data-loader.d.ts +3 -3
- package/dist/data-loader.js +5 -5
- package/dist/{debug-B3DW8asF.js → debug-DMwiBRRn.js} +3 -3
- package/dist/debug.js +5 -5
- package/dist/index.js +217 -100
- package/dist/{logger-D8Vy4evt.js → logger-DxuNm8GV.js} +5 -1
- package/dist/logger.js +1 -1
- package/dist/{mcp-DCAyJs6a.js → mcp-pA-Z7D2o.js} +4 -4
- package/dist/mcp.d.ts +2 -2
- package/dist/mcp.js +5 -5
- package/dist/{pricing-fetcher-AYfCy7g-.d.ts → pricing-fetcher-C9P2YKDv.d.ts} +3 -0
- package/dist/{pricing-fetcher-DWqNGcYq.js → pricing-fetcher-S0o3dB03.js} +14 -2
- package/dist/pricing-fetcher.d.ts +1 -1
- package/dist/pricing-fetcher.js +3 -3
- package/package.json +1 -1
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
|
-
|
|
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 };
|
package/dist/calculate-cost.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import "./pricing-fetcher-
|
|
2
|
-
import { DailyUsage, MonthlyUsage, SessionUsage, WeeklyUsage } from "./data-loader-
|
|
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
|
|
package/dist/calculate-cost.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import { getTotalTokens } from "./_token-utils-WjkbrjKv.js";
|
|
2
|
-
import "./_types-
|
|
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-
|
|
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-
|
|
4
|
-
import { logger } from "./logger-
|
|
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
|
|
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 =
|
|
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
|
-
|
|
4107
|
+
_usingCtx5.e = _;
|
|
4063
4108
|
} finally {
|
|
4064
|
-
|
|
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-
|
|
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 };
|
package/dist/data-loader.d.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import "./pricing-fetcher-
|
|
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-
|
|
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 };
|
package/dist/data-loader.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import "./pricing-fetcher-
|
|
1
|
+
import "./pricing-fetcher-S0o3dB03.js";
|
|
2
2
|
import "./_token-utils-WjkbrjKv.js";
|
|
3
|
-
import "./_types-
|
|
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-
|
|
5
|
-
import "./logger-
|
|
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-
|
|
2
|
-
import { getClaudePaths, glob, unwrap, usageDataSchema } from "./data-loader-
|
|
3
|
-
import { logger } from "./logger-
|
|
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-
|
|
1
|
+
import "./pricing-fetcher-S0o3dB03.js";
|
|
2
2
|
import "./_token-utils-WjkbrjKv.js";
|
|
3
|
-
import "./_types-
|
|
4
|
-
import "./data-loader-
|
|
5
|
-
import "./logger-
|
|
6
|
-
import { detectMismatches, printMismatchReport } from "./debug-
|
|
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-
|
|
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-
|
|
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-
|
|
7
|
-
import { description, log, logger, name, version } from "./logger-
|
|
8
|
-
import { detectMismatches, printMismatchReport } from "./debug-
|
|
9
|
-
import { createMcpHttpApp, createMcpServer, startMcpServerStdio } from "./mcp-
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
3710
|
-
case burnRate.tokensPerMinuteForIndicator > BURN_RATE_THRESHOLDS.MODERATE: return import_picocolors$
|
|
3711
|
-
default: return import_picocolors$
|
|
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$
|
|
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$
|
|
3787
|
-
emptyChar: import_picocolors$
|
|
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$
|
|
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$
|
|
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$
|
|
3816
|
-
const sessionCol2 = `${import_picocolors$
|
|
3817
|
-
const sessionCol3 = `${import_picocolors$
|
|
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$
|
|
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$
|
|
3838
|
-
if (tokenPercent > 100) barColor = import_picocolors$
|
|
3839
|
-
else if (tokenPercent > 80) barColor = import_picocolors$
|
|
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$
|
|
3844
|
+
emptyChar: import_picocolors$7.default.gray("░"),
|
|
3844
3845
|
leftBracket: "[",
|
|
3845
3846
|
rightBracket: "]"
|
|
3846
|
-
}) : `[${import_picocolors$
|
|
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$
|
|
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$
|
|
3854
|
+
return `${import_picocolors$7.default.bold("Burn Rate:")} ${formattedRate} token/min ${rateIndicator}`;
|
|
3854
3855
|
};
|
|
3855
|
-
const usageLabel = `${drawEmoji("🔥")}${import_picocolors$
|
|
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$
|
|
3860
|
-
let usageCol2 = config.tokenLimit != null && config.tokenLimit > 0 ? `${import_picocolors$
|
|
3861
|
-
const usageCol3 = `${import_picocolors$
|
|
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$
|
|
3870
|
-
if (usageCol2.length > 0) usageCol2 = `${import_picocolors$
|
|
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$
|
|
3895
|
-
if (projectedPercent > 100) projBarColor = import_picocolors$
|
|
3896
|
-
else if (projectedPercent > 80) projBarColor = import_picocolors$
|
|
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$
|
|
3901
|
+
emptyChar: import_picocolors$7.default.gray("░"),
|
|
3901
3902
|
leftBracket: "[",
|
|
3902
3903
|
rightBracket: "]"
|
|
3903
|
-
}) : `[${import_picocolors$
|
|
3904
|
-
const limitStatus = config.tokenLimit != null && config.tokenLimit > 0 ? projectedPercent > 100 ? import_picocolors$
|
|
3905
|
-
const projLabel = `${drawEmoji("📈")}${import_picocolors$
|
|
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$
|
|
3911
|
-
let projCol2 = `${import_picocolors$
|
|
3912
|
-
const projCol3 = `${import_picocolors$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
3963
|
+
terminal.write(import_picocolors$7.default.gray(`Refresh: ${config.refreshInterval / 1e3}s | Ctrl+C: stop\n`));
|
|
3963
3964
|
}
|
|
3964
|
-
var import_picocolors$
|
|
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$
|
|
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$
|
|
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: "
|
|
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$
|
|
4248
|
-
log(`Time Remaining: ${import_picocolors$
|
|
4249
|
-
log(import_picocolors$
|
|
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$
|
|
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$
|
|
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$
|
|
4269
|
-
log(import_picocolors$
|
|
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$
|
|
4308
|
-
import_picocolors$
|
|
4309
|
-
import_picocolors$
|
|
4310
|
-
import_picocolors$
|
|
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$
|
|
4313
|
-
gapRow.push(import_picocolors$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
4341
|
+
content: import_picocolors$5.default.gray(`(assuming ${formatNumber(actualTokenLimit)} token limit)`),
|
|
4341
4342
|
hAlign: "right"
|
|
4342
4343
|
},
|
|
4343
|
-
import_picocolors$
|
|
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$
|
|
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$
|
|
4358
|
+
content: import_picocolors$5.default.gray("(assuming current burn rate)"),
|
|
4358
4359
|
hAlign: "right"
|
|
4359
4360
|
},
|
|
4360
|
-
import_picocolors$
|
|
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$
|
|
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$
|
|
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$
|
|
4682
|
+
import_picocolors$4.default.yellow("Total"),
|
|
4682
4683
|
"",
|
|
4683
|
-
import_picocolors$
|
|
4684
|
-
import_picocolors$
|
|
4685
|
-
import_picocolors$
|
|
4686
|
-
import_picocolors$
|
|
4687
|
-
import_picocolors$
|
|
4688
|
-
import_picocolors$
|
|
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$
|
|
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$
|
|
5292
|
+
import_picocolors$3.default.yellow("Total"),
|
|
5292
5293
|
"",
|
|
5293
|
-
import_picocolors$
|
|
5294
|
-
import_picocolors$
|
|
5295
|
-
import_picocolors$
|
|
5296
|
-
import_picocolors$
|
|
5297
|
-
import_picocolors$
|
|
5298
|
-
import_picocolors$
|
|
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$
|
|
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$
|
|
5427
|
+
import_picocolors$2.default.yellow("Total"),
|
|
5427
5428
|
"",
|
|
5428
|
-
import_picocolors$
|
|
5429
|
-
import_picocolors$
|
|
5430
|
-
import_picocolors$
|
|
5431
|
-
import_picocolors$
|
|
5432
|
-
import_picocolors$
|
|
5433
|
-
import_picocolors$
|
|
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.
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
6
|
-
import { name, version } from "./logger-
|
|
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-
|
|
2
|
-
import { LoadOptions } from "./data-loader-
|
|
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-
|
|
1
|
+
import "./pricing-fetcher-S0o3dB03.js";
|
|
2
2
|
import "./_token-utils-WjkbrjKv.js";
|
|
3
|
-
import "./_types-
|
|
3
|
+
import "./_types-B-1t4mxD.js";
|
|
4
4
|
import "./calculate-cost-BDqO4yWA.js";
|
|
5
|
-
import "./data-loader-
|
|
6
|
-
import "./logger-
|
|
7
|
-
import { createMcpHttpApp, createMcpServer, startMcpServerStdio } from "./mcp-
|
|
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-
|
|
2
|
-
import { logger } from "./logger-
|
|
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-
|
|
1
|
+
import { PricingFetcher$1 as PricingFetcher } from "./pricing-fetcher-C9P2YKDv.js";
|
|
2
2
|
export { PricingFetcher };
|
package/dist/pricing-fetcher.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { PricingFetcher } from "./pricing-fetcher-
|
|
2
|
-
import "./_types-
|
|
3
|
-
import "./logger-
|
|
1
|
+
import { PricingFetcher } from "./pricing-fetcher-S0o3dB03.js";
|
|
2
|
+
import "./_types-B-1t4mxD.js";
|
|
3
|
+
import "./logger-DxuNm8GV.js";
|
|
4
4
|
export { PricingFetcher };
|