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.
- package/README.md +20 -51
- package/dist/index.js +87 -42
- 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
|
|
156
|
-
|
|
157
|
-
│ 2025-05-30
|
|
158
|
-
│ 2025-05-29
|
|
159
|
-
│ 2025-05-28
|
|
160
|
-
|
|
161
|
-
│ Total
|
|
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
|
|
175
|
-
|
|
176
|
-
│
|
|
177
|
-
|
|
178
|
-
│
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
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
|
|
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
|
|
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
|
-
|
|
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
|
|
7160
|
-
"Output
|
|
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.
|
|
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.
|
|
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
|
|
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
|
-
|
|
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
|
|
7254
|
-
"Output
|
|
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.
|
|
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.
|
|
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
|
]);
|