ccusage 0.6.1 → 0.7.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/dist/index.js CHANGED
@@ -1,13 +1,13 @@
1
1
  #!/usr/bin/env node
2
- import { __commonJS, __require, __toESM, getDefaultClaudePath, loadDailyUsageData, loadMonthlyUsageData, loadSessionData } from "./data-loader-DP5qBPn6.js";
2
+ import { __commonJS, __require, __toESM, formatCurrency, formatModelsDisplay, formatNumber, getDefaultClaudePath, loadDailyUsageData, loadMonthlyUsageData, loadSessionData, pushBreakdownRows, require_picocolors } from "./data-loader-nOFcMg_V.js";
3
3
  import { calculateTotals, createTotalsObject, getTotalTokens } from "./calculate-cost-2IwHSzmi.js";
4
- import { safeParse } from "./dist-C0-Tf5eD.js";
5
- import { description, log, logger, name, version } from "./logger-DsQC4OvA.js";
6
- import "./pricing-fetcher-BPUgMrB_.js";
7
- import { detectMismatches, printMismatchReport } from "./debug-C_5Qx11m.js";
8
- import { CostModes, SortOrders, createMcpServer, dateSchema } from "./mcp-BQdv12mr.js";
4
+ import { safeParse } from "./dist-BEQ1tJCL.js";
5
+ import { description, log, logger, name, version } from "./logger-BPjA3VFO.js";
6
+ import "./pricing-fetcher-CAeJvZnF.js";
7
+ import { detectMismatches, printMismatchReport } from "./debug-Bttss7TN.js";
8
+ import { CostModes, SortOrders, createMcpServer, dateSchema } from "./mcp-DCEVbd8C.js";
9
9
  import "./types-DS8M8QF_.js";
10
- import "./index-CISmcbXk-DCA05NUL.js";
10
+ import "./index-CISmcbXk-x9eVmhGM.js";
11
11
  import g$1 from "node:process";
12
12
 
13
13
  //#region node_modules/gunshi/lib/utils-D41C8Abf.js
@@ -175,7 +175,7 @@ const BUILT_IN_PREFIX_CODE = BUILT_IN_PREFIX.codePointAt(0);
175
175
  * @param param A {@link CommandContextParams | parameters} to create a {@link CommandContext | command context}
176
176
  * @returns A {@link CommandContext | command context}, which is readonly
177
177
  */
