ccusage 12.3.2 → 13.0.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/LICENSE CHANGED
@@ -2,6 +2,8 @@ MIT License
2
2
 
3
3
  Copyright (c) 2025 ryoppippi
4
4
 
5
+ Logo and brand assets created by nyatinte are also licensed under MIT License.
6
+
5
7
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
8
  of this software and associated documentation files (the "Software"), to deal
7
9
  in the Software without restriction, including without limitation the rights
package/README.md CHANGED
@@ -1,6 +1,8 @@
1
1
  # ccusage
2
2
 
3
- > **ccusage(claude-code-usage)**
3
+ <div align="center">
4
+ <img src="docs/logo.png" alt="ccusage logo" width="256" height="256">
5
+ </div>
4
6
 
5
7
  [![npm version](https://img.shields.io/npm/v/ccusage?color=yellow)](https://npmjs.com/package/ccusage)
6
8
  [![NPM Downloads](https://img.shields.io/npm/dy/ccusage)](https://tanstack.com/stats/npm?packageGroups=%5B%7B%22packages%22:%5B%7B%22name%22:%22ccusage%22%7D%5D%7D%5D&range=30-days&transform=none&binType=daily&showDataMode=all&height=400)
@@ -12,6 +14,8 @@
12
14
  <img src="https://github.com/ryoppippi/ccusage/blob/main/docs/screenshot.png?raw=true">
13
15
  </div>
14
16
 
17
+ > **ccusage(claude-code-usage)**
18
+
15
19
  A CLI tool for analyzing Claude Code usage from local JSONL files.
16
20
 
17
21
  Inspired by [this article](https://note.com/milliondev/n/n1d018da2d769) about tracking Claude Code usage costs.
@@ -19,7 +23,7 @@ Inspired by [this article](https://note.com/milliondev/n/n1d018da2d769) about tr
19
23
  ## What is `ccusage` (by NotebookLM)
20
24
 
21
25
  <details>
22
- <summary>Podcact</summary>
26
+ <summary>Podcast</summary>
23
27
 
24
28
  # English
25
29
 
@@ -477,6 +481,10 @@ With `--breakdown` flag:
477
481
 
478
482
  MIT
479
483
 
484
+ This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
485
+
486
+ The logo and brand assets are also licensed under the MIT License. Created by [@nyatinte](https://github.com/nyatinte).
487
+
480
488
  ## Author
481
489
 
482
490
  [@ryoppippi](https://github.com/ryoppippi)
@@ -492,6 +500,7 @@ While the original approach uses DuckDB for analysis, this tool provides a more
492
500
  some projects use `ccusage` internally and provide additional features:
493
501
 
494
502
  - [claude-usage-tracker-for-mac](https://github.com/penicillin0/claude-usage-tracker-for-mac) – macOS menu bar app to visualize Claude Code usage costs by [@penicillin0](https://github.com/penicillin0).
503
+ - [ccusage Raycast Extension](https://www.raycast.com/nyatinte/ccusage) – Raycast extension to view Claude Code usage reports in Raycast by [@nyatinte](https://github.com/nyatinte).
495
504
 
496
505
  ## Acknowledgments
497
506
 
@@ -1,5 +1,5 @@
1
- import "./pricing-fetcher-BkOpRIdx.js";
2
- import { DailyUsage, MonthlyUsage, SessionUsage } from "./data-loader-CBwn9vk0.js";
1
+ import "./pricing-fetcher-A6FC8DhM.js";
2
+ import { DailyUsage, MonthlyUsage, SessionUsage } from "./data-loader-BrxITdVN.js";
3
3
 
4
4
  //#region src/calculate-cost.d.ts
5
5
  /**
@@ -1,2 +1,3 @@
1
- import { calculateTotals, createTotalsObject, getTotalTokens } from "./calculate-cost-D3IraeGW.js";
1
+ import "./types.internal-CX7kpidj.js";
2
+ import { calculateTotals, createTotalsObject, getTotalTokens } from "./calculate-cost-CoS7we68.js";
2
3
  export { calculateTotals, createTotalsObject, getTotalTokens };
@@ -1,5 +1,6 @@
1
- import { PricingFetcher, __commonJSMin, __require, __toESM, arrayType, numberType, objectType, require_usingCtx, stringType } from "./pricing-fetcher-mFPZYGXl.js";
2
- import { logger } from "./logger-BfzGx5lS.js";
1
+ import { CLAUDE_PROJECTS_DIR_NAME, DEFAULT_CLAUDE_CODE_PATH, DEFAULT_RECENT_DAYS, PricingFetcher, USAGE_DATA_GLOB_PATTERN, USER_HOME_DIR, __commonJSMin, __require, __toESM, require_usingCtx } from "./pricing-fetcher-Cx71zrV9.js";
2
+ import { activityDateSchema, arrayType, createDailyDate, createMonthlyDate, createProjectPath, createSessionId, dailyDateSchema, isoTimestampSchema, messageIdSchema, modelNameSchema, monthlyDateSchema, numberType, objectType, projectPathSchema, requestIdSchema, sessionIdSchema, versionSchema } from "./types.internal-CX7kpidj.js";
3
+ import { logger } from "./logger-B4PJ298G.js";
3
4
  import a, { readFile } from "node:fs/promises";
4
5
  import F, { homedir } from "node:os";
5
6
  import path, { posix } from "node:path";
@@ -244,6 +245,9 @@ function groupBy(arr, getKeyFromItem) {
244
245
  }
245
246
  return result;
246
247
  }
248
+ function uniq(arr) {
249
+ return Array.from(new Set(arr));
250
+ }
247
251
  var castComparer = function(comparer) {
248
252
  return function(a$1, b$1, order) {
249
253
  return comparer(a$1, b$1, order) * order;
@@ -3056,10 +3060,6 @@ async function glob(patternsOrOptions, options) {
3056
3060
  */
3057
3061
  const DEFAULT_SESSION_DURATION_HOURS = 5;
3058
3062
  /**
3059
- * Default number of recent days to include when filtering blocks
3060
- */
3061
- const DEFAULT_RECENT_DAYS = 3;
3062
- /**
3063
3063
  * Identifies and creates session blocks from usage entries
3064
3064
  * Groups entries into time-based blocks (typically 5-hour periods) with gap detection
3065
3065
  * @param entries - Array of usage entries to process
@@ -3123,14 +3123,14 @@ function createBlock(startTime, entries, now, sessionDurationMs) {
3123
3123
  cacheReadInputTokens: 0
3124
3124
  };
3125
3125
  let costUSD = 0;
3126
- const modelsSet = /* @__PURE__ */ new Set();
3126
+ const models = [];
3127
3127
  for (const entry of entries) {
3128
3128
  tokenCounts.inputTokens += entry.usage.inputTokens;
3129
3129
  tokenCounts.outputTokens += entry.usage.outputTokens;
3130
3130
  tokenCounts.cacheCreationInputTokens += entry.usage.cacheCreationInputTokens;
3131
3131
  tokenCounts.cacheReadInputTokens += entry.usage.cacheReadInputTokens;
3132
3132
  costUSD += entry.costUSD ?? 0;
3133
- modelsSet.add(entry.model);
3133
+ models.push(entry.model);
3134
3134
  }
3135
3135
  return {
3136
3136
  id: startTime.toISOString(),
@@ -3141,7 +3141,7 @@ function createBlock(startTime, entries, now, sessionDurationMs) {
3141
3141
  entries,
3142
3142
  tokenCounts,
3143
3143
  costUSD,
3144
- models: Array.from(modelsSet)
3144
+ models: uniq(models)
3145
3145
  };
3146
3146
  }
3147
3147
  /**
@@ -3233,22 +3233,18 @@ function filterRecentBlocks(blocks, days = DEFAULT_RECENT_DAYS) {
3233
3233
  }
3234
3234
  var import_usingCtx = __toESM(require_usingCtx(), 1);
3235
3235
  /**
3236
- * Default Claude data directory path (~/.claude)
3237
- */
3238
- const DEFAULT_CLAUDE_CODE_PATH = path.join(homedir(), ".claude");
3239
- /**
3240
3236
  * Default path for Claude data directory
3241
3237
  * Uses environment variable CLAUDE_CONFIG_DIR if set, otherwise defaults to ~/.claude
3242
3238
  */
3243
3239
  function getDefaultClaudePath() {
3244
3240
  const envClaudeCodePath = (process$1.env.CLAUDE_CONFIG_DIR ?? "").trim();
3245
- if (envClaudeCodePath === "") return DEFAULT_CLAUDE_CODE_PATH;
3241
+ if (envClaudeCodePath === "") return path.join(USER_HOME_DIR, DEFAULT_CLAUDE_CODE_PATH);
3246
3242
  if (!isDirectorySync(envClaudeCodePath)) throw new Error(`CLAUDE_CONFIG_DIR path is not a valid directory: ${envClaudeCodePath}.
3247
- Please set CLAUDE_CONFIG_DIR to a valid directory path, or ensure ${DEFAULT_CLAUDE_CODE_PATH} exists.
3243
+ Please set CLAUDE_CONFIG_DIR to a valid directory path, or ensure ${path.join(USER_HOME_DIR, DEFAULT_CLAUDE_CODE_PATH)} exists.
3248
3244
  `.trim());
3249
- const claudeCodeProjectsPath = path.join(envClaudeCodePath, "projects");
3245
+ const claudeCodeProjectsPath = path.join(envClaudeCodePath, CLAUDE_PROJECTS_DIR_NAME);
3250
3246
  if (!isDirectorySync(claudeCodeProjectsPath)) throw new Error(`Claude data directory does not exist: ${claudeCodeProjectsPath}.
3251
- Please set CLAUDE_CONFIG_DIR to a valid path, or ensure ${DEFAULT_CLAUDE_CODE_PATH} exists.
3247
+ Please set CLAUDE_CONFIG_DIR to a valid path, or ensure ${path.join(USER_HOME_DIR, DEFAULT_CLAUDE_CODE_PATH)} exists.
3252
3248
  `.trim());
3253
3249
  return envClaudeCodePath;
3254
3250
  }
@@ -3256,8 +3252,8 @@ Please set CLAUDE_CONFIG_DIR to a valid path, or ensure ${DEFAULT_CLAUDE_CODE_PA
3256
3252
  * Zod schema for validating Claude usage data from JSONL files
3257
3253
  */
3258
3254
  const usageDataSchema = objectType({
3259
- timestamp: stringType(),
3260
- version: stringType().optional(),
3255
+ timestamp: isoTimestampSchema,
3256
+ version: versionSchema.optional(),
3261
3257
  message: objectType({
3262
3258
  usage: objectType({
3263
3259
  input_tokens: numberType(),
@@ -3265,17 +3261,17 @@ const usageDataSchema = objectType({
3265
3261
  cache_creation_input_tokens: numberType().optional(),
3266
3262
  cache_read_input_tokens: numberType().optional()
3267
3263
  }),
3268
- model: stringType().optional(),
3269
- id: stringType().optional()
3264
+ model: modelNameSchema.optional(),
3265
+ id: messageIdSchema.optional()
3270
3266
  }),
3271
3267
  costUSD: numberType().optional(),
3272
- requestId: stringType().optional()
3268
+ requestId: requestIdSchema.optional()
3273
3269
  });
3274
3270
  /**
3275
3271
  * Zod schema for model-specific usage breakdown data
3276
3272
  */
3277
3273
  const modelBreakdownSchema = objectType({
3278
- modelName: stringType(),
3274
+ modelName: modelNameSchema,
3279
3275
  inputTokens: numberType(),
3280
3276
  outputTokens: numberType(),
3281
3277
  cacheCreationTokens: numberType(),
@@ -3286,42 +3282,42 @@ const modelBreakdownSchema = objectType({
3286
3282
  * Zod schema for daily usage aggregation data
3287
3283
  */
3288
3284
  const dailyUsageSchema = objectType({
3289
- date: stringType().regex(/^\d{4}-\d{2}-\d{2}$/),
3285
+ date: dailyDateSchema,
3290
3286
  inputTokens: numberType(),
3291
3287
  outputTokens: numberType(),
3292
3288
  cacheCreationTokens: numberType(),
3293
3289
  cacheReadTokens: numberType(),
3294
3290
  totalCost: numberType(),
3295
- modelsUsed: arrayType(stringType()),
3291
+ modelsUsed: arrayType(modelNameSchema),
3296
3292
  modelBreakdowns: arrayType(modelBreakdownSchema)
3297
3293
  });
3298
3294
  /**
3299
3295
  * Zod schema for session-based usage aggregation data
3300
3296
  */
3301
3297
  const sessionUsageSchema = objectType({
3302
- sessionId: stringType(),
3303
- projectPath: stringType(),
3298
+ sessionId: sessionIdSchema,
3299
+ projectPath: projectPathSchema,
3304
3300
  inputTokens: numberType(),
3305
3301
  outputTokens: numberType(),
3306
3302
  cacheCreationTokens: numberType(),
3307
3303
  cacheReadTokens: numberType(),
3308
3304
  totalCost: numberType(),
3309
- lastActivity: stringType(),
3310
- versions: arrayType(stringType()),
3311
- modelsUsed: arrayType(stringType()),
3305
+ lastActivity: activityDateSchema,
3306
+ versions: arrayType(versionSchema),
3307
+ modelsUsed: arrayType(modelNameSchema),
3312
3308
  modelBreakdowns: arrayType(modelBreakdownSchema)
3313
3309
  });
3314
3310
  /**
3315
3311
  * Zod schema for monthly usage aggregation data
3316
3312
  */
3317
3313
  const monthlyUsageSchema = objectType({
3318
- month: stringType().regex(/^\d{4}-\d{2}$/),
3314
+ month: monthlyDateSchema,
3319
3315
  inputTokens: numberType(),
3320
3316
  outputTokens: numberType(),
3321
3317
  cacheCreationTokens: numberType(),
3322
3318
  cacheReadTokens: numberType(),
3323
3319
  totalCost: numberType(),
3324
- modelsUsed: arrayType(stringType()),
3320
+ modelsUsed: arrayType(modelNameSchema),
3325
3321
  modelBreakdowns: arrayType(modelBreakdownSchema)
3326
3322
  });
3327
3323
  /**
@@ -3439,7 +3435,7 @@ function markAsProcessed(uniqueHash, processedHashes) {
3439
3435
  * Extracts unique models from entries, excluding synthetic model
3440
3436
  */
3441
3437
  function extractUniqueModels(entries, getModel) {
3442
- return [...new Set(entries.map(getModel).filter((m$1) => m$1 != null && m$1 !== "<synthetic>"))];
3438
+ return uniq(entries.map(getModel).filter((m$1) => m$1 != null && m$1 !== "<synthetic>"));
3443
3439
  }
3444
3440
  /**
3445
3441
  * Formats a date string to YYYY-MM-DD format
@@ -3564,8 +3560,8 @@ async function loadDailyUsageData(options) {
3564
3560
  try {
3565
3561
  var _usingCtx = (0, import_usingCtx.default)();
3566
3562
  const claudePath = options?.claudePath ?? getDefaultClaudePath();
3567
- const claudeDir = path.join(claudePath, "projects");
3568
- const files = await glob(["**/*.jsonl"], {
3563
+ const claudeDir = path.join(claudePath, CLAUDE_PROJECTS_DIR_NAME);
3564
+ const files = await glob([USAGE_DATA_GLOB_PATTERN], {
3569
3565
  cwd: claudeDir,
3570
3566
  absolute: true
3571
3567
  });
@@ -3604,7 +3600,7 @@ async function loadDailyUsageData(options) {
3604
3600
  const totals = calculateTotals(entries, (entry) => entry.data.message.usage, (entry) => entry.cost);
3605
3601
  const modelsUsed = extractUniqueModels(entries, (e) => e.model);
3606
3602
  return {
3607
- date,
3603
+ date: createDailyDate(date),
3608
3604
  ...totals,
3609
3605
  modelsUsed,
3610
3606
  modelBreakdowns
@@ -3628,8 +3624,8 @@ async function loadSessionData(options) {
3628
3624
  try {
3629
3625
  var _usingCtx3 = (0, import_usingCtx.default)();
3630
3626
  const claudePath = options?.claudePath ?? getDefaultClaudePath();
3631
- const claudeDir = path.join(claudePath, "projects");
3632
- const files = await glob(["**/*.jsonl"], {
3627
+ const claudeDir = path.join(claudePath, CLAUDE_PROJECTS_DIR_NAME);
3628
+ const files = await glob([USAGE_DATA_GLOB_PATTERN], {
3633
3629
  cwd: claudeDir,
3634
3630
  absolute: true
3635
3631
  });
@@ -3672,18 +3668,18 @@ async function loadSessionData(options) {
3672
3668
  const results = Object.entries(groupedBySessions).map(([_, entries]) => {
3673
3669
  if (entries == null) return void 0;
3674
3670
  const latestEntry = entries.reduce((latest, current) => current.timestamp > latest.timestamp ? current : latest);
3675
- const versionSet = /* @__PURE__ */ new Set();
3676
- for (const entry of entries) if (entry.data.version != null) versionSet.add(entry.data.version);
3671
+ const versions = [];
3672
+ for (const entry of entries) if (entry.data.version != null) versions.push(entry.data.version);
3677
3673
  const modelAggregates = aggregateByModel(entries, (entry) => entry.model, (entry) => entry.data.message.usage, (entry) => entry.cost);
3678
3674
  const modelBreakdowns = createModelBreakdowns(modelAggregates);
3679
3675
  const totals = calculateTotals(entries, (entry) => entry.data.message.usage, (entry) => entry.cost);
3680
3676
  const modelsUsed = extractUniqueModels(entries, (e) => e.model);
3681
3677
  return {
3682
- sessionId: latestEntry.sessionId,
3683
- projectPath: latestEntry.projectPath,
3678
+ sessionId: createSessionId(latestEntry.sessionId),
3679
+ projectPath: createProjectPath(latestEntry.projectPath),
3684
3680
  ...totals,
3685
3681
  lastActivity: formatDate(latestEntry.timestamp),
3686
- versions: Array.from(versionSet).sort(),
3682
+ versions: uniq(versions).sort(),
3687
3683
  modelsUsed,
3688
3684
  modelBreakdowns
3689
3685
  };
@@ -3711,8 +3707,8 @@ async function loadMonthlyUsageData(options) {
3711
3707
  const allBreakdowns = dailyEntries.flatMap((daily) => daily.modelBreakdowns);
3712
3708
  const modelAggregates = aggregateModelBreakdowns(allBreakdowns);
3713
3709
  const modelBreakdowns = createModelBreakdowns(modelAggregates);
3714
- const modelsSet = /* @__PURE__ */ new Set();
3715
- for (const data of dailyEntries) for (const model of data.modelsUsed) if (model !== "<synthetic>") modelsSet.add(model);
3710
+ const models = [];
3711
+ for (const data of dailyEntries) for (const model of data.modelsUsed) if (model !== "<synthetic>") models.push(model);
3716
3712
  let totalInputTokens = 0;
3717
3713
  let totalOutputTokens = 0;
3718
3714
  let totalCacheCreationTokens = 0;
@@ -3726,13 +3722,13 @@ async function loadMonthlyUsageData(options) {
3726
3722
  totalCost += daily.totalCost;
3727
3723
  }
3728
3724
  const monthlyUsage = {
3729
- month,
3725
+ month: createMonthlyDate(month),
3730
3726
  inputTokens: totalInputTokens,
3731
3727
  outputTokens: totalOutputTokens,
3732
3728
  cacheCreationTokens: totalCacheCreationTokens,
3733
3729
  cacheReadTokens: totalCacheReadTokens,
3734
3730
  totalCost,
3735
- modelsUsed: Array.from(modelsSet),
3731
+ modelsUsed: uniq(models),
3736
3732
  modelBreakdowns
3737
3733
  };
3738
3734
  monthlyArray.push(monthlyUsage);
@@ -3749,8 +3745,8 @@ async function loadSessionBlockData(options) {
3749
3745
  try {
3750
3746
  var _usingCtx4 = (0, import_usingCtx.default)();
3751
3747
  const claudePath = options?.claudePath ?? getDefaultClaudePath();
3752
- const claudeDir = path.join(claudePath, "projects");
3753
- const files = await glob(["**/*.jsonl"], {
3748
+ const claudeDir = path.join(claudePath, CLAUDE_PROJECTS_DIR_NAME);
3749
+ const files = await glob([USAGE_DATA_GLOB_PATTERN], {
3754
3750
  cwd: claudeDir,
3755
3751
  absolute: true
3756
3752
  });
@@ -3802,4 +3798,4 @@ async function loadSessionBlockData(options) {
3802
3798
  _usingCtx4.d();
3803
3799
  }
3804
3800
  }
3805
- export { DEFAULT_SESSION_DURATION_HOURS, calculateBurnRate, calculateCostForEntry, createUniqueHash, dailyUsageSchema, filterRecentBlocks, formatDate, formatDateCompact, getDefaultClaudePath, getEarliestTimestamp, glob, loadDailyUsageData, loadMonthlyUsageData, loadSessionBlockData, loadSessionData, modelBreakdownSchema, monthlyUsageSchema, projectBlockUsage, sessionUsageSchema, sortFilesByTimestamp, usageDataSchema };
3801
+ export { DEFAULT_SESSION_DURATION_HOURS, calculateBurnRate, calculateCostForEntry, createUniqueHash, dailyUsageSchema, filterRecentBlocks, formatDate, formatDateCompact, getDefaultClaudePath, getEarliestTimestamp, glob, loadDailyUsageData, loadMonthlyUsageData, loadSessionBlockData, loadSessionData, modelBreakdownSchema, monthlyUsageSchema, projectBlockUsage, sessionUsageSchema, sortFilesByTimestamp, uniq, usageDataSchema };
@@ -1,4 +1,4 @@
1
- import { CostMode, PricingFetcher, SortOrder } from "./pricing-fetcher-BkOpRIdx.js";
1
+ import { CostMode, PricingFetcher, SortOrder } from "./pricing-fetcher-A6FC8DhM.js";
2
2
  import { z } from "zod";
3
3
 
4
4
  //#region src/session-blocks.internal.d.ts
@@ -56,8 +56,8 @@ declare function getDefaultClaudePath(): string;
56
56
  * Zod schema for validating Claude usage data from JSONL files
57
57
  */
58
58
  declare const usageDataSchema: z.ZodObject<{
59
- timestamp: z.ZodString;
60
- version: z.ZodOptional<z.ZodString>;
59
+ timestamp: z.ZodBranded<z.ZodString, "ISOTimestamp">;
60
+ version: z.ZodOptional<z.ZodBranded<z.ZodString, "Version">>;
61
61
  message: z.ZodObject<{
62
62
  usage: z.ZodObject<{
63
63
  input_tokens: z.ZodNumber;
@@ -75,8 +75,8 @@ declare const usageDataSchema: z.ZodObject<{
75
75
  cache_creation_input_tokens?: number | undefined;
76
76
  cache_read_input_tokens?: number | undefined;
77
77
  }>;
78
- model: z.ZodOptional<z.ZodString>;
79
- id: z.ZodOptional<z.ZodString>;
78
+ model: z.ZodOptional<z.ZodBranded<z.ZodString, "ModelName">>;
79
+ id: z.ZodOptional<z.ZodBranded<z.ZodString, "MessageId">>;
80
80
  }, "strip", z.ZodTypeAny, {
81
81
  usage: {
82
82
  input_tokens: number;
@@ -84,8 +84,8 @@ declare const usageDataSchema: z.ZodObject<{
84
84
  cache_creation_input_tokens?: number | undefined;
85
85
  cache_read_input_tokens?: number | undefined;
86
86
  };
87
- model?: string | undefined;
88
- id?: string | undefined;
87
+ model?: string & z.BRAND<"ModelName"> | undefined;
88
+ id?: string & z.BRAND<"MessageId"> | undefined;
89
89
  }, {
90
90
  usage: {
91
91
  input_tokens: number;
@@ -97,10 +97,10 @@ declare const usageDataSchema: z.ZodObject<{
97
97
  id?: string | undefined;
98
98
  }>;
99
99
  costUSD: z.ZodOptional<z.ZodNumber>;
100
- requestId: z.ZodOptional<z.ZodString>;
100
+ requestId: z.ZodOptional<z.ZodBranded<z.ZodString, "RequestId">>;
101
101
  }, "strip", z.ZodTypeAny, {
102
- timestamp: string;
103
- version?: string | undefined;
102
+ timestamp: string & z.BRAND<"ISOTimestamp">;
103
+ version?: string & z.BRAND<"Version"> | undefined;
104
104
  message: {
105
105
  usage: {
106
106
  input_tokens: number;
@@ -108,11 +108,11 @@ declare const usageDataSchema: z.ZodObject<{
108
108
  cache_creation_input_tokens?: number | undefined;
109
109
  cache_read_input_tokens?: number | undefined;
110
110
  };
111
- model?: string | undefined;
112
- id?: string | undefined;
111
+ model?: string & z.BRAND<"ModelName"> | undefined;
112
+ id?: string & z.BRAND<"MessageId"> | undefined;
113
113
  };
114
114
  costUSD?: number | undefined;
115
- requestId?: string | undefined;
115
+ requestId?: string & z.BRAND<"RequestId"> | undefined;
116
116
  }, {
117
117
  timestamp: string;
118
118
  version?: string | undefined;
@@ -137,14 +137,14 @@ type UsageData = z.infer<typeof usageDataSchema>;
137
137
  * Zod schema for model-specific usage breakdown data
138
138
  */
139
139
  declare const modelBreakdownSchema: z.ZodObject<{
140
- modelName: z.ZodString;
140
+ modelName: z.ZodBranded<z.ZodString, "ModelName">;
141
141
  inputTokens: z.ZodNumber;
142
142
  outputTokens: z.ZodNumber;
143
143
  cacheCreationTokens: z.ZodNumber;
144
144
  cacheReadTokens: z.ZodNumber;
145
145
  cost: z.ZodNumber;
146
146
  }, "strip", z.ZodTypeAny, {
147
- modelName: string;
147
+ modelName: string & z.BRAND<"ModelName">;
148
148
  inputTokens: number;
149
149
  outputTokens: number;
150
150
  cacheCreationTokens: number;
@@ -166,22 +166,22 @@ type ModelBreakdown = z.infer<typeof modelBreakdownSchema>;
166
166
  * Zod schema for daily usage aggregation data
167
167
  */
168
168
  declare const dailyUsageSchema: z.ZodObject<{
169
- date: z.ZodString;
169
+ date: z.ZodBranded<z.ZodString, "DailyDate">;
170
170
  inputTokens: z.ZodNumber;
171
171
  outputTokens: z.ZodNumber;
172
172
  cacheCreationTokens: z.ZodNumber;
173
173
  cacheReadTokens: z.ZodNumber;
174
174
  totalCost: z.ZodNumber;
175
- modelsUsed: z.ZodArray<z.ZodString, "many">;
175
+ modelsUsed: z.ZodArray<z.ZodBranded<z.ZodString, "ModelName">, "many">;
176
176
  modelBreakdowns: z.ZodArray<z.ZodObject<{
177
- modelName: z.ZodString;
177
+ modelName: z.ZodBranded<z.ZodString, "ModelName">;
178
178
  inputTokens: z.ZodNumber;
179
179
  outputTokens: z.ZodNumber;
180
180
  cacheCreationTokens: z.ZodNumber;
181
181
  cacheReadTokens: z.ZodNumber;
182
182
  cost: z.ZodNumber;
183
183
  }, "strip", z.ZodTypeAny, {
184
- modelName: string;
184
+ modelName: string & z.BRAND<"ModelName">;
185
185
  inputTokens: number;
186
186
  outputTokens: number;
187
187
  cacheCreationTokens: number;
@@ -196,15 +196,15 @@ declare const dailyUsageSchema: z.ZodObject<{
196
196
  cost: number;
197
197
  }>, "many">;
198
198
  }, "strip", z.ZodTypeAny, {
199
- date: string;
199
+ date: string & z.BRAND<"DailyDate">;
200
200
  inputTokens: number;
201
201
  outputTokens: number;
202
202
  cacheCreationTokens: number;
203
203
  cacheReadTokens: number;
204
204
  totalCost: number;
205
- modelsUsed: string[];
205
+ modelsUsed: (string & z.BRAND<"ModelName">)[];
206
206
  modelBreakdowns: {
207
- modelName: string;
207
+ modelName: string & z.BRAND<"ModelName">;
208
208
  inputTokens: number;
209
209
  outputTokens: number;
210
210
  cacheCreationTokens: number;
@@ -236,25 +236,25 @@ type DailyUsage = z.infer<typeof dailyUsageSchema>;
236
236
  * Zod schema for session-based usage aggregation data
237
237
  */
238
238
  declare const sessionUsageSchema: z.ZodObject<{
239
- sessionId: z.ZodString;
240
- projectPath: z.ZodString;
239
+ sessionId: z.ZodBranded<z.ZodString, "SessionId">;
240
+ projectPath: z.ZodBranded<z.ZodString, "ProjectPath">;
241
241
  inputTokens: z.ZodNumber;
242
242
  outputTokens: z.ZodNumber;
243
243
  cacheCreationTokens: z.ZodNumber;
244
244
  cacheReadTokens: z.ZodNumber;
245
245
  totalCost: z.ZodNumber;
246
- lastActivity: z.ZodString;
247
- versions: z.ZodArray<z.ZodString, "many">;
248
- modelsUsed: z.ZodArray<z.ZodString, "many">;
246
+ lastActivity: z.ZodBranded<z.ZodString, "ActivityDate">;
247
+ versions: z.ZodArray<z.ZodBranded<z.ZodString, "Version">, "many">;
248
+ modelsUsed: z.ZodArray<z.ZodBranded<z.ZodString, "ModelName">, "many">;
249
249
  modelBreakdowns: z.ZodArray<z.ZodObject<{
250
- modelName: z.ZodString;
250
+ modelName: z.ZodBranded<z.ZodString, "ModelName">;
251
251
  inputTokens: z.ZodNumber;
252
252
  outputTokens: z.ZodNumber;
253
253
  cacheCreationTokens: z.ZodNumber;
254
254
  cacheReadTokens: z.ZodNumber;
255
255
  cost: z.ZodNumber;
256
256
  }, "strip", z.ZodTypeAny, {
257
- modelName: string;
257
+ modelName: string & z.BRAND<"ModelName">;
258
258
  inputTokens: number;
259
259
  outputTokens: number;
260
260
  cacheCreationTokens: number;
@@ -269,18 +269,18 @@ declare const sessionUsageSchema: z.ZodObject<{
269
269
  cost: number;
270
270
  }>, "many">;
271
271
  }, "strip", z.ZodTypeAny, {
272
- sessionId: string;
273
- projectPath: string;
272
+ sessionId: string & z.BRAND<"SessionId">;
273
+ projectPath: string & z.BRAND<"ProjectPath">;
274
274
  inputTokens: number;
275
275
  outputTokens: number;
276
276
  cacheCreationTokens: number;
277
277
  cacheReadTokens: number;
278
278
  totalCost: number;
279
- lastActivity: string;
280
- versions: string[];
281
- modelsUsed: string[];
279
+ lastActivity: string & z.BRAND<"ActivityDate">;
280
+ versions: (string & z.BRAND<"Version">)[];
281
+ modelsUsed: (string & z.BRAND<"ModelName">)[];
282
282
  modelBreakdowns: {
283
- modelName: string;
283
+ modelName: string & z.BRAND<"ModelName">;
284
284
  inputTokens: number;
285
285
  outputTokens: number;
286
286
  cacheCreationTokens: number;
@@ -315,22 +315,22 @@ type SessionUsage = z.infer<typeof sessionUsageSchema>;
315
315
  * Zod schema for monthly usage aggregation data
316
316
  */
317
317
  declare const monthlyUsageSchema: z.ZodObject<{
318
- month: z.ZodString;
318
+ month: z.ZodBranded<z.ZodString, "MonthlyDate">;
319
319
  inputTokens: z.ZodNumber;
320
320
  outputTokens: z.ZodNumber;
321
321
  cacheCreationTokens: z.ZodNumber;
322
322
  cacheReadTokens: z.ZodNumber;
323
323
  totalCost: z.ZodNumber;
324
- modelsUsed: z.ZodArray<z.ZodString, "many">;
324
+ modelsUsed: z.ZodArray<z.ZodBranded<z.ZodString, "ModelName">, "many">;
325
325
  modelBreakdowns: z.ZodArray<z.ZodObject<{
326
- modelName: z.ZodString;
326
+ modelName: z.ZodBranded<z.ZodString, "ModelName">;
327
327
  inputTokens: z.ZodNumber;
328
328
  outputTokens: z.ZodNumber;
329
329
  cacheCreationTokens: z.ZodNumber;
330
330
  cacheReadTokens: z.ZodNumber;
331
331
  cost: z.ZodNumber;
332
332
  }, "strip", z.ZodTypeAny, {
333
- modelName: string;
333
+ modelName: string & z.BRAND<"ModelName">;
334
334
  inputTokens: number;
335
335
  outputTokens: number;
336
336
  cacheCreationTokens: number;
@@ -345,15 +345,15 @@ declare const monthlyUsageSchema: z.ZodObject<{
345
345
  cost: number;
346
346
  }>, "many">;
347
347
  }, "strip", z.ZodTypeAny, {
348
- month: string;
348
+ month: string & z.BRAND<"MonthlyDate">;
349
349
  inputTokens: number;
350
350
  outputTokens: number;
351
351
  cacheCreationTokens: number;
352
352
  cacheReadTokens: number;
353
353
  totalCost: number;
354
- modelsUsed: string[];
354
+ modelsUsed: (string & z.BRAND<"ModelName">)[];
355
355
  modelBreakdowns: {
356
- modelName: string;
356
+ modelName: string & z.BRAND<"ModelName">;
357
357
  inputTokens: number;
358
358
  outputTokens: number;
359
359
  cacheCreationTokens: number;
@@ -1,3 +1,3 @@
1
- import "./pricing-fetcher-BkOpRIdx.js";
2
- import { DailyUsage, DateFilter, LoadOptions, ModelBreakdown, MonthlyUsage, SessionUsage, UsageData, calculateCostForEntry, createUniqueHash, dailyUsageSchema, formatDate, formatDateCompact, getDefaultClaudePath, getEarliestTimestamp, loadDailyUsageData, loadMonthlyUsageData, loadSessionBlockData, loadSessionData, modelBreakdownSchema, monthlyUsageSchema, sessionUsageSchema, sortFilesByTimestamp, usageDataSchema } from "./data-loader-CBwn9vk0.js";
1
+ import "./pricing-fetcher-A6FC8DhM.js";
2
+ import { DailyUsage, DateFilter, LoadOptions, ModelBreakdown, MonthlyUsage, SessionUsage, UsageData, calculateCostForEntry, createUniqueHash, dailyUsageSchema, formatDate, formatDateCompact, getDefaultClaudePath, getEarliestTimestamp, loadDailyUsageData, loadMonthlyUsageData, loadSessionBlockData, loadSessionData, modelBreakdownSchema, monthlyUsageSchema, sessionUsageSchema, sortFilesByTimestamp, usageDataSchema } from "./data-loader-BrxITdVN.js";
3
3
  export { DailyUsage, DateFilter, LoadOptions, ModelBreakdown, MonthlyUsage, SessionUsage, UsageData, calculateCostForEntry, createUniqueHash, dailyUsageSchema, formatDate, formatDateCompact, getDefaultClaudePath, getEarliestTimestamp, loadDailyUsageData, loadMonthlyUsageData, loadSessionBlockData, loadSessionData, modelBreakdownSchema, monthlyUsageSchema, sessionUsageSchema, sortFilesByTimestamp, usageDataSchema };
@@ -1,4 +1,5 @@
1
- import "./pricing-fetcher-mFPZYGXl.js";
2
- import { calculateCostForEntry, createUniqueHash, dailyUsageSchema, formatDate, formatDateCompact, getDefaultClaudePath, getEarliestTimestamp, loadDailyUsageData, loadMonthlyUsageData, loadSessionBlockData, loadSessionData, modelBreakdownSchema, monthlyUsageSchema, sessionUsageSchema, sortFilesByTimestamp, usageDataSchema } from "./data-loader-i0_91kbD.js";
3
- import "./logger-BfzGx5lS.js";
1
+ import "./pricing-fetcher-Cx71zrV9.js";
2
+ import "./types.internal-CX7kpidj.js";
3
+ import { calculateCostForEntry, createUniqueHash, dailyUsageSchema, formatDate, formatDateCompact, getDefaultClaudePath, getEarliestTimestamp, loadDailyUsageData, loadMonthlyUsageData, loadSessionBlockData, loadSessionData, modelBreakdownSchema, monthlyUsageSchema, sessionUsageSchema, sortFilesByTimestamp, usageDataSchema } from "./data-loader-B8gFJPfi.js";
4
+ import "./logger-B4PJ298G.js";
4
5
  export { calculateCostForEntry, createUniqueHash, dailyUsageSchema, formatDate, formatDateCompact, getDefaultClaudePath, getEarliestTimestamp, loadDailyUsageData, loadMonthlyUsageData, loadSessionBlockData, loadSessionData, modelBreakdownSchema, monthlyUsageSchema, sessionUsageSchema, sortFilesByTimestamp, usageDataSchema };
@@ -1,15 +1,10 @@
1
- import { PricingFetcher, __toESM, require_usingCtx } from "./pricing-fetcher-mFPZYGXl.js";
2
- import { glob, usageDataSchema } from "./data-loader-i0_91kbD.js";
3
- import { logger } from "./logger-BfzGx5lS.js";
1
+ import { CLAUDE_PROJECTS_DIR_NAME, DEBUG_MATCH_THRESHOLD_PERCENT, DEFAULT_CLAUDE_CODE_PATH, PricingFetcher, USAGE_DATA_GLOB_PATTERN, USER_HOME_DIR, __toESM, require_usingCtx } from "./pricing-fetcher-Cx71zrV9.js";
2
+ import { glob, usageDataSchema } from "./data-loader-B8gFJPfi.js";
3
+ import { logger } from "./logger-B4PJ298G.js";
4
4
  import { readFile } from "node:fs/promises";
5
- import { homedir } from "node:os";
6
5
  import path from "node:path";
7
6
  var import_usingCtx = __toESM(require_usingCtx(), 1);
8
7
  /**
9
- * Threshold percentage for considering costs as matching (0.1% tolerance)
10
- */
11
- const MATCH_THRESHOLD_PERCENT = .1;
12
- /**
13
8
  * Analyzes usage data to detect pricing mismatches between stored and calculated costs
14
9
  * Compares pre-calculated costUSD values with costs calculated from token usage
15
10
  * @param claudePath - Optional path to Claude data directory
@@ -18,8 +13,8 @@ const MATCH_THRESHOLD_PERCENT = .1;
18
13
  async function detectMismatches(claudePath) {
19
14
  try {
20
15
  var _usingCtx = (0, import_usingCtx.default)();
21
- const claudeDir = claudePath ?? path.join(homedir(), ".claude", "projects");
22
- const files = await glob(["**/*.jsonl"], {
16
+ const claudeDir = claudePath ?? path.join(USER_HOME_DIR, DEFAULT_CLAUDE_CODE_PATH, CLAUDE_PROJECTS_DIR_NAME);
17
+ const files = await glob([USAGE_DATA_GLOB_PATTERN], {
23
18
  cwd: claudeDir,
24
19
  absolute: true
25
20
  });
@@ -63,7 +58,7 @@ async function detectMismatches(claudePath) {
63
58
  avgPercentDiff: 0
64
59
  };
65
60
  versionStat.total++;
66
- if (percentDiff < MATCH_THRESHOLD_PERCENT) versionStat.matches++;
61
+ if (percentDiff < DEBUG_MATCH_THRESHOLD_PERCENT) versionStat.matches++;
67
62
  else versionStat.mismatches++;
68
63
  versionStat.avgPercentDiff = (versionStat.avgPercentDiff * (versionStat.total - 1) + percentDiff) / versionStat.total;
69
64
  stats.versionStats.set(data.version, versionStat);
package/dist/debug.js CHANGED
@@ -1,5 +1,6 @@
1
- import "./pricing-fetcher-mFPZYGXl.js";
2
- import "./data-loader-i0_91kbD.js";
3
- import "./logger-BfzGx5lS.js";
4
- import { detectMismatches, printMismatchReport } from "./debug-DUZvOm08.js";
1
+ import "./pricing-fetcher-Cx71zrV9.js";
2
+ import "./types.internal-CX7kpidj.js";
3
+ import "./data-loader-B8gFJPfi.js";
4
+ import "./logger-B4PJ298G.js";
5
+ import { detectMismatches, printMismatchReport } from "./debug-CL2Shx1n.js";
5
6
  export { detectMismatches, printMismatchReport };