ccusage 15.8.0 → 15.9.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +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-DbAQLtpd.js → data-loader-D3wQxjrt.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-jL56ZeA8.js → debug-Dz_xcM_P.js} +3 -3
- package/dist/debug.js +5 -5
- package/dist/index.js +215 -99
- package/dist/{logger-HOimBpSq.js → logger-BODy31tA.js} +1 -1
- package/dist/logger.js +1 -1
- package/dist/{mcp-DVxqAEVW.js → mcp-opivOm8q.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-CAYjaayN.js → pricing-fetcher-DtGb7sbF.js} +8 -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-DtGb7sbF.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-BODy31tA.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-DtGb7sbF.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-D3wQxjrt.js";
|
|
5
|
+
import "./logger-BODy31tA.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-DtGb7sbF.js";
|
|
2
|
+
import { getClaudePaths, glob, unwrap, usageDataSchema } from "./data-loader-D3wQxjrt.js";
|
|
3
|
+
import { logger } from "./logger-BODy31tA.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-DtGb7sbF.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-D3wQxjrt.js";
|
|
5
|
+
import "./logger-BODy31tA.js";
|
|
6
|
+
import { detectMismatches, printMismatchReport } from "./debug-Dz_xcM_P.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-DtGb7sbF.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-D3wQxjrt.js";
|
|
7
|
+
import { description, log, logger, name, version } from "./logger-BODy31tA.js";
|
|
8
|
+
import { detectMismatches, printMismatchReport } from "./debug-Dz_xcM_P.js";
|
|
9
|
+
import { createMcpHttpApp, createMcpServer, startMcpServerStdio } from "./mcp-opivOm8q.js";
|
|
10
10
|
import { readFile } from "node:fs/promises";
|
|
11
11
|
import process$1 from "node:process";
|
|
12
12
|
import { createServer } from "node:http";
|
|
@@ -2950,7 +2950,7 @@ function stringWidth(string, options = {}) {
|
|
|
2950
2950
|
return width;
|
|
2951
2951
|
}
|
|
2952
2952
|
var import_cli_table3 = __toESM(require_cli_table3(), 1);
|
|
2953
|
-
var import_picocolors$
|
|
2953
|
+
var import_picocolors$8 = __toESM(require_picocolors(), 1);
|
|
2954
2954
|
/**
|
|
2955
2955
|
* Responsive table class that adapts column widths based on terminal size
|
|
2956
2956
|
* Automatically adjusts formatting and layout for different screen sizes
|
|
@@ -3186,7 +3186,7 @@ function pushBreakdownRows(table, breakdowns, extraColumns = 1, trailingColumns
|
|
|
3186
3186
|
const row = [` └─ ${formatModelName(breakdown.modelName)}`];
|
|
3187
3187
|
for (let i = 0; i < extraColumns; i++) row.push("");
|
|
3188
3188
|
const totalTokens = breakdown.inputTokens + breakdown.outputTokens + breakdown.cacheCreationTokens + breakdown.cacheReadTokens;
|
|
3189
|
-
row.push(import_picocolors$
|
|
3189
|
+
row.push(import_picocolors$8.default.gray(formatNumber(breakdown.inputTokens)), import_picocolors$8.default.gray(formatNumber(breakdown.outputTokens)), import_picocolors$8.default.gray(formatNumber(breakdown.cacheCreationTokens)), import_picocolors$8.default.gray(formatNumber(breakdown.cacheReadTokens)), import_picocolors$8.default.gray(formatNumber(totalTokens)), import_picocolors$8.default.gray(formatCurrency(breakdown.cost)));
|
|
3190
3190
|
for (let i = 0; i < trailingColumns; i++) row.push("");
|
|
3191
3191
|
table.push(row);
|
|
3192
3192
|
}
|
|
@@ -3700,16 +3700,16 @@ const RESTORE_CURSOR = "\x1B8";
|
|
|
3700
3700
|
function drawEmoji(emoji) {
|
|
3701
3701
|
return `${SAVE_CURSOR}${emoji}${RESTORE_CURSOR}${cursorForward(stringWidth(emoji))}`;
|
|
3702
3702
|
}
|
|
3703
|
-
var import_picocolors$
|
|
3703
|
+
var import_picocolors$7 = __toESM(require_picocolors(), 1);
|
|
3704
3704
|
/**
|
|
3705
3705
|
* Get rate indicator (HIGH/MODERATE/NORMAL) based on burn rate
|
|
3706
3706
|
*/
|
|
3707
3707
|
function getRateIndicator(burnRate) {
|
|
3708
3708
|
if (burnRate == null) return "";
|
|
3709
3709
|
switch (true) {
|
|
3710
|
-
case burnRate.tokensPerMinuteForIndicator > BURN_RATE_THRESHOLDS.HIGH: return import_picocolors$
|
|
3711
|
-
case burnRate.tokensPerMinuteForIndicator > BURN_RATE_THRESHOLDS.MODERATE: return import_picocolors$
|
|
3712
|
-
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`);
|
|
3713
3713
|
}
|
|
3714
3714
|
}
|
|
3715
3715
|
/**
|
|
@@ -3726,7 +3726,7 @@ async function renderWaitingState(terminal, config, signal) {
|
|
|
3726
3726
|
terminal.startBuffering();
|
|
3727
3727
|
terminal.write(cursorTo(0, 0));
|
|
3728
3728
|
terminal.write(eraseDown);
|
|
3729
|
-
terminal.write(import_picocolors$
|
|
3729
|
+
terminal.write(import_picocolors$7.default.yellow("No active session block found. Waiting...\n"));
|
|
3730
3730
|
terminal.write(cursorHide);
|
|
3731
3731
|
terminal.flush();
|
|
3732
3732
|
await delayWithAbort(config.refreshInterval, signal);
|
|
@@ -3784,8 +3784,8 @@ function renderLiveDisplay(terminal, block, config) {
|
|
|
3784
3784
|
const barWidth = boxWidth - labelWidth - maxRightTextWidth - spacing - boxPadding;
|
|
3785
3785
|
const sessionProgressBar = createProgressBar(elapsed, sessionDuration, barWidth, {
|
|
3786
3786
|
showPercentage: false,
|
|
3787
|
-
fillChar: import_picocolors$
|
|
3788
|
-
emptyChar: import_picocolors$
|
|
3787
|
+
fillChar: import_picocolors$7.default.cyan("█"),
|
|
3788
|
+
emptyChar: import_picocolors$7.default.gray("░"),
|
|
3789
3789
|
leftBracket: "[",
|
|
3790
3790
|
rightBracket: "]"
|
|
3791
3791
|
});
|
|
@@ -3805,17 +3805,17 @@ function renderLiveDisplay(terminal, block, config) {
|
|
|
3805
3805
|
const detailsSpacing = 2;
|
|
3806
3806
|
const detailsAvailableWidth = boxWidth - 3 - detailsIndent;
|
|
3807
3807
|
terminal.write(`${marginStr}┌${"─".repeat(boxWidth - 2)}┐\n`);
|
|
3808
|
-
terminal.write(`${marginStr}│${import_picocolors$
|
|
3808
|
+
terminal.write(`${marginStr}│${import_picocolors$7.default.bold(centerText("CLAUDE CODE - LIVE TOKEN USAGE MONITOR", boxWidth - 2))}│\n`);
|
|
3809
3809
|
terminal.write(`${marginStr}├${"─".repeat(boxWidth - 2)}┤\n`);
|
|
3810
3810
|
terminal.write(`${marginStr}│${" ".repeat(boxWidth - 2)}│\n`);
|
|
3811
|
-
const sessionLabel = `${drawEmoji("⏱️")}${import_picocolors$
|
|
3811
|
+
const sessionLabel = `${drawEmoji("⏱️")}${import_picocolors$7.default.bold(" SESSION")}`;
|
|
3812
3812
|
const sessionLabelWidth = stringWidth(sessionLabel);
|
|
3813
3813
|
const sessionBarStr = `${sessionLabel}${"".padEnd(Math.max(0, labelWidth - sessionLabelWidth))} ${sessionProgressBar} ${sessionRightText}`;
|
|
3814
3814
|
const sessionBarPadded = sessionBarStr + " ".repeat(Math.max(0, boxWidth - 3 - stringWidth(sessionBarStr)));
|
|
3815
3815
|
terminal.write(`${marginStr}│ ${sessionBarPadded}│\n`);
|
|
3816
|
-
const sessionCol1 = `${import_picocolors$
|
|
3817
|
-
const sessionCol2 = `${import_picocolors$
|
|
3818
|
-
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})`;
|
|
3819
3819
|
let sessionDetails = `${" ".repeat(detailsIndent)}${sessionCol1}${" ".repeat(detailsSpacing)}${sessionCol2}${" ".repeat(detailsSpacing)}${sessionCol3}`;
|
|
3820
3820
|
const sessionDetailsWidth = stringWidth(sessionCol1) + stringWidth(sessionCol2) + stringWidth(sessionCol3) + detailsSpacing * 2;
|
|
3821
3821
|
if (sessionDetailsWidth > detailsAvailableWidth) sessionDetails = `${" ".repeat(detailsIndent)}${sessionCol1}${" ".repeat(detailsSpacing)}${sessionCol3}`;
|
|
@@ -3827,7 +3827,7 @@ function renderLiveDisplay(terminal, block, config) {
|
|
|
3827
3827
|
minute: "2-digit",
|
|
3828
3828
|
hour12: true
|
|
3829
3829
|
}) ?? null;
|
|
3830
|
-
const usageLimitResetTime = resetTime !== null ? import_picocolors$
|
|
3830
|
+
const usageLimitResetTime = resetTime !== null ? import_picocolors$7.default.red(`${drawEmoji("❌")} USAGE LIMIT. RESET AT ${resetTime}`) : "";
|
|
3831
3831
|
usageLimitResetTimePadded = resetTime !== null ? usageLimitResetTime + " ".repeat(Math.max(0, boxWidth - 3 - stringWidth(usageLimitResetTime))) : null;
|
|
3832
3832
|
}
|
|
3833
3833
|
terminal.write(`${marginStr}│ ${sessionDetailsPadded}│\n`);
|
|
@@ -3835,31 +3835,31 @@ function renderLiveDisplay(terminal, block, config) {
|
|
|
3835
3835
|
terminal.write(`${marginStr}│${" ".repeat(boxWidth - 2)}│\n`);
|
|
3836
3836
|
terminal.write(`${marginStr}├${"─".repeat(boxWidth - 2)}┤\n`);
|
|
3837
3837
|
terminal.write(`${marginStr}│${" ".repeat(boxWidth - 2)}│\n`);
|
|
3838
|
-
let barColor = import_picocolors$
|
|
3839
|
-
if (tokenPercent > 100) barColor = import_picocolors$
|
|
3840
|
-
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;
|
|
3841
3841
|
const usageBar = config.tokenLimit != null && config.tokenLimit > 0 ? createProgressBar(totalTokens, config.tokenLimit, barWidth, {
|
|
3842
3842
|
showPercentage: false,
|
|
3843
3843
|
fillChar: barColor("█"),
|
|
3844
|
-
emptyChar: import_picocolors$
|
|
3844
|
+
emptyChar: import_picocolors$7.default.gray("░"),
|
|
3845
3845
|
leftBracket: "[",
|
|
3846
3846
|
rightBracket: "]"
|
|
3847
|
-
}) : `[${import_picocolors$
|
|
3847
|
+
}) : `[${import_picocolors$7.default.green("█".repeat(Math.floor(barWidth * .1)))}${import_picocolors$7.default.gray("░".repeat(barWidth - Math.floor(barWidth * .1)))}]`;
|
|
3848
3848
|
const burnRate = calculateBurnRate(block);
|
|
3849
3849
|
const rateIndicator = getRateIndicator(burnRate);
|
|
3850
3850
|
const buildRateDisplay = (useShort) => {
|
|
3851
|
-
if (burnRate == null) return `${import_picocolors$
|
|
3851
|
+
if (burnRate == null) return `${import_picocolors$7.default.bold("Burn Rate:")} N/A`;
|
|
3852
3852
|
const rateValue = Math.round(burnRate.tokensPerMinute);
|
|
3853
3853
|
const formattedRate = useShort ? formatTokensShort(rateValue) : formatNumber(rateValue);
|
|
3854
|
-
return `${import_picocolors$
|
|
3854
|
+
return `${import_picocolors$7.default.bold("Burn Rate:")} ${formattedRate} token/min ${rateIndicator}`;
|
|
3855
3855
|
};
|
|
3856
|
-
const usageLabel = `${drawEmoji("🔥")}${import_picocolors$
|
|
3856
|
+
const usageLabel = `${drawEmoji("🔥")}${import_picocolors$7.default.bold(" USAGE")}`;
|
|
3857
3857
|
const usageLabelWidth = stringWidth(usageLabel);
|
|
3858
3858
|
const usageBarStr = `${usageLabel}${"".padEnd(Math.max(0, labelWidth - usageLabelWidth))} ${usageBar} ${usageRightText}`;
|
|
3859
3859
|
let rateDisplay = buildRateDisplay(false);
|
|
3860
|
-
let usageCol1 = `${import_picocolors$
|
|
3861
|
-
let usageCol2 = config.tokenLimit != null && config.tokenLimit > 0 ? `${import_picocolors$
|
|
3862
|
-
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)}`;
|
|
3863
3863
|
let totalWidth = stringWidth(usageCol1);
|
|
3864
3864
|
if (usageCol2.length > 0) totalWidth += detailsSpacing + stringWidth(usageCol2);
|
|
3865
3865
|
totalWidth += detailsSpacing + stringWidth(usageCol3);
|
|
@@ -3867,8 +3867,8 @@ function renderLiveDisplay(terminal, block, config) {
|
|
|
3867
3867
|
if (totalWidth > detailsAvailableWidth) {
|
|
3868
3868
|
useTwoLineLayout = true;
|
|
3869
3869
|
rateDisplay = buildRateDisplay(true);
|
|
3870
|
-
usageCol1 = `${import_picocolors$
|
|
3871
|
-
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`;
|
|
3872
3872
|
}
|
|
3873
3873
|
const usageBarPadded = usageBarStr + " ".repeat(Math.max(0, boxWidth - 3 - stringWidth(usageBarStr)));
|
|
3874
3874
|
terminal.write(`${marginStr}│ ${usageBarPadded}│\n`);
|
|
@@ -3892,30 +3892,30 @@ function renderLiveDisplay(terminal, block, config) {
|
|
|
3892
3892
|
terminal.write(`${marginStr}├${"─".repeat(boxWidth - 2)}┤\n`);
|
|
3893
3893
|
terminal.write(`${marginStr}│${" ".repeat(boxWidth - 2)}│\n`);
|
|
3894
3894
|
if (projection != null) {
|
|
3895
|
-
let projBarColor = import_picocolors$
|
|
3896
|
-
if (projectedPercent > 100) projBarColor = import_picocolors$
|
|
3897
|
-
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;
|
|
3898
3898
|
const projectionBar = config.tokenLimit != null && config.tokenLimit > 0 ? createProgressBar(projection.totalTokens, config.tokenLimit, barWidth, {
|
|
3899
3899
|
showPercentage: false,
|
|
3900
3900
|
fillChar: projBarColor("█"),
|
|
3901
|
-
emptyChar: import_picocolors$
|
|
3901
|
+
emptyChar: import_picocolors$7.default.gray("░"),
|
|
3902
3902
|
leftBracket: "[",
|
|
3903
3903
|
rightBracket: "]"
|
|
3904
|
-
}) : `[${import_picocolors$
|
|
3905
|
-
const limitStatus = config.tokenLimit != null && config.tokenLimit > 0 ? projectedPercent > 100 ? import_picocolors$
|
|
3906
|
-
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")}`;
|
|
3907
3907
|
const projLabelWidth = stringWidth(projLabel);
|
|
3908
3908
|
const projBarStr = `${projLabel}${"".padEnd(Math.max(0, labelWidth - projLabelWidth))} ${projectionBar} ${projectionRightText}`;
|
|
3909
3909
|
const projBarPadded = projBarStr + " ".repeat(Math.max(0, boxWidth - 3 - stringWidth(projBarStr)));
|
|
3910
3910
|
terminal.write(`${marginStr}│ ${projBarPadded}│\n`);
|
|
3911
|
-
const projCol1 = `${import_picocolors$
|
|
3912
|
-
let projCol2 = `${import_picocolors$
|
|
3913
|
-
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)}`;
|
|
3914
3914
|
const projTotalWidth = stringWidth(projCol1) + stringWidth(projCol2) + stringWidth(projCol3) + detailsSpacing * 2;
|
|
3915
3915
|
let projUseTwoLineLayout = false;
|
|
3916
3916
|
if (projTotalWidth > detailsAvailableWidth) {
|
|
3917
3917
|
projUseTwoLineLayout = true;
|
|
3918
|
-
projCol2 = `${import_picocolors$
|
|
3918
|
+
projCol2 = `${import_picocolors$7.default.gray("Tokens:")} ${formatTokenDisplay(projection.totalTokens, true)}`;
|
|
3919
3919
|
}
|
|
3920
3920
|
if (projUseTwoLineLayout) {
|
|
3921
3921
|
const projDetailsLine1 = `${" ".repeat(detailsIndent)}${projCol1}`;
|
|
@@ -3939,7 +3939,7 @@ function renderLiveDisplay(terminal, block, config) {
|
|
|
3939
3939
|
}
|
|
3940
3940
|
terminal.write(`${marginStr}├${"─".repeat(boxWidth - 2)}┤\n`);
|
|
3941
3941
|
const refreshText = `${drawEmoji("↻")} Refreshing every ${config.refreshInterval / 1e3}s • Press Ctrl+C to stop`;
|
|
3942
|
-
terminal.write(`${marginStr}│${import_picocolors$
|
|
3942
|
+
terminal.write(`${marginStr}│${import_picocolors$7.default.gray(centerText(refreshText, boxWidth - 2))}│\n`);
|
|
3943
3943
|
terminal.write(`${marginStr}└${"─".repeat(boxWidth - 2)}┘\n`);
|
|
3944
3944
|
}
|
|
3945
3945
|
/**
|
|
@@ -3947,22 +3947,22 @@ function renderLiveDisplay(terminal, block, config) {
|
|
|
3947
3947
|
*/
|
|
3948
3948
|
function renderCompactLiveDisplay(terminal, block, config, totalTokens, elapsed, remaining) {
|
|
3949
3949
|
const width = terminal.width;
|
|
3950
|
-
terminal.write(`${import_picocolors$
|
|
3950
|
+
terminal.write(`${import_picocolors$7.default.bold(centerText("LIVE MONITOR", width))}\n`);
|
|
3951
3951
|
terminal.write(`${"─".repeat(width)}\n`);
|
|
3952
3952
|
const sessionPercent = elapsed / (elapsed + remaining) * 100;
|
|
3953
3953
|
terminal.write(`Session: ${sessionPercent.toFixed(1)}% (${Math.floor(elapsed / 60)}h ${Math.floor(elapsed % 60)}m)\n`);
|
|
3954
3954
|
if (config.tokenLimit != null && config.tokenLimit > 0) {
|
|
3955
3955
|
const tokenPercent = totalTokens / config.tokenLimit * 100;
|
|
3956
|
-
const status = tokenPercent > 100 ? import_picocolors$
|
|
3956
|
+
const status = tokenPercent > 100 ? import_picocolors$7.default.red("OVER") : tokenPercent > 80 ? import_picocolors$7.default.yellow("WARN") : import_picocolors$7.default.green("OK");
|
|
3957
3957
|
terminal.write(`Tokens: ${formatNumber(totalTokens)}/${formatNumber(config.tokenLimit)} ${status}\n`);
|
|
3958
3958
|
} else terminal.write(`Tokens: ${formatNumber(totalTokens)}\n`);
|
|
3959
3959
|
terminal.write(`Cost: ${formatCurrency(block.costUSD)}\n`);
|
|
3960
3960
|
const burnRate = calculateBurnRate(block);
|
|
3961
3961
|
if (burnRate != null) terminal.write(`Rate: ${formatNumber(burnRate.tokensPerMinute)}/min\n`);
|
|
3962
3962
|
terminal.write(`${"─".repeat(width)}\n`);
|
|
3963
|
-
terminal.write(import_picocolors$
|
|
3963
|
+
terminal.write(import_picocolors$7.default.gray(`Refresh: ${config.refreshInterval / 1e3}s | Ctrl+C: stop\n`));
|
|
3964
3964
|
}
|
|
3965
|
-
var import_picocolors$
|
|
3965
|
+
var import_picocolors$6 = __toESM(require_picocolors(), 1);
|
|
3966
3966
|
var import_usingCtx = __toESM(require_usingCtx(), 1);
|
|
3967
3967
|
async function startLiveMonitoring(config) {
|
|
3968
3968
|
try {
|
|
@@ -4025,7 +4025,7 @@ async function startLiveMonitoring(config) {
|
|
|
4025
4025
|
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
4026
4026
|
terminal.startBuffering();
|
|
4027
4027
|
terminal.clearScreen();
|
|
4028
|
-
terminal.write(import_picocolors$
|
|
4028
|
+
terminal.write(import_picocolors$6.default.red(`Error: ${errorMessage}\n`));
|
|
4029
4029
|
terminal.flush();
|
|
4030
4030
|
logger.error(`Live monitoring error: ${errorMessage}`);
|
|
4031
4031
|
await delayWithAbort(config.refreshInterval, abortController.signal).catch(() => {});
|
|
@@ -4036,7 +4036,7 @@ async function startLiveMonitoring(config) {
|
|
|
4036
4036
|
_usingCtx.d();
|
|
4037
4037
|
}
|
|
4038
4038
|
}
|
|
4039
|
-
var import_picocolors$
|
|
4039
|
+
var import_picocolors$5 = __toESM(require_picocolors(), 1);
|
|
4040
4040
|
/**
|
|
4041
4041
|
* Formats the time display for a session block
|
|
4042
4042
|
* @param block - Session block to format
|
|
@@ -4245,19 +4245,19 @@ const blocksCommand = define({
|
|
|
4245
4245
|
const now = new Date();
|
|
4246
4246
|
const elapsed = Math.round((now.getTime() - block.startTime.getTime()) / (1e3 * 60));
|
|
4247
4247
|
const remaining = Math.round((block.endTime.getTime() - now.getTime()) / (1e3 * 60));
|
|
4248
|
-
log(`Block Started: ${import_picocolors$
|
|
4249
|
-
log(`Time Remaining: ${import_picocolors$
|
|
4250
|
-
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:"));
|
|
4251
4251
|
log(` Input Tokens: ${formatNumber(block.tokenCounts.inputTokens)}`);
|
|
4252
4252
|
log(` Output Tokens: ${formatNumber(block.tokenCounts.outputTokens)}`);
|
|
4253
4253
|
log(` Total Cost: ${formatCurrency(block.costUSD)}\n`);
|
|
4254
4254
|
if (burnRate != null) {
|
|
4255
|
-
log(import_picocolors$
|
|
4255
|
+
log(import_picocolors$5.default.bold("Burn Rate:"));
|
|
4256
4256
|
log(` Tokens/minute: ${formatNumber(burnRate.tokensPerMinute)}`);
|
|
4257
4257
|
log(` Cost/hour: ${formatCurrency(burnRate.costPerHour)}\n`);
|
|
4258
4258
|
}
|
|
4259
4259
|
if (projection != null) {
|
|
4260
|
-
log(import_picocolors$
|
|
4260
|
+
log(import_picocolors$5.default.bold("Projected Usage (if current rate continues):"));
|
|
4261
4261
|
log(` Total Tokens: ${formatNumber(projection.totalTokens)}`);
|
|
4262
4262
|
log(` Total Cost: ${formatCurrency(projection.totalCost)}\n`);
|
|
4263
4263
|
if (ctx.values.tokenLimit != null) {
|
|
@@ -4266,8 +4266,8 @@ const blocksCommand = define({
|
|
|
4266
4266
|
const currentTokens = getTotalTokens(block.tokenCounts);
|
|
4267
4267
|
const remainingTokens = Math.max(0, limit - currentTokens);
|
|
4268
4268
|
const percentUsed = projection.totalTokens / limit * 100;
|
|
4269
|
-
const status = percentUsed > 100 ? import_picocolors$
|
|
4270
|
-
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:"));
|
|
4271
4271
|
log(` Limit: ${formatNumber(limit)} tokens`);
|
|
4272
4272
|
log(` Current Usage: ${formatNumber(currentTokens)} (${(currentTokens / limit * 100).toFixed(1)}%)`);
|
|
4273
4273
|
log(` Remaining: ${formatNumber(remainingTokens)} tokens`);
|
|
@@ -4305,17 +4305,17 @@ const blocksCommand = define({
|
|
|
4305
4305
|
const useCompactFormat = terminalWidth < BLOCKS_COMPACT_WIDTH_THRESHOLD;
|
|
4306
4306
|
for (const block of blocks) if (block.isGap ?? false) {
|
|
4307
4307
|
const gapRow = [
|
|
4308
|
-
import_picocolors$
|
|
4309
|
-
import_picocolors$
|
|
4310
|
-
import_picocolors$
|
|
4311
|
-
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("-")
|
|
4312
4312
|
];
|
|
4313
|
-
if (actualTokenLimit != null && actualTokenLimit > 0) gapRow.push(import_picocolors$
|
|
4314
|
-
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("-"));
|
|
4315
4315
|
table.push(gapRow);
|
|
4316
4316
|
} else {
|
|
4317
4317
|
const totalTokens = getTotalTokens(block.tokenCounts);
|
|
4318
|
-
const status = block.isActive ? import_picocolors$
|
|
4318
|
+
const status = block.isActive ? import_picocolors$5.default.green("ACTIVE") : "";
|
|
4319
4319
|
const row = [
|
|
4320
4320
|
formatBlockTime(block, useCompactFormat, ctx.values.locale),
|
|
4321
4321
|
status,
|
|
@@ -4325,7 +4325,7 @@ const blocksCommand = define({
|
|
|
4325
4325
|
if (actualTokenLimit != null && actualTokenLimit > 0) {
|
|
4326
4326
|
const percentage = totalTokens / actualTokenLimit * 100;
|
|
4327
4327
|
const percentText = `${percentage.toFixed(1)}%`;
|
|
4328
|
-
row.push(percentage > 100 ? import_picocolors$
|
|
4328
|
+
row.push(percentage > 100 ? import_picocolors$5.default.red(percentText) : percentText);
|
|
4329
4329
|
}
|
|
4330
4330
|
row.push(formatCurrency(block.costUSD));
|
|
4331
4331
|
table.push(row);
|
|
@@ -4333,15 +4333,15 @@ const blocksCommand = define({
|
|
|
4333
4333
|
if (actualTokenLimit != null && actualTokenLimit > 0) {
|
|
4334
4334
|
const currentTokens = getTotalTokens(block.tokenCounts);
|
|
4335
4335
|
const remainingTokens = Math.max(0, actualTokenLimit - currentTokens);
|
|
4336
|
-
const remainingText = remainingTokens > 0 ? formatNumber(remainingTokens) : import_picocolors$
|
|
4336
|
+
const remainingText = remainingTokens > 0 ? formatNumber(remainingTokens) : import_picocolors$5.default.red("0");
|
|
4337
4337
|
const remainingPercent = (actualTokenLimit - currentTokens) / actualTokenLimit * 100;
|
|
4338
|
-
const remainingPercentText = remainingPercent > 0 ? `${remainingPercent.toFixed(1)}%` : import_picocolors$
|
|
4338
|
+
const remainingPercentText = remainingPercent > 0 ? `${remainingPercent.toFixed(1)}%` : import_picocolors$5.default.red("0.0%");
|
|
4339
4339
|
const remainingRow = [
|
|
4340
4340
|
{
|
|
4341
|
-
content: import_picocolors$
|
|
4341
|
+
content: import_picocolors$5.default.gray(`(assuming ${formatNumber(actualTokenLimit)} token limit)`),
|
|
4342
4342
|
hAlign: "right"
|
|
4343
4343
|
},
|
|
4344
|
-
import_picocolors$
|
|
4344
|
+
import_picocolors$5.default.blue("REMAINING"),
|
|
4345
4345
|
"",
|
|
4346
4346
|
remainingText,
|
|
4347
4347
|
remainingPercentText,
|
|
@@ -4352,13 +4352,13 @@ const blocksCommand = define({
|
|
|
4352
4352
|
const projection = projectBlockUsage(block);
|
|
4353
4353
|
if (projection != null) {
|
|
4354
4354
|
const projectedTokens = formatNumber(projection.totalTokens);
|
|
4355
|
-
const projectedText = actualTokenLimit != null && actualTokenLimit > 0 && projection.totalTokens > actualTokenLimit ? import_picocolors$
|
|
4355
|
+
const projectedText = actualTokenLimit != null && actualTokenLimit > 0 && projection.totalTokens > actualTokenLimit ? import_picocolors$5.default.red(projectedTokens) : projectedTokens;
|
|
4356
4356
|
const projectedRow = [
|
|
4357
4357
|
{
|
|
4358
|
-
content: import_picocolors$
|
|
4358
|
+
content: import_picocolors$5.default.gray("(assuming current burn rate)"),
|
|
4359
4359
|
hAlign: "right"
|
|
4360
4360
|
},
|
|
4361
|
-
import_picocolors$
|
|
4361
|
+
import_picocolors$5.default.yellow("PROJECTED"),
|
|
4362
4362
|
"",
|
|
4363
4363
|
projectedText
|
|
4364
4364
|
];
|
|
@@ -4513,7 +4513,7 @@ function formatProjectName(projectName) {
|
|
|
4513
4513
|
if (aliases.has(parsed)) return aliases.get(parsed);
|
|
4514
4514
|
return parsed;
|
|
4515
4515
|
}
|
|
4516
|
-
var import_picocolors$
|
|
4516
|
+
var import_picocolors$4 = __toESM(require_picocolors(), 1);
|
|
4517
4517
|
const dailyCommand = define({
|
|
4518
4518
|
name: "daily",
|
|
4519
4519
|
description: "Show usage report grouped by date",
|
|
@@ -4631,7 +4631,7 @@ const dailyCommand = define({
|
|
|
4631
4631
|
""
|
|
4632
4632
|
]);
|
|
4633
4633
|
table.push([
|
|
4634
|
-
import_picocolors$
|
|
4634
|
+
import_picocolors$4.default.cyan(`Project: ${formatProjectName(projectName)}`),
|
|
4635
4635
|
"",
|
|
4636
4636
|
"",
|
|
4637
4637
|
"",
|
|
@@ -4679,14 +4679,14 @@ const dailyCommand = define({
|
|
|
4679
4679
|
""
|
|
4680
4680
|
]);
|
|
4681
4681
|
table.push([
|
|
4682
|
-
import_picocolors$
|
|
4682
|
+
import_picocolors$4.default.yellow("Total"),
|
|
4683
4683
|
"",
|
|
4684
|
-
import_picocolors$
|
|
4685
|
-
import_picocolors$
|
|
4686
|
-
import_picocolors$
|
|
4687
|
-
import_picocolors$
|
|
4688
|
-
import_picocolors$
|
|
4689
|
-
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))
|
|
4690
4690
|
]);
|
|
4691
4691
|
log(table.toString());
|
|
4692
4692
|
if (table.isCompactMode()) {
|
|
@@ -5170,7 +5170,7 @@ const mcpCommand = define({
|
|
|
5170
5170
|
}
|
|
5171
5171
|
}
|
|
5172
5172
|
});
|
|
5173
|
-
var import_picocolors$
|
|
5173
|
+
var import_picocolors$3 = __toESM(require_picocolors(), 1);
|
|
5174
5174
|
const monthlyCommand = define({
|
|
5175
5175
|
name: "monthly",
|
|
5176
5176
|
description: "Show usage report grouped by month",
|
|
@@ -5289,14 +5289,14 @@ const monthlyCommand = define({
|
|
|
5289
5289
|
""
|
|
5290
5290
|
]);
|
|
5291
5291
|
table.push([
|
|
5292
|
-
import_picocolors$
|
|
5292
|
+
import_picocolors$3.default.yellow("Total"),
|
|
5293
5293
|
"",
|
|
5294
|
-
import_picocolors$
|
|
5295
|
-
import_picocolors$
|
|
5296
|
-
import_picocolors$
|
|
5297
|
-
import_picocolors$
|
|
5298
|
-
import_picocolors$
|
|
5299
|
-
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))
|
|
5300
5300
|
]);
|
|
5301
5301
|
log(table.toString());
|
|
5302
5302
|
if (table.isCompactMode()) {
|
|
@@ -5306,7 +5306,7 @@ const monthlyCommand = define({
|
|
|
5306
5306
|
}
|
|
5307
5307
|
}
|
|
5308
5308
|
});
|
|
5309
|
-
var import_picocolors$
|
|
5309
|
+
var import_picocolors$2 = __toESM(require_picocolors(), 1);
|
|
5310
5310
|
const sessionCommand = define({
|
|
5311
5311
|
name: "session",
|
|
5312
5312
|
description: "Show usage report grouped by conversation session",
|
|
@@ -5424,14 +5424,14 @@ const sessionCommand = define({
|
|
|
5424
5424
|
""
|
|
5425
5425
|
]);
|
|
5426
5426
|
table.push([
|
|
5427
|
-
import_picocolors$
|
|
5427
|
+
import_picocolors$2.default.yellow("Total"),
|
|
5428
5428
|
"",
|
|
5429
|
-
import_picocolors$
|
|
5430
|
-
import_picocolors$
|
|
5431
|
-
import_picocolors$
|
|
5432
|
-
import_picocolors$
|
|
5433
|
-
import_picocolors$
|
|
5434
|
-
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)),
|
|
5435
5435
|
""
|
|
5436
5436
|
]);
|
|
5437
5437
|
log(table.toString());
|
|
@@ -5442,6 +5442,121 @@ const sessionCommand = define({
|
|
|
5442
5442
|
}
|
|
5443
5443
|
}
|
|
5444
5444
|
});
|
|
5445
|
+
const { stdin: stdin$1 } = process;
|
|
5446
|
+
async function getStdin() {
|
|
5447
|
+
let result = "";
|
|
5448
|
+
if (stdin$1.isTTY) return result;
|
|
5449
|
+
stdin$1.setEncoding("utf8");
|
|
5450
|
+
for await (const chunk of stdin$1) result += chunk;
|
|
5451
|
+
return result;
|
|
5452
|
+
}
|
|
5453
|
+
getStdin.buffer = async () => {
|
|
5454
|
+
const result = [];
|
|
5455
|
+
let length = 0;
|
|
5456
|
+
if (stdin$1.isTTY) return Buffer.concat([]);
|
|
5457
|
+
for await (const chunk of stdin$1) {
|
|
5458
|
+
result.push(chunk);
|
|
5459
|
+
length += chunk.length;
|
|
5460
|
+
}
|
|
5461
|
+
return Buffer.concat(result, length);
|
|
5462
|
+
};
|
|
5463
|
+
var import_picocolors$1 = __toESM(require_picocolors(), 1);
|
|
5464
|
+
/**
|
|
5465
|
+
/**
|
|
5466
|
+
* Formats the remaining time for display
|
|
5467
|
+
* @param remaining - Remaining minutes
|
|
5468
|
+
* @returns Formatted time string
|
|
5469
|
+
*/
|
|
5470
|
+
function formatRemainingTime(remaining) {
|
|
5471
|
+
const remainingHours = Math.floor(remaining / 60);
|
|
5472
|
+
const remainingMins = remaining % 60;
|
|
5473
|
+
if (remainingHours > 0) return `${remainingHours}h ${remainingMins}m left`;
|
|
5474
|
+
return `${remainingMins}m left`;
|
|
5475
|
+
}
|
|
5476
|
+
const statuslineCommand = define({
|
|
5477
|
+
name: "statusline",
|
|
5478
|
+
description: "Display compact status line for Claude Code hooks (Beta)",
|
|
5479
|
+
args: {},
|
|
5480
|
+
async run() {
|
|
5481
|
+
logger.level = 0;
|
|
5482
|
+
const stdin$2 = await getStdin();
|
|
5483
|
+
if (stdin$2.length === 0) {
|
|
5484
|
+
log("❌ No input provided");
|
|
5485
|
+
process$1.exit(1);
|
|
5486
|
+
}
|
|
5487
|
+
const hookDataJson = JSON.parse(stdin$2.trim());
|
|
5488
|
+
const hookDataParseResult = statuslineHookJsonSchema.safeParse(hookDataJson);
|
|
5489
|
+
if (!hookDataParseResult.success) {
|
|
5490
|
+
log("❌ Invalid input format:", hookDataParseResult.error.message);
|
|
5491
|
+
process$1.exit(1);
|
|
5492
|
+
}
|
|
5493
|
+
const hookData = hookDataParseResult.data;
|
|
5494
|
+
const claudePaths = getClaudePaths();
|
|
5495
|
+
if (claudePaths.length === 0) {
|
|
5496
|
+
log("❌ No Claude data directory found");
|
|
5497
|
+
process$1.exit(1);
|
|
5498
|
+
}
|
|
5499
|
+
const sessionId = hookData.session_id;
|
|
5500
|
+
let sessionCost = null;
|
|
5501
|
+
try {
|
|
5502
|
+
const sessionData = await loadSessionUsageById(sessionId, { mode: "auto" });
|
|
5503
|
+
if (sessionData != null) sessionCost = sessionData.totalCost;
|
|
5504
|
+
} catch (error) {
|
|
5505
|
+
logger.error("Failed to load session data:", error);
|
|
5506
|
+
}
|
|
5507
|
+
const today = new Date();
|
|
5508
|
+
const todayStr = today.toISOString().split("T")[0]?.replace(/-/g, "") ?? "";
|
|
5509
|
+
let todayCost = 0;
|
|
5510
|
+
try {
|
|
5511
|
+
const dailyData = await loadDailyUsageData({
|
|
5512
|
+
since: todayStr,
|
|
5513
|
+
until: todayStr,
|
|
5514
|
+
mode: "auto"
|
|
5515
|
+
});
|
|
5516
|
+
if (dailyData.length > 0) {
|
|
5517
|
+
const totals = calculateTotals(dailyData);
|
|
5518
|
+
todayCost = totals.totalCost;
|
|
5519
|
+
}
|
|
5520
|
+
} catch (error) {
|
|
5521
|
+
logger.error("Failed to load daily data:", error);
|
|
5522
|
+
}
|
|
5523
|
+
let blockInfo = "";
|
|
5524
|
+
let burnRateInfo = "";
|
|
5525
|
+
try {
|
|
5526
|
+
const blocks = await loadSessionBlockData({ mode: "auto" });
|
|
5527
|
+
if (blocks.length === 0) blockInfo = "No active block";
|
|
5528
|
+
else {
|
|
5529
|
+
const activeBlock = blocks.find((block) => {
|
|
5530
|
+
if (!block.isActive) return false;
|
|
5531
|
+
return true;
|
|
5532
|
+
});
|
|
5533
|
+
if (activeBlock != null) {
|
|
5534
|
+
const now = new Date();
|
|
5535
|
+
const remaining = Math.round((activeBlock.endTime.getTime() - now.getTime()) / (1e3 * 60));
|
|
5536
|
+
const blockCost = activeBlock.costUSD;
|
|
5537
|
+
blockInfo = `${formatCurrency(blockCost)} block (${formatRemainingTime(remaining)})`;
|
|
5538
|
+
const burnRate = calculateBurnRate(activeBlock);
|
|
5539
|
+
if (burnRate != null) {
|
|
5540
|
+
const costPerHour = burnRate.costPerHour;
|
|
5541
|
+
const costPerHourStr = `${formatCurrency(costPerHour)}/hr`;
|
|
5542
|
+
let coloredBurnRate = costPerHourStr;
|
|
5543
|
+
if (burnRate.tokensPerMinuteForIndicator < 2e3) coloredBurnRate = import_picocolors$1.default.green(costPerHourStr);
|
|
5544
|
+
else if (burnRate.tokensPerMinuteForIndicator < 5e3) coloredBurnRate = import_picocolors$1.default.yellow(costPerHourStr);
|
|
5545
|
+
else coloredBurnRate = import_picocolors$1.default.red(costPerHourStr);
|
|
5546
|
+
burnRateInfo = ` | 🔥 ${coloredBurnRate}`;
|
|
5547
|
+
}
|
|
5548
|
+
} else blockInfo = "No active block";
|
|
5549
|
+
}
|
|
5550
|
+
} catch (error) {
|
|
5551
|
+
logger.error("Failed to load block data:", error);
|
|
5552
|
+
blockInfo = "No active block";
|
|
5553
|
+
}
|
|
5554
|
+
const modelName = hookData.model.display_name;
|
|
5555
|
+
const sessionDisplay = sessionCost !== null ? formatCurrency(sessionCost) : "N/A";
|
|
5556
|
+
const statusLine = `🤖 ${modelName} | 💰 ${sessionDisplay} session / ${formatCurrency(todayCost)} today / ${blockInfo}${burnRateInfo}`;
|
|
5557
|
+
log(statusLine);
|
|
5558
|
+
}
|
|
5559
|
+
});
|
|
5445
5560
|
var import_picocolors = __toESM(require_picocolors(), 1);
|
|
5446
5561
|
const weeklyCommand = define({
|
|
5447
5562
|
name: "weekly",
|
|
@@ -5599,6 +5714,7 @@ subCommands.set("weekly", weeklyCommand);
|
|
|
5599
5714
|
subCommands.set("session", sessionCommand);
|
|
5600
5715
|
subCommands.set("blocks", blocksCommand);
|
|
5601
5716
|
subCommands.set("mcp", mcpCommand);
|
|
5717
|
+
subCommands.set("statusline", statuslineCommand);
|
|
5602
5718
|
/**
|
|
5603
5719
|
* Default command when no subcommand is specified (defaults to daily)
|
|
5604
5720
|
*/
|
|
@@ -951,7 +951,7 @@ function _getDefaultLogLevel() {
|
|
|
951
951
|
}
|
|
952
952
|
const consola = createConsola();
|
|
953
953
|
var name = "ccusage";
|
|
954
|
-
var version = "15.
|
|
954
|
+
var version = "15.9.1";
|
|
955
955
|
var description = "Usage analysis tool for Claude Code";
|
|
956
956
|
/**
|
|
957
957
|
* Application logger instance with package name tag
|
package/dist/logger.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { log, logger } from "./logger-
|
|
1
|
+
import { log, logger } from "./logger-BODy31tA.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-DtGb7sbF.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-D3wQxjrt.js";
|
|
6
|
+
import { name, version } from "./logger-BODy31tA.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-DtGb7sbF.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-D3wQxjrt.js";
|
|
6
|
+
import "./logger-BODy31tA.js";
|
|
7
|
+
import { createMcpHttpApp, createMcpServer, startMcpServerStdio } from "./mcp-opivOm8q.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-BODy31tA.js";
|
|
3
3
|
import { createRequire } from "node:module";
|
|
4
4
|
import path from "node:path";
|
|
5
5
|
import F, { homedir } from "node:os";
|
|
@@ -406,6 +406,12 @@ var PricingFetcher = class {
|
|
|
406
406
|
"cache_creation_input_token_cost": 1875e-8,
|
|
407
407
|
"cache_read_input_token_cost": 15e-7
|
|
408
408
|
},
|
|
409
|
+
"claude-opus-4-1": {
|
|
410
|
+
"input_cost_per_token": 15e-6,
|
|
411
|
+
"output_cost_per_token": 75e-6,
|
|
412
|
+
"cache_creation_input_token_cost": 1875e-8,
|
|
413
|
+
"cache_read_input_token_cost": 15e-7
|
|
414
|
+
},
|
|
409
415
|
"claude-opus-4-1-20250805": {
|
|
410
416
|
"input_cost_per_token": 15e-6,
|
|
411
417
|
"output_cost_per_token": 75e-6,
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { PricingFetcher$1 as PricingFetcher } from "./pricing-fetcher-
|
|
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-DtGb7sbF.js";
|
|
2
|
+
import "./_types-B-1t4mxD.js";
|
|
3
|
+
import "./logger-BODy31tA.js";
|
|
4
4
|
export { PricingFetcher };
|