ccusage 0.1.12 → 0.2.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.
Files changed (3) hide show
  1. package/README.md +20 -51
  2. package/dist/index.js +87 -42
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -41,10 +41,12 @@ This tool helps you understand the value you're getting from your subscription b
41
41
  - 🎨 **Beautiful Output**: Colorful table-formatted display
42
42
  - 📄 **JSON Output**: Export data in structured JSON format with `--json`
43
43
  - 💰 **Cost Tracking**: Shows costs in USD for each day/session
44
+ - 🔄 **Cache Token Support**: Tracks and displays cache creation and cache read tokens separately
44
45
 
45
46
  ## Limitations
46
47
 
47
48
  - This tool only reads local JSONL files generated by Claude Code. If you use Claude Code with multiple devices, you need to ensure the JSONL files are synchronized across devices.
49
+ - API usage for tools like Web Search, Code Execution, and Image Analysis are not included in the token usage reports. The tool only tracks language model token usage.
48
50
 
49
51
  ## Installation
50
52
 
@@ -151,15 +153,15 @@ All commands support the following options:
151
153
  │ │
152
154
  ╰──────────────────────────────────────────╯
153
155
 
154
- ┌──────────────────┬──────────────┬───────────────┬──────────────┬────────────┐
155
- │ Date │ Input TokensOutput Tokens │ Total Tokens │ Cost (USD) │
156
- ├──────────────────┼──────────────┼───────────────┼──────────────┼────────────┤
157
- │ 2025-05-30 277 │ 31,456 │ 31,733 │ $17.45
158
- │ 2025-05-29 959 │ 39,662 │ 40,621 │ $16.37
159
- │ 2025-05-28 155 │ 21,693 │ 21,848 │ $8.33
160
- ├──────────────────┼──────────────┼───────────────┼──────────────┼────────────┤
161
- │ Total 11,174 │ 720,366 │ 731,540 │ $336.17
162
- └──────────────────┴──────────────┴───────────────┴──────────────┴────────────┘
156
+ ┌──────────────┬────────┬─────────┬──────────────┬────────────┬──────────────┬────────────┐
157
+ │ Date │ Input Output │ Cache Create Cache Read │ Total Tokens │ Cost (USD) │
158
+ ├──────────────┼────────┼─────────┼──────────────┼────────────┼──────────────┼────────────┤
159
+ │ 2025-05-30 277 │ 31,456 │ 512 │ 1,024 │ 33,269 │ $17.58
160
+ │ 2025-05-29 959 │ 39,662 │ 256 │ 768 │ 41,645 │ $16.42
161
+ │ 2025-05-28 155 │ 21,693 │ 128 │ 512 │ 22,488 │ $8.36
162
+ ├──────────────┼────────┼─────────┼──────────────┼────────────┼──────────────┼────────────┤
163
+ │ Total 11,174 │ 720,366 │ 896 │ 2,304 734,740 │ $336.47
164
+ └──────────────┴────────┴─────────┴──────────────┴────────────┴──────────────┴────────────┘
163
165
  ```
164
166
 
165
167
  ### Session Report
@@ -170,53 +172,20 @@ All commands support the following options:
170
172
  │ │
171
173
  ╰───────────────────────────────────────────────╯
172
174
 
173
- ┌──────────────────────────────┬──────────────┬───────────────┬──────────────┬────────────┬───────────────┐
174
- │ Project / Session │ Input TokensOutput Tokens │ Total Tokens │ Cost (USD) │ Last Activity │
175
- ├──────────────────────────────┼──────────────┼───────────────┼──────────────┼────────────┼───────────────┤
176
- my-project 2,775 186,645189,420 $98.40 │ 2025-05-26
177
- │ └─ session-abc123... │ │ │ │ │ │
178
- another-project 1,063 41,421 42,484 │ $20.08 │ 2025-05-29
179
- │ └─ session-def456... │ │ │ │ │ │
180
- ├──────────────────────────────┼──────────────┼───────────────┼──────────────┼────────────┼───────────────┤
181
- │ Total │ 11,174 │ 720,445 │ 731,619 │ $336.38 │ │
182
- └──────────────────────────────┴──────────────┴───────────────┴──────────────┴────────────┴───────────────┘
175
+ ┌─────────────┬────────────┬────────┬─────────┬──────────────┬────────────┬──────────────┬────────────┬───────────────┐
176
+ │ Project Session │ Input Output │ Cache Create Cache Read │ Total Tokens │ Cost (USD) │ Last Activity │
177
+ ├─────────────┼────────────┼────────┼─────────┼──────────────┼────────────┼──────────────┼────────────┼───────────────┤
178
+ myproject │ session-1 4,512 350,846 512 │ 1,024 356,894 │ $156.40 │ 2025-05-24
179
+ ├─────────────┼────────────┼────────┼─────────┼──────────────┼────────────┼──────────────┼────────────┼───────────────┤
180
+ myproject │ session-2 2,775 186,645 256 │ 768 │ 190,444 │ $98.45 │ 2025-05-25
181
+ ├─────────────┼────────────┼────────┼─────────┼──────────────┼────────────┼──────────────┼────────────┼───────────────┤
182
+ │ Total │ │ 11,174 │ 720,445 │ 768 │ 1,792 │ 734,179 │ $336.68 │ │
183
+ └─────────────┴────────────┴────────┴─────────┴──────────────┴────────────┴──────────────┴────────────┴───────────────┘
183
184
  ```