178
- async function createCommandContext({ args, values, positionals, rest, argv: argv$1, tokens, command, cliOptions, callMode = "entry", omitted = false }) {
178
+ async function createCommandContext({ args, values, positionals, rest, argv, tokens, command, cliOptions, callMode = "entry", omitted = false }) {
179
179
  /**
180
180
  * normailize the options schema and values, to avoid prototype pollution
181
181
  */
@@ -186,7 +186,7 @@ async function createCommandContext({ args, values, positionals, rest, argv: arg
186
186
  /**
187
187
  * setup the environment
188
188
  */
189
- const env$2 = Object.assign(create(), COMMAND_OPTIONS_DEFAULT, cliOptions);
189
+ const env$1 = Object.assign(create(), COMMAND_OPTIONS_DEFAULT, cliOptions);
190
190
  const locale = resolveLocale(cliOptions.locale);
191
191
  const localeStr = locale.toString();
192
192
  const translationAdapterFactory = cliOptions.translationAdapterFactory || createTranslationAdapter;
@@ -233,12 +233,12 @@ async function createCommandContext({ args, values, positionals, rest, argv: arg
233
233
  omitted,
234
234
  callMode,
235
235
  locale,
236
- env: env$2,
236
+ env: env$1,
237
237
  args: _args,
238
238
  values,
239
239
  positionals,
240
240
  rest,
241
- _: argv$1,
241
+ _: argv,
242
242
  tokens,
243
243
  toKebab: command.toKebab,
244
244
  log: cliOptions.usageSilent ? NOOP : log$1,
@@ -1009,9 +1009,9 @@ function createTypeError(option, schema) {
1009
1009
  * @param options A {@link CliOptions | CLI options}
1010
1010
  * @returns A rendered usage or undefined. if you will use {@link CliOptions.usageSilent} option, it will return rendered usage string.
1011
1011
  */
1012
- async function cli(argv$1, entry, options = {}) {
1012
+ async function cli(argv, entry, options = {}) {
1013
1013
  const cliOptions = resolveCliOptions(options, entry);
1014
- const tokens = parseArgs(argv$1);
1014
+ const tokens = parseArgs(argv);
1015
1015
  const subCommand = getSubCommand(tokens);
1016
1016
  const { commandName: name$1, command, callMode } = await resolveCommand(subCommand, entry, cliOptions);
1017
1017
  if (!command) throw new Error(`Command not found: ${name$1 || ""}`);
@@ -1027,7 +1027,7 @@ async function cli(argv$1, entry, options = {}) {
1027
1027
  values,
1028
1028
  positionals,
1029
1029
  rest,
1030
- argv: argv$1,
1030
+ argv,
1031
1031
  tokens,
1032
1032
  omitted,
1033
1033
  callMode,
@@ -1582,11 +1582,11 @@ var require_styles = __commonJS({ "node_modules/@colors/colors/lib/styles.js"(ex
1582
1582
  //#endregion
1583
1583
  //#region node_modules/@colors/colors/lib/system/has-flag.js
1584
1584
  var require_has_flag = __commonJS({ "node_modules/@colors/colors/lib/system/has-flag.js"(exports, module) {
1585
- module.exports = function(flag, argv$1) {
1586
- argv$1 = argv$1 || process.argv;
1587
- var terminatorPos = argv$1.indexOf("--");
1585
+ module.exports = function(flag, argv) {
1586
+ argv = argv || process.argv;
1587
+ var terminatorPos = argv.indexOf("--");
1588
1588
  var prefix = /^-{1,2}/.test(flag) ? "" : "--";
1589
- var pos = argv$1.indexOf(prefix + flag);
1589
+ var pos = argv.indexOf(prefix + flag);
1590
1590
  return pos !== -1 && (terminatorPos === -1 ? true : pos < terminatorPos);
1591
1591
  };
1592
1592
  } });
@@ -1596,11 +1596,11 @@ var require_has_flag = __commonJS({ "node_modules/@colors/colors/lib/system/has-
1596
1596
  var require_supports_colors = __commonJS({ "node_modules/@colors/colors/lib/system/supports-colors.js"(exports, module) {
1597
1597
  var os = __require("os");
1598
1598
  var hasFlag = require_has_flag();
1599
- var env$1 = process.env;
1599
+ var env = process.env;
1600
1600
  var forceColor = void 0;
1601
1601
  if (hasFlag("no-color") || hasFlag("no-colors") || hasFlag("color=false")) forceColor = false;
1602
1602
  else if (hasFlag("color") || hasFlag("colors") || hasFlag("color=true") || hasFlag("color=always")) forceColor = true;
1603
- if ("FORCE_COLOR" in env$1) forceColor = env$1.FORCE_COLOR.length === 0 || parseInt(env$1.FORCE_COLOR, 10) !== 0;
1603
+ if ("FORCE_COLOR" in env) forceColor = env.FORCE_COLOR.length === 0 || parseInt(env.FORCE_COLOR, 10) !== 0;
1604
1604
  function translateLevel(level$1) {
1605
1605
  if (level$1 === 0) return false;
1606
1606
  return {
@@ -1621,30 +1621,30 @@ var require_supports_colors = __commonJS({ "node_modules/@colors/colors/lib/syst
1621
1621
  if (Number(process.versions.node.split(".")[0]) >= 8 && Number(osRelease[0]) >= 10 && Number(osRelease[2]) >= 10586) return Number(osRelease[2]) >= 14931 ? 3 : 2;
1622
1622
  return 1;
1623
1623
  }
1624
- if ("CI" in env$1) {
1624
+ if ("CI" in env) {
1625
1625
  if ([
1626
1626
  "TRAVIS",
1627
1627
  "CIRCLECI",
1628
1628
  "APPVEYOR",
1629
1629
  "GITLAB_CI"
1630
1630
  ].some(function(sign) {
1631
- return sign in env$1;
1632
- }) || env$1.CI_NAME === "codeship") return 1;
1631
+ return sign in env;
1632
+ }) || env.CI_NAME === "codeship") return 1;
1633
1633
  return min;
1634
1634
  }
1635
- if ("TEAMCITY_VERSION" in env$1) return /^(9\.(0*[1-9]\d*)\.|\d{2,}\.)/.test(env$1.TEAMCITY_VERSION) ? 1 : 0;
1636
- if ("TERM_PROGRAM" in env$1) {
1637
- var version$2 = parseInt((env$1.TERM_PROGRAM_VERSION || "").split(".")[0], 10);
1638
- switch (env$1.TERM_PROGRAM) {
1635
+ if ("TEAMCITY_VERSION" in env) return /^(9\.(0*[1-9]\d*)\.|\d{2,}\.)/.test(env.TEAMCITY_VERSION) ? 1 : 0;
1636
+ if ("TERM_PROGRAM" in env) {
1637
+ var version$2 = parseInt((env.TERM_PROGRAM_VERSION || "").split(".")[0], 10);
1638
+ switch (env.TERM_PROGRAM) {
1639
1639
  case "iTerm.app": return version$2 >= 3 ? 3 : 2;
1640
1640
  case "Hyper": return 3;
1641
1641
  case "Apple_Terminal": return 2;
1642
1642
  }
1643
1643
  }
1644
- if (/-256(color)?$/i.test(env$1.TERM)) return 2;
1645
- if (/^screen|^xterm|^vt100|^rxvt|color|ansi|cygwin|linux/i.test(env$1.TERM)) return 1;
1646
- if ("COLORTERM" in env$1) return 1;
1647
- if (env$1.TERM === "dumb") return min;
1644
+ if (/-256(color)?$/i.test(env.TERM)) return 2;
1645
+ if (/^screen|^xterm|^vt100|^rxvt|color|ansi|cygwin|linux/i.test(env.TERM)) return 1;
1646
+ if ("COLORTERM" in env) return 1;
1647
+ if (env.TERM === "dumb") return min;
1648
1648
  return min;
1649
1649
  }
1650
1650
  function getSupportLevel(stream) {
@@ -2813,75 +2813,6 @@ var require_cli_table3 = __commonJS({ "node_modules/cli-table3/index.js"(exports
2813
2813
  module.exports = require_table();
2814
2814
  } });
2815
2815
 
2816
- //#endregion
2817
- //#region node_modules/picocolors/picocolors.js
2818
- var require_picocolors = __commonJS({ "node_modules/picocolors/picocolors.js"(exports, module) {
2819
- let p = process || {}, argv = p.argv || [], env = p.env || {};
2820
- let isColorSupported = !(!!env.NO_COLOR || argv.includes("--no-color")) && (!!env.FORCE_COLOR || argv.includes("--color") || p.platform === "win32" || (p.stdout || {}).isTTY && env.TERM !== "dumb" || !!env.CI);
2821
- let formatter = (open, close, replace = open) => (input) => {
2822
- let string = "" + input, index = string.indexOf(close, open.length);
2823
- return ~index ? open + replaceClose(string, close, replace, index) + close : open + string + close;
2824
- };
2825
- let replaceClose = (string, close, replace, index) => {
2826
- let result = "", cursor = 0;
2827
- do {
2828
- result += string.substring(cursor, index) + replace;
2829
- cursor = index + close.length;
2830
- index = string.indexOf(close, cursor);
2831
- } while (~index);
2832
- return result + string.substring(cursor);
2833
- };
2834
- let createColors = (enabled = isColorSupported) => {
2835
- let f = enabled ? formatter : () => String;
2836
- return {
2837
- isColorSupported: enabled,
2838
- reset: f("\x1B[0m", "\x1B[0m"),
2839
- bold: f("\x1B[1m", "\x1B[22m", "\x1B[22m\x1B[1m"),
2840
- dim: f("\x1B[2m", "\x1B[22m", "\x1B[22m\x1B[2m"),
2841
- italic: f("\x1B[3m", "\x1B[23m"),
2842
- underline: f("\x1B[4m", "\x1B[24m"),
2843
- inverse: f("\x1B[7m", "\x1B[27m"),
2844
- hidden: f("\x1B[8m", "\x1B[28m"),
2845
- strikethrough: f("\x1B[9m", "\x1B[29m"),
2846
- black: f("\x1B[30m", "\x1B[39m"),
2847
- red: f("\x1B[31m", "\x1B[39m"),
2848
- green: f("\x1B[32m", "\x1B[39m"),
2849
- yellow: f("\x1B[33m", "\x1B[39m"),
2850
- blue: f("\x1B[34m", "\x1B[39m"),
2851
- magenta: f("\x1B[35m", "\x1B[39m"),
2852
- cyan: f("\x1B[36m", "\x1B[39m"),
2853
- white: f("\x1B[37m", "\x1B[39m"),
2854
- gray: f("\x1B[90m", "\x1B[39m"),
2855
- bgBlack: f("\x1B[40m", "\x1B[49m"),
2856
- bgRed: f("\x1B[41m", "\x1B[49m"),
2857
- bgGreen: f("\x1B[42m", "\x1B[49m"),
2858
- bgYellow: f("\x1B[43m", "\x1B[49m"),
2859
- bgBlue: f("\x1B[44m", "\x1B[49m"),
2860
- bgMagenta: f("\x1B[45m", "\x1B[49m"),
2861
- bgCyan: f("\x1B[46m", "\x1B[49m"),
2862
- bgWhite: f("\x1B[47m", "\x1B[49m"),
2863
- blackBright: f("\x1B[90m", "\x1B[39m"),
2864
- redBright: f("\x1B[91m", "\x1B[39m"),
2865
- greenBright: f("\x1B[92m", "\x1B[39m"),
2866
- yellowBright: f("\x1B[93m", "\x1B[39m"),
2867
- blueBright: f("\x1B[94m", "\x1B[39m"),
2868
- magentaBright: f("\x1B[95m", "\x1B[39m"),
2869
- cyanBright: f("\x1B[96m", "\x1B[39m"),
2870
- whiteBright: f("\x1B[97m", "\x1B[39m"),
2871
- bgBlackBright: f("\x1B[100m", "\x1B[49m"),
2872
- bgRedBright: f("\x1B[101m", "\x1B[49m"),
2873
- bgGreenBright: f("\x1B[102m", "\x1B[49m"),
2874
- bgYellowBright: f("\x1B[103m", "\x1B[49m"),
2875
- bgBlueBright: f("\x1B[104m", "\x1B[49m"),
2876
- bgMagentaBright: f("\x1B[105m", "\x1B[49m"),
2877
- bgCyanBright: f("\x1B[106m", "\x1B[49m"),
2878
- bgWhiteBright: f("\x1B[107m", "\x1B[49m")
2879
- };
2880
- };
2881
- module.exports = createColors();
2882
- module.exports.createColors = createColors;
2883
- } });
2884
-
2885
2816
  //#endregion
2886
2817
  //#region src/shared-args.internal.ts
2887
2818
  function parseDateArg(value) {
@@ -2938,6 +2869,12 @@ const sharedArgs = {
2938
2869
  description: "Sort order: desc (newest first) or asc (oldest first)",
2939
2870
  default: "asc",
2940
2871
  choices: SortOrders
2872
+ },
2873
+ breakdown: {
2874
+ type: "boolean",
2875
+ short: "b",
2876
+ description: "Show per-model cost breakdown",
2877
+ default: false
2941
2878
  }
2942
2879
  };
2943
2880
  const sharedCommandConfig = {
@@ -2945,15 +2882,6 @@ const sharedCommandConfig = {
2945
2882
  toKebab: true
2946
2883
  };
2947
2884
 
2948
- //#endregion
2949
- //#region src/utils.internal.ts
2950
- function formatNumber(num) {
2951
- return num.toLocaleString("en-US");
2952
- }
2953
- function formatCurrency(amount) {
2954
- return `$${amount.toFixed(2)}`;
2955
- }
2956
-
2957
2885
  //#endregion
2958
2886
  //#region src/commands/daily.ts
2959
2887
  var import_cli_table3$2 = __toESM(require_cli_table3(), 1);
@@ -2990,7 +2918,9 @@ const dailyCommand = define({
2990
2918
  cacheCreationTokens: data.cacheCreationTokens,
2991
2919
  cacheReadTokens: data.cacheReadTokens,
2992
2920
  totalTokens: getTotalTokens(data),
2993
- totalCost: data.totalCost
2921
+ totalCost: data.totalCost,
2922
+ modelsUsed: data.modelsUsed,
2923
+ modelBreakdowns: data.modelBreakdowns
2994
2924
  })),
2995
2925
  totals: createTotalsObject(totals)
2996
2926
  };
@@ -3000,6 +2930,7 @@ const dailyCommand = define({
3000
2930
  const table = new import_cli_table3$2.default({
3001
2931
  head: [
3002
2932
  "Date",
2933
+ "Models",
3003
2934
  "Input",
3004
2935
  "Output",
3005
2936
  "Cache Create",
@@ -3009,6 +2940,7 @@ const dailyCommand = define({
3009
2940
  ],
3010
2941
  style: { head: ["cyan"] },
3011
2942
  colAligns: [
2943
+ "left",
3012
2944
  "left",
3013
2945
  "right",
3014
2946
  "right",
@@ -3018,15 +2950,19 @@ const dailyCommand = define({
3018
2950
  "right"
3019
2951
  ]
3020
2952
  });
3021
- for (const data of dailyData) table.push([
3022
- data.date,
3023
- formatNumber(data.inputTokens),
3024
- formatNumber(data.outputTokens),
3025
- formatNumber(data.cacheCreationTokens),
3026
- formatNumber(data.cacheReadTokens),
3027
- formatNumber(getTotalTokens(data)),
3028
- formatCurrency(data.totalCost)
3029
- ]);
2953
+ for (const data of dailyData) {
2954
+ table.push([
2955
+ data.date,
2956
+ formatModelsDisplay(data.modelsUsed),
2957
+ formatNumber(data.inputTokens),
2958
+ formatNumber(data.outputTokens),
2959
+ formatNumber(data.cacheCreationTokens),
2960
+ formatNumber(data.cacheReadTokens),
2961
+ formatNumber(getTotalTokens(data)),
2962
+ formatCurrency(data.totalCost)
2963
+ ]);
2964
+ if (ctx.values.breakdown) pushBreakdownRows(table, data.modelBreakdowns);
2965
+ }
3030
2966
  table.push([
3031
2967
  "─".repeat(12),
3032
2968
  "─".repeat(12),
@@ -3034,10 +2970,12 @@ const dailyCommand = define({
3034
2970
  "─".repeat(12),
3035
2971
  "─".repeat(12),
3036
2972
  "─".repeat(12),
2973
+ "─".repeat(12),
3037
2974
  "─".repeat(10)
3038
2975
  ]);
3039
2976
  table.push([
3040
2977
  import_picocolors$2.default.yellow("Total"),
2978
+ "",
3041
2979
  import_picocolors$2.default.yellow(formatNumber(totals.inputTokens)),
3042
2980
  import_picocolors$2.default.yellow(formatNumber(totals.outputTokens)),
3043
2981
  import_picocolors$2.default.yellow(formatNumber(totals.cacheCreationTokens)),
@@ -3133,7 +3071,9 @@ const monthlyCommand = define({
3133
3071
  cacheCreationTokens: data.cacheCreationTokens,
3134
3072
  cacheReadTokens: data.cacheReadTokens,
3135
3073
  totalTokens: getTotalTokens(data),
3136
- totalCost: data.totalCost
3074
+ totalCost: data.totalCost,
3075
+ modelsUsed: data.modelsUsed,
3076
+ modelBreakdowns: data.modelBreakdowns
3137
3077
  })),
3138
3078
  totals: createTotalsObject(totals)
3139
3079
  };
@@ -3143,6 +3083,7 @@ const monthlyCommand = define({
3143
3083
  const table = new import_cli_table3$1.default({
3144
3084
  head: [
3145
3085
  "Month",
3086
+ "Models",
3146
3087
  "Input",
3147
3088
  "Output",
3148
3089
  "Cache Create",
@@ -3152,6 +3093,7 @@ const monthlyCommand = define({
3152
3093
  ],
3153
3094
  style: { head: ["cyan"] },
3154
3095
  colAligns: [
3096
+ "left",
3155
3097
  "left",
3156
3098
  "right",
3157
3099
  "right",
@@ -3161,15 +3103,19 @@ const monthlyCommand = define({
3161
3103
  "right"
3162
3104
  ]
3163
3105
  });
3164
- for (const data of monthlyData) table.push([
3165
- data.month,
3166
- formatNumber(data.inputTokens),
3167
- formatNumber(data.outputTokens),
3168
- formatNumber(data.cacheCreationTokens),
3169
- formatNumber(data.cacheReadTokens),
3170
- formatNumber(getTotalTokens(data)),
3171
- formatCurrency(data.totalCost)
3172
- ]);
3106
+ for (const data of monthlyData) {
3107
+ table.push([
3108
+ data.month,
3109
+ formatModelsDisplay(data.modelsUsed),
3110
+ formatNumber(data.inputTokens),
3111
+ formatNumber(data.outputTokens),
3112
+ formatNumber(data.cacheCreationTokens),
3113
+ formatNumber(data.cacheReadTokens),
3114
+ formatNumber(getTotalTokens(data)),
3115
+ formatCurrency(data.totalCost)
3116
+ ]);
3117
+ if (ctx.values.breakdown) pushBreakdownRows(table, data.modelBreakdowns);
3118
+ }
3173
3119
  table.push([
3174
3120
  "─".repeat(12),
3175
3121
  "─".repeat(12),
@@ -3177,10 +3123,12 @@ const monthlyCommand = define({
3177
3123
  "─".repeat(12),
3178
3124
  "─".repeat(12),
3179
3125
  "─".repeat(12),
3126
+ "─".repeat(12),
3180
3127
  "─".repeat(10)
3181
3128
  ]);
3182
3129
  table.push([
3183
3130
  import_picocolors$1.default.yellow("Total"),
3131
+ "",
3184
3132
  import_picocolors$1.default.yellow(formatNumber(totals.inputTokens)),
3185
3133
  import_picocolors$1.default.yellow(formatNumber(totals.outputTokens)),
3186
3134
  import_picocolors$1.default.yellow(formatNumber(totals.cacheCreationTokens)),
@@ -3223,7 +3171,6 @@ const sessionCommand = define({
3223
3171
  if (ctx.values.json) {
3224
3172
  const jsonOutput = {
3225
3173
  sessions: sessionData.map((data) => ({
3226
- projectPath: data.projectPath,
3227
3174
  sessionId: data.sessionId,
3228
3175
  inputTokens: data.inputTokens,
3229
3176
  outputTokens: data.outputTokens,
@@ -3231,7 +3178,9 @@ const sessionCommand = define({
3231
3178
  cacheReadTokens: data.cacheReadTokens,
3232
3179
  totalTokens: getTotalTokens(data),
3233
3180
  totalCost: data.totalCost,
3234
- lastActivity: data.lastActivity
3181
+ lastActivity: data.lastActivity,
3182
+ modelsUsed: data.modelsUsed,
3183
+ modelBreakdowns: data.modelBreakdowns
3235
3184
  })),
3236
3185
  totals: createTotalsObject(totals)
3237
3186
  };
@@ -3240,8 +3189,8 @@ const sessionCommand = define({
3240
3189
  logger.box("Claude Code Token Usage Report - By Session");
3241
3190
  const table = new import_cli_table3.default({
3242
3191
  head: [
3243
- "Project",
3244
3192
  "Session",
3193
+ "Models",
3245
3194
  "Input",
3246
3195
  "Output",
3247
3196
  "Cache Create",
@@ -3263,16 +3212,13 @@ const sessionCommand = define({
3263
3212
  "left"
3264
3213
  ]
3265
3214
  });
3266
- let maxProjectLength = 0;
3267
3215
  let maxSessionLength = 0;
3268
3216
  for (const data of sessionData) {
3269
- const projectDisplay = data.projectPath.length > 20 ? `...${data.projectPath.slice(-17)}` : data.projectPath;
3270
3217
  const sessionDisplay = data.sessionId.split("-").slice(-2).join("-");
3271
- maxProjectLength = Math.max(maxProjectLength, projectDisplay.length);
3272
3218
  maxSessionLength = Math.max(maxSessionLength, sessionDisplay.length);
3273
3219
  table.push([
3274
- projectDisplay,
3275
3220
  sessionDisplay,
3221
+ formatModelsDisplay(data.modelsUsed),
3276
3222
  formatNumber(data.inputTokens),
3277
3223
  formatNumber(data.outputTokens),
3278
3224
  formatNumber(data.cacheCreationTokens),
@@ -3281,15 +3227,16 @@ const sessionCommand = define({
3281
3227
  formatCurrency(data.totalCost),
3282
3228
  data.lastActivity
3283
3229
  ]);
3230
+ if (ctx.values.breakdown) pushBreakdownRows(table, data.modelBreakdowns, 1, 1);
3284
3231
  }
3285
3232
  table.push([
3286
- "─".repeat(maxProjectLength),
3287
3233
  "─".repeat(maxSessionLength),
3288
3234
  "─".repeat(12),
3289
3235
  "─".repeat(12),
3290
3236
  "─".repeat(12),
3291
3237
  "─".repeat(12),
3292
3238
  "─".repeat(12),
3239
+ "─".repeat(12),
3293
3240
  "─".repeat(10),
3294
3241
  "─".repeat(12)
3295
3242
  ]);
@@ -965,7 +965,7 @@ const consola = createConsola$1();
965
965
  //#endregion
966
966
  //#region package.json
967
967
  var name = "ccusage";
968
- var version = "0.6.1";
968
+ var version = "0.7.0";
969
969
  var description = "Usage analysis tool for Claude Code";
970
970
 
971
971
  //#endregion
package/dist/logger.js CHANGED
@@ -1,3 +1,3 @@
1
- import { log, logger } from "./logger-DsQC4OvA.js";
1
+ import { log, logger } from "./logger-BPjA3VFO.js";
2
2
 
3
3
  export { log, logger };
@@ -1,8 +1,8 @@
1
- import { __commonJS, __require, __toESM, getDefaultClaudePath, loadDailyUsageData, loadSessionData } from "./data-loader-DP5qBPn6.js";
2
- import { description, literal, object, optional, pipe, regex, string, union } from "./dist-C0-Tf5eD.js";
3
- import { name, version } from "./logger-DsQC4OvA.js";
1
+ import { __commonJS, __require, __toESM, getDefaultClaudePath, loadDailyUsageData, loadSessionData } from "./data-loader-nOFcMg_V.js";
2
+ import { description, literal, object, optional, pipe, regex, string, union } from "./dist-BEQ1tJCL.js";
3
+ import { name, version } from "./logger-BPjA3VFO.js";
4
4
  import { anyType, arrayType, booleanType, discriminatedUnionType, enumType, literalType, numberType, objectType, optionalType, recordType, stringType, unionType, unknownType } from "./types-DS8M8QF_.js";
5
- import { toJsonSchema } from "./index-CISmcbXk-DCA05NUL.js";
5
+ import { toJsonSchema } from "./index-CISmcbXk-x9eVmhGM.js";
6
6
  import g$1 from "node:process";
7
7
  import { EventEmitter } from "events";
8
8
  import { randomUUID } from "node:crypto";
@@ -2832,8 +2832,8 @@ var require_setprototypeof = __commonJS({ "node_modules/setprototypeof/index.js"
2832
2832
  } });
2833
2833
 
2834
2834
  //#endregion
2835
- //#region node_modules/statuses/codes.json
2836
- var require_codes = __commonJS({ "node_modules/statuses/codes.json"(exports, module) {
2835
+ //#region node_modules/http-errors/node_modules/statuses/codes.json
2836
+ var require_codes = __commonJS({ "node_modules/http-errors/node_modules/statuses/codes.json"(exports, module) {
2837
2837
  module.exports = {
2838
2838
  "100": "Continue",
2839
2839
  "101": "Switching Protocols",
@@ -2902,8 +2902,8 @@ var require_codes = __commonJS({ "node_modules/statuses/codes.json"(exports, mod
2902
2902
  } });
2903
2903
 
2904
2904
  //#endregion
2905
- //#region node_modules/statuses/index.js
2906
- var require_statuses = __commonJS({ "node_modules/statuses/index.js"(exports, module) {
2905
+ //#region node_modules/http-errors/node_modules/statuses/index.js
2906
+ var require_statuses = __commonJS({ "node_modules/http-errors/node_modules/statuses/index.js"(exports, module) {
2907
2907
  /**
2908
2908
  * Module dependencies.
2909
2909
  * @private
@@ -36916,6 +36916,7 @@ var FastMCPSession = class extends FastMCPSessionEventEmitter {
36916
36916
  #clientCapabilities;
36917
36917
  #connectionState = "connecting";
36918
36918
  #loggingLevel = "info";
36919
+ #needsEventLoopFlush = false;
36919
36920
  #pingConfig;
36920
36921
  #pingInterval = null;
36921
36922
  #prompts = [];
@@ -36924,11 +36925,12 @@ var FastMCPSession = class extends FastMCPSessionEventEmitter {
36924
36925
  #roots = [];
36925
36926
  #rootsConfig;
36926
36927
  #server;
36927
- constructor({ auth, instructions, name: name$1, ping, prompts, resources, resourcesTemplates, roots, tools, version: version$1 }) {
36928
+ constructor({ auth, instructions, name: name$1, ping, prompts, resources, resourcesTemplates, roots, tools, transportType, version: version$1 }) {
36928
36929
  super();
36929
36930
  this.#auth = auth;
36930
36931
  this.#pingConfig = ping;
36931
36932
  this.#rootsConfig = roots;
36933
+ this.#needsEventLoopFlush = transportType === "httpStream";
36932
36934
  if (tools.length) this.#capabilities.tools = {};
36933
36935
  if (resources.length || resourcesTemplates.length) this.#capabilities.resources = {};
36934
36936
  if (prompts.length) {
@@ -37271,6 +37273,7 @@ ${e instanceof Error ? e.stack : JSON.stringify(e)}`);
37271
37273
  progressToken
37272
37274
  }
37273
37275
  });
37276
+ if (this.#needsEventLoopFlush) await new Promise((resolve$4) => setImmediate(resolve$4));
37274
37277
  };
37275
37278
  const log$1 = {
37276
37279
  debug: (message, context) => {
@@ -37319,6 +37322,7 @@ ${e instanceof Error ? e.stack : JSON.stringify(e)}`);
37319
37322
  toolName: request$1.params.name
37320
37323
  }
37321
37324
  });
37325
+ if (this.#needsEventLoopFlush) await new Promise((resolve$4) => setImmediate(resolve$4));
37322
37326
  };
37323
37327
  const executeToolPromise = tool.execute(args, {
37324
37328
  log: log$1,
@@ -37464,6 +37468,7 @@ var FastMCP = class extends FastMCPEventEmitter {
37464
37468
  resourcesTemplates: this.#resourcesTemplates,
37465
37469
  roots: this.#options.roots,
37466
37470
  tools: this.#tools,
37471
+ transportType: "stdio",
37467
37472
  version: this.#options.version
37468
37473
  });
37469
37474
  await session.connect(transport);
@@ -37483,6 +37488,7 @@ var FastMCP = class extends FastMCPEventEmitter {
37483
37488
  resourcesTemplates: this.#resourcesTemplates,
37484
37489
  roots: this.#options.roots,
37485
37490
  tools: this.#tools,
37491
+ transportType: "httpStream",
37486
37492
  version: this.#options.version
37487
37493
  });
37488
37494
  },
package/dist/mcp.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import "./pricing-fetcher-CfEgfzSr.js";
2
- import { LoadOptions } from "./data-loader-VdEcqJHc.js";
1
+ import { LoadOptions } from "./data-loader-pCzn-ryX.js";
2
+ import "./pricing-fetcher-Dq-OLBp4.js";
3
3
  import { FastMCP } from "fastmcp";
4
4
 
5
5
  //#region src/mcp.d.ts
package/dist/mcp.js CHANGED
@@ -1,9 +1,9 @@
1
- import "./data-loader-DP5qBPn6.js";
2
- import "./dist-C0-Tf5eD.js";
3
- import "./logger-DsQC4OvA.js";
4
- import "./pricing-fetcher-BPUgMrB_.js";
5
- import { createMcpServer } from "./mcp-BQdv12mr.js";
1
+ import "./data-loader-nOFcMg_V.js";
2
+ import "./dist-BEQ1tJCL.js";
3
+ import "./logger-BPjA3VFO.js";
4
+ import "./pricing-fetcher-CAeJvZnF.js";
5
+ import { createMcpServer } from "./mcp-DCEVbd8C.js";
6
6
  import "./types-DS8M8QF_.js";
7
- import "./index-CISmcbXk-DCA05NUL.js";
7
+ import "./index-CISmcbXk-x9eVmhGM.js";
8
8
 
9
9
  export { createMcpServer };
@@ -0,0 +1,79 @@
1
+ import { number, object, optional, safeParse } from "./dist-BEQ1tJCL.js";
2
+ import { logger } from "./logger-BPjA3VFO.js";
3
+
4
+ //#region src/pricing-fetcher.ts
5
+ const ModelPricingSchema = object({
6
+ input_cost_per_token: optional(number()),
7
+ output_cost_per_token: optional(number()),
8
+ cache_creation_input_token_cost: optional(number()),
9
+ cache_read_input_token_cost: optional(number())
10
+ });
11
+ const LITELLM_PRICING_URL = "https://raw.githubusercontent.com/BerriAI/litellm/main/model_prices_and_context_window.json";
12
+ var PricingFetcher = class {
13
+ cachedPricing = null;
14
+ constructor() {}
15
+ [Symbol.dispose]() {
16
+ this.clearCache();
17
+ }
18
+ clearCache() {
19
+ this.cachedPricing = null;
20
+ }
21
+ async ensurePricingLoaded() {
22
+ if (this.cachedPricing != null) return this.cachedPricing;
23
+ try {
24
+ logger.warn("Fetching latest model pricing from LiteLLM...");
25
+ const response = await fetch(LITELLM_PRICING_URL);
26
+ if (!response.ok) throw new Error(`Failed to fetch pricing data: ${response.statusText}`);
27
+ const data = await response.json();
28
+ const pricing = /* @__PURE__ */ new Map();
29
+ for (const [modelName, modelData] of Object.entries(data)) if (typeof modelData === "object" && modelData !== null) {
30
+ const parsed = safeParse(ModelPricingSchema, modelData);
31
+ if (parsed.success) pricing.set(modelName, parsed.output);
32
+ }
33
+ this.cachedPricing = pricing;
34
+ logger.info(`Loaded pricing for ${pricing.size} models`);
35
+ return pricing;
36
+ } catch (error) {
37
+ logger.error("Failed to fetch model pricing:", error);
38
+ throw new Error("Could not fetch model pricing data");
39
+ }
40
+ }
41
+ async fetchModelPricing() {
42
+ return this.ensurePricingLoaded();
43
+ }
44
+ async getModelPricing(modelName) {
45
+ const pricing = await this.ensurePricingLoaded();
46
+ const directMatch = pricing.get(modelName);
47
+ if (directMatch != null) return directMatch;
48
+ const variations = [
49
+ modelName,
50
+ `anthropic/${modelName}`,
51
+ `claude-3-5-${modelName}`,
52
+ `claude-3-${modelName}`,
53
+ `claude-${modelName}`
54
+ ];
55
+ for (const variant of variations) {
56
+ const match = pricing.get(variant);
57
+ if (match != null) return match;
58
+ }
59
+ const lowerModel = modelName.toLowerCase();
60
+ for (const [key, value] of pricing) if (key.toLowerCase().includes(lowerModel) || lowerModel.includes(key.toLowerCase())) return value;
61
+ return null;
62
+ }
63
+ async calculateCostFromTokens(tokens, modelName) {
64
+ const pricing = await this.getModelPricing(modelName);
65
+ if (pricing == null) return 0;
66
+ return this.calculateCostFromPricing(tokens, pricing);
67
+ }
68
+ calculateCostFromPricing(tokens, pricing) {
69
+ let cost = 0;
70
+ if (pricing.input_cost_per_token != null) cost += tokens.input_tokens * pricing.input_cost_per_token;
71
+ if (pricing.output_cost_per_token != null) cost += tokens.output_tokens * pricing.output_cost_per_token;
72
+ if (tokens.cache_creation_input_tokens != null && pricing.cache_creation_input_token_cost != null) cost += tokens.cache_creation_input_tokens * pricing.cache_creation_input_token_cost;
73
+ if (tokens.cache_read_input_tokens != null && pricing.cache_read_input_token_cost != null) cost += tokens.cache_read_input_tokens * pricing.cache_read_input_token_cost;
74
+ return cost;
75
+ }
76
+ };
77
+
78
+ //#endregion
79
+ export { PricingFetcher };