184
185
 
185
186
  ## Requirements
186
-
187
- - [Bun](https://bun.sh) runtime
188
187
  - Claude Code usage history files (`~/.claude/projects/**/*.jsonl`)
189
188
 
190
- ## Development
191
-
192
- ```bash
193
- # Run tests
194
- bun test
195
-
196
- # Type check
197
- bun run typecheck
198
-
199
- # Lint
200
- bun run lint
201
-
202
- # Format code
203
- bun run format
204
- ```
205
-
206
- ## Project Structure
207
-
208
- ```
209
- ccusage/
210
- ├── commands/
211
- │ ├── daily.ts # Daily report command
212
- │ └── session.ts # Session report command
213
- ├── data-loader.ts # JSONL data loading logic
214
- ├── index.ts # CLI entry point
215
- ├── logger.ts # Logger configuration
216
- ├── utils.ts # Shared utilities
217
- └── package.json
218
- ```
219
-
220
189
  ## License
221
190
 
222
191
  MIT
package/dist/index.js CHANGED
@@ -2901,6 +2901,37 @@ var require_picocolors = __commonJS({ "node_modules/picocolors/picocolors.js"(ex
2901
2901
  module.exports.createColors = createColors$1;
2902
2902
  } });
2903
2903
 
2904
+ //#endregion
2905
+ //#region calculate-cost.ts
2906
+ function calculateTotals(data) {
2907
+ return data.reduce((acc, item) => ({
2908
+ inputTokens: acc.inputTokens + item.inputTokens,
2909
+ outputTokens: acc.outputTokens + item.outputTokens,
2910
+ cacheCreationTokens: acc.cacheCreationTokens + item.cacheCreationTokens,
2911
+ cacheReadTokens: acc.cacheReadTokens + item.cacheReadTokens,
2912
+ totalCost: acc.totalCost + item.totalCost
2913
+ }), {
2914
+ inputTokens: 0,
2915
+ outputTokens: 0,
2916
+ cacheCreationTokens: 0,
2917
+ cacheReadTokens: 0,
2918
+ totalCost: 0
2919
+ });
2920
+ }
2921
+ function getTotalTokens(tokens) {
2922
+ return tokens.inputTokens + tokens.outputTokens + tokens.cacheCreationTokens + tokens.cacheReadTokens;
2923
+ }
2924
+ function createTotalsObject(totals) {
2925
+ return {
2926
+ inputTokens: totals.inputTokens,
2927
+ outputTokens: totals.outputTokens,
2928
+ cacheCreationTokens: totals.cacheCreationTokens,
2929
+ cacheReadTokens: totals.cacheReadTokens,
2930
+ totalTokens: getTotalTokens(totals),
2931
+ totalCost: totals.totalCost
2932
+ };
2933
+ }
2934
+
2904
2935
  //#endregion
2905
2936
  //#region node_modules/fdir/dist/utils.js
2906
2937
  var require_utils$1 = __commonJS({ "node_modules/fdir/dist/utils.js"(exports) {
@@ -5939,7 +5970,9 @@ const UsageDataSchema = object({
5939
5970
  timestamp: string(),
5940
5971
  message: object({ usage: object({
5941
5972
  input_tokens: number(),
5942
- output_tokens: number()
5973
+ output_tokens: number(),
5974
+ cache_creation_input_tokens: optional(number()),
5975
+ cache_read_input_tokens: optional(number())
5943
5976
  }) }),
5944
5977
  costUSD: number()
5945
5978
  });
@@ -5947,6 +5980,8 @@ const DailyUsageSchema = object({
5947
5980
  date: string(),
5948
5981
  inputTokens: number(),
5949
5982
  outputTokens: number(),
5983
+ cacheCreationTokens: number(),
5984
+ cacheReadTokens: number(),
5950
5985
  totalCost: number()
5951
5986
  });
5952
5987
  const SessionUsageSchema = object({
@@ -5954,6 +5989,8 @@ const SessionUsageSchema = object({
5954
5989
  projectPath: string(),
5955
5990
  inputTokens: number(),
5956
5991
  outputTokens: number(),
5992
+ cacheCreationTokens: number(),
5993
+ cacheReadTokens: number(),
5957
5994
  totalCost: number(),
5958
5995
  lastActivity: string()
5959
5996
  });
@@ -5986,10 +6023,14 @@ async function loadUsageData(options) {
5986
6023
  date,
5987
6024
  inputTokens: 0,
5988
6025
  outputTokens: 0,
6026
+ cacheCreationTokens: 0,
6027
+ cacheReadTokens: 0,
5989
6028
  totalCost: 0
5990
6029
  };
5991
6030
  existing.inputTokens += data.message.usage.input_tokens || 0;
5992
6031
  existing.outputTokens += data.message.usage.output_tokens || 0;
6032
+ existing.cacheCreationTokens += data.message.usage.cache_creation_input_tokens || 0;
6033
+ existing.cacheReadTokens += data.message.usage.cache_read_input_tokens || 0;
5993
6034
  existing.totalCost += data.costUSD || 0;
5994
6035
  dailyMap.set(date, existing);
5995
6036
  } catch (e) {}
@@ -6035,11 +6076,15 @@ async function loadSessionData(options) {
6035
6076
  projectPath: projectPath || "Unknown Project",
6036
6077
  inputTokens: 0,
6037
6078
  outputTokens: 0,
6079
+ cacheCreationTokens: 0,
6080
+ cacheReadTokens: 0,
6038
6081
  totalCost: 0,
6039
6082
  lastActivity: ""
6040
6083
  };
6041
6084
  existing.inputTokens += data.message.usage.input_tokens || 0;
6042
6085
  existing.outputTokens += data.message.usage.output_tokens || 0;
6086
+ existing.cacheCreationTokens += data.message.usage.cache_creation_input_tokens || 0;
6087
+ existing.cacheReadTokens += data.message.usage.cache_read_input_tokens || 0;
6043
6088
  existing.totalCost += data.costUSD || 0;
6044
6089
  if (data.timestamp > lastTimestamp) {
6045
6090
  lastTimestamp = data.timestamp;
@@ -7023,7 +7068,7 @@ const consola = createConsola();
7023
7068
  //#endregion
7024
7069
  //#region package.json
7025
7070
  var name = "ccusage";
7026
- var version = "0.1.12";
7071
+ var version = "0.2.1";
7027
7072
  var description = "Usage analysis tool for Claude Code";
7028
7073
 
7029
7074
  //#endregion
@@ -7040,6 +7085,8 @@ const ModelSpecSchema = object({
7040
7085
  input_cost_per_token: optional(number()),
7041
7086
  output_cost_per_token: optional(number()),
7042
7087
  output_cost_per_reasoning_token: optional(number()),
7088
+ cache_creation_input_token_cost: optional(number()),
7089
+ cache_read_input_token_cost: optional(number()),
7043
7090
  litellm_provider: optional(string()),
7044
7091
  mode: optional(string()),
7045
7092
  supports_function_calling: optional(boolean()),
@@ -7125,30 +7172,19 @@ const dailyCommand = define({
7125
7172
  else logger.warn("No Claude usage data found.");
7126
7173
  process$1.exit(0);
7127
7174
  }
7128
- const totals = dailyData.reduce((acc, data) => ({
7129
- inputTokens: acc.inputTokens + data.inputTokens,
7130
- outputTokens: acc.outputTokens + data.outputTokens,
7131
- totalCost: acc.totalCost + data.totalCost
7132
- }), {
7133
- inputTokens: 0,
7134
- outputTokens: 0,
7135
- totalCost: 0
7136
- });
7175
+ const totals = calculateTotals(dailyData);
7137
7176
  if (ctx.values.json) {
7138
7177
  const jsonOutput = {
7139
7178
  daily: dailyData.map((data) => ({
7140
7179
  date: data.date,
7141
7180
  inputTokens: data.inputTokens,
7142
7181
  outputTokens: data.outputTokens,
7143
- totalTokens: data.inputTokens + data.outputTokens,
7182
+ cacheCreationTokens: data.cacheCreationTokens,
7183
+ cacheReadTokens: data.cacheReadTokens,
7184
+ totalTokens: getTotalTokens(data),
7144
7185
  totalCost: data.totalCost
7145
7186
  })),
7146
- totals: {
7147
- inputTokens: totals.inputTokens,
7148
- outputTokens: totals.outputTokens,
7149
- totalTokens: totals.inputTokens + totals.outputTokens,
7150
- totalCost: totals.totalCost
7151
- }
7187
+ totals: createTotalsObject(totals)
7152
7188
  };
7153
7189
  log(JSON.stringify(jsonOutput, null, 2));
7154
7190
  } else {
@@ -7156,8 +7192,10 @@ const dailyCommand = define({
7156
7192
  const table = new import_cli_table3$1.default({
7157
7193
  head: [
7158
7194
  "Date",
7159
- "Input Tokens",
7160
- "Output Tokens",
7195
+ "Input",
7196
+ "Output",
7197
+ "Cache Create",
7198
+ "Cache Read",
7161
7199
  "Total Tokens",
7162
7200
  "Cost (USD)"
7163
7201
  ],
@@ -7167,6 +7205,8 @@ const dailyCommand = define({
7167
7205
  "right",
7168
7206
  "right",
7169
7207
  "right",
7208
+ "right",
7209
+ "right",
7170
7210
  "right"
7171
7211
  ]
7172
7212
  });
@@ -7174,7 +7214,9 @@ const dailyCommand = define({
7174
7214
  data.date,
7175
7215
  formatNumber(data.inputTokens),
7176
7216
  formatNumber(data.outputTokens),
7177
- formatNumber(data.inputTokens + data.outputTokens),
7217
+ formatNumber(data.cacheCreationTokens),
7218
+ formatNumber(data.cacheReadTokens),
7219
+ formatNumber(getTotalTokens(data)),
7178
7220
  formatCurrency(data.totalCost)
7179
7221
  ]);
7180
7222
  table.push([
@@ -7182,13 +7224,17 @@ const dailyCommand = define({
7182
7224
  "─".repeat(12),
7183
7225
  "─".repeat(12),
7184
7226
  "─".repeat(12),
7227
+ "─".repeat(12),
7228
+ "─".repeat(12),
7185
7229
  "─".repeat(10)
7186
7230
  ]);
7187
7231
  table.push([
7188
7232
  import_picocolors$1.default.yellow("Total"),
7189
7233
  import_picocolors$1.default.yellow(formatNumber(totals.inputTokens)),
7190
7234
  import_picocolors$1.default.yellow(formatNumber(totals.outputTokens)),
7191
- import_picocolors$1.default.yellow(formatNumber(totals.inputTokens + totals.outputTokens)),
7235
+ import_picocolors$1.default.yellow(formatNumber(totals.cacheCreationTokens)),
7236
+ import_picocolors$1.default.yellow(formatNumber(totals.cacheReadTokens)),
7237
+ import_picocolors$1.default.yellow(formatNumber(getTotalTokens(totals))),
7192
7238
  import_picocolors$1.default.yellow(formatCurrency(totals.totalCost))
7193
7239
  ]);
7194
7240
  console.log(table.toString());
@@ -7216,15 +7262,7 @@ const sessionCommand = define({
7216
7262
  else logger.warn("No Claude usage data found.");
7217
7263
  process$1.exit(0);
7218
7264
  }
7219
- const totals = sessionData.reduce((acc, data) => ({
7220
- inputTokens: acc.inputTokens + data.inputTokens,
7221
- outputTokens: acc.outputTokens + data.outputTokens,
7222
- totalCost: acc.totalCost + data.totalCost
7223
- }), {
7224
- inputTokens: 0,
7225
- outputTokens: 0,
7226
- totalCost: 0
7227
- });
7265
+ const totals = calculateTotals(sessionData);
7228
7266
  if (ctx.values.json) {
7229
7267
  const jsonOutput = {
7230
7268
  sessions: sessionData.map((data) => ({
@@ -7232,16 +7270,13 @@ const sessionCommand = define({
7232
7270
  sessionId: data.sessionId,
7233
7271
  inputTokens: data.inputTokens,
7234
7272
  outputTokens: data.outputTokens,
7235
- totalTokens: data.inputTokens + data.outputTokens,
7273
+ cacheCreationTokens: data.cacheCreationTokens,
7274
+ cacheReadTokens: data.cacheReadTokens,
7275
+ totalTokens: getTotalTokens(data),
7236
7276
  totalCost: data.totalCost,
7237
7277
  lastActivity: data.lastActivity
7238
7278
  })),
7239
- totals: {
7240
- inputTokens: totals.inputTokens,
7241
- outputTokens: totals.outputTokens,
7242
- totalTokens: totals.inputTokens + totals.outputTokens,
7243
- totalCost: totals.totalCost
7244
- }
7279
+ totals: createTotalsObject(totals)
7245
7280
  };
7246
7281
  log(JSON.stringify(jsonOutput, null, 2));
7247
7282
  } else {
@@ -7250,8 +7285,10 @@ const sessionCommand = define({
7250
7285
  head: [
7251
7286
  "Project",
7252
7287
  "Session",
7253
- "Input Tokens",
7254
- "Output Tokens",
7288
+ "Input",
7289
+ "Output",
7290
+ "Cache Create",
7291
+ "Cache Read",
7255
7292
  "Total Tokens",
7256
7293
  "Cost (USD)",
7257
7294
  "Last Activity"
@@ -7264,6 +7301,8 @@ const sessionCommand = define({
7264
7301
  "right",
7265
7302
  "right",
7266
7303
  "right",
7304
+ "right",
7305
+ "right",
7267
7306
  "left"
7268
7307
  ]
7269
7308
  });
@@ -7279,7 +7318,9 @@ const sessionCommand = define({
7279
7318
  sessionDisplay,
7280
7319
  formatNumber(data.inputTokens),
7281
7320
  formatNumber(data.outputTokens),
7282
- formatNumber(data.inputTokens + data.outputTokens),
7321
+ formatNumber(data.cacheCreationTokens),
7322
+ formatNumber(data.cacheReadTokens),
7323
+ formatNumber(getTotalTokens(data)),
7283
7324
  formatCurrency(data.totalCost),
7284
7325
  data.lastActivity
7285
7326
  ]);
@@ -7290,6 +7331,8 @@ const sessionCommand = define({
7290
7331
  "─".repeat(12),
7291
7332
  "─".repeat(12),
7292
7333
  "─".repeat(12),
7334
+ "─".repeat(12),
7335
+ "─".repeat(12),
7293
7336
  "─".repeat(10),
7294
7337
  "─".repeat(12)
7295
7338
  ]);
@@ -7298,7 +7341,9 @@ const sessionCommand = define({
7298
7341
  "",
7299
7342
  import_picocolors.default.yellow(formatNumber(totals.inputTokens)),
7300
7343
  import_picocolors.default.yellow(formatNumber(totals.outputTokens)),
7301
- import_picocolors.default.yellow(formatNumber(totals.inputTokens + totals.outputTokens)),
7344
+ import_picocolors.default.yellow(formatNumber(totals.cacheCreationTokens)),
7345
+ import_picocolors.default.yellow(formatNumber(totals.cacheReadTokens)),
7346
+ import_picocolors.default.yellow(formatNumber(getTotalTokens(totals))),
7302
7347
  import_picocolors.default.yellow(formatCurrency(totals.totalCost)),
7303
7348
  ""
7304
7349
  ]);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ccusage",
3
- "version": "0.1.12",
3
+ "version": "0.2.1",
4
4
  "description": "Usage analysis tool for Claude Code",
5
5
  "homepage": "https://github.com/ryoppippi/ccusage#readme",
6
6
  "bugs": {