cursor-usage 0.1.2 → 0.1.3
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 +127 -37
- package/dist/commands.js +131 -119
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -4,12 +4,12 @@ A CLI tool for analyzing Cursor API usage and membership information, inspired b
|
|
|
4
4
|
|
|
5
5
|
## Features
|
|
6
6
|
|
|
7
|
-
-
|
|
8
|
-
-
|
|
9
|
-
-
|
|
10
|
-
-
|
|
11
|
-
-
|
|
12
|
-
-
|
|
7
|
+
- Extract Cursor credentials from local database
|
|
8
|
+
- Fetch usage data from Cursor API
|
|
9
|
+
- Display membership and plan usage information
|
|
10
|
+
- Show usage breakdown (included vs bonus)
|
|
11
|
+
- Track percentage of included usage consumed
|
|
12
|
+
- Colorful terminal output
|
|
13
13
|
|
|
14
14
|
## Installation
|
|
15
15
|
|
|
@@ -17,6 +17,26 @@ A CLI tool for analyzing Cursor API usage and membership information, inspired b
|
|
|
17
17
|
npm install
|
|
18
18
|
```
|
|
19
19
|
|
|
20
|
+
## Quick Test
|
|
21
|
+
|
|
22
|
+
You can test the package without installing it locally using npx or bunx:
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
# Test with npx (Node.js)
|
|
26
|
+
npx cursor-usage@latest
|
|
27
|
+
|
|
28
|
+
# Test with bunx (Bun runtime)
|
|
29
|
+
bunx cursor-usage@latest
|
|
30
|
+
|
|
31
|
+
# Test specific commands
|
|
32
|
+
npx cursor-usage@latest daily
|
|
33
|
+
npx cursor-usage@latest monthly
|
|
34
|
+
|
|
35
|
+
# Test with flags
|
|
36
|
+
npx cursor-usage@latest daily --breakdown
|
|
37
|
+
npx cursor-usage@latest weekly --json
|
|
38
|
+
```
|
|
39
|
+
|
|
20
40
|
## Usage
|
|
21
41
|
|
|
22
42
|
### Commands
|
|
@@ -44,8 +64,28 @@ npm run dev -- today
|
|
|
44
64
|
|
|
45
65
|
# Show help
|
|
46
66
|
npm run dev -- help
|
|
67
|
+
|
|
68
|
+
# Show usage with date range
|
|
69
|
+
npm run dev -- daily --since 2026-01-01 --until 2026-01-15
|
|
70
|
+
|
|
71
|
+
# Show usage with model breakdown
|
|
72
|
+
npm run dev -- daily --breakdown
|
|
73
|
+
|
|
74
|
+
# Show compact table format
|
|
75
|
+
npm run dev -- monthly --compact
|
|
76
|
+
|
|
77
|
+
# Output as JSON (detailed reports only)
|
|
78
|
+
npm run dev -- daily --json
|
|
47
79
|
```
|
|
48
80
|
|
|
81
|
+
### Flags
|
|
82
|
+
|
|
83
|
+
- `--since DATE` - Start date (YYYY-MM-DD)
|
|
84
|
+
- `--until DATE` - End date (YYYY-MM-DD)
|
|
85
|
+
- `--breakdown` - Show per-model breakdown
|
|
86
|
+
- `--json` - Output as JSON (machine-readable format)
|
|
87
|
+
- `--compact` - Compact table format
|
|
88
|
+
|
|
49
89
|
### Development
|
|
50
90
|
|
|
51
91
|
```bash
|
|
@@ -59,11 +99,11 @@ npm run build # Compile TypeScript
|
|
|
59
99
|
### Summary View
|
|
60
100
|
|
|
61
101
|
```
|
|
62
|
-
|
|
102
|
+
ACCOUNT INFORMATION:
|
|
63
103
|
Membership: pro
|
|
64
104
|
Billing Cycle: <your-billing-cycle>
|
|
65
105
|
|
|
66
|
-
|
|
106
|
+
PLAN USAGE:
|
|
67
107
|
Used: 150 / 2000 (7.50%)
|
|
68
108
|
Remaining: 1850
|
|
69
109
|
```
|
|
@@ -136,21 +176,91 @@ USAGE EVENTS FOR Today
|
|
|
136
176
|
Total Events: 3
|
|
137
177
|
Total Tokens: 3,150
|
|
138
178
|
Total Cost: $0.14
|
|
139
|
-
|
|
179
|
+
==================================================================================================================
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
### Model Breakdown View (`--breakdown`)
|
|
183
|
+
|
|
184
|
+
When using `--breakdown`, reports include a detailed per-model breakdown:
|
|
185
|
+
|
|
186
|
+
```
|
|
187
|
+
==================================================================================================================
|
|
188
|
+
PER-MODEL BREAKDOWN
|
|
189
|
+
==================================================================================================================
|
|
190
|
+
|
|
191
|
+
+---------------+--------+--------------+-------+-------+-------+---------+------------+------------+
|
|
192
|
+
| Model | Events | Total Tokens | Input | Output| Cost | Token % | Cost % |
|
|
193
|
+
+---------------+--------+--------------+-------+-------+-------+---------+------------+
|
|
194
|
+
| claude-opus | 15 | 2,500,000 | 20000 | 15000 | $2.00 | 50.00% | 40.00% |
|
|
195
|
+
| claude-sonnet | 10 | 2,000,000 | 15000 | 12000 | $1.60 | 40.00% | 32.00% |
|
|
196
|
+
| claude-haiku | 5 | 500,000 | 5000 | 3000 | $0.40 | 10.00% | 8.00% |
|
|
197
|
+
+---------------+--------+--------------+-------+-------+-------+---------+------------+
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
### JSON Output (`--json`)
|
|
201
|
+
|
|
202
|
+
JSON output provides clean, structured data for programmatic use (no table formatting):
|
|
203
|
+
|
|
204
|
+
```json
|
|
205
|
+
{
|
|
206
|
+
"command": "daily",
|
|
207
|
+
"generatedAt": "2026-01-11T10:30:00.000Z",
|
|
208
|
+
"period": "last 7 days",
|
|
209
|
+
"summary": {
|
|
210
|
+
"totalEvents": 45,
|
|
211
|
+
"totalTokens": 539301,
|
|
212
|
+
"totalCost": 0.82
|
|
213
|
+
},
|
|
214
|
+
"data": [
|
|
215
|
+
{
|
|
216
|
+
"date": "2026-01-11",
|
|
217
|
+
"eventCount": 3,
|
|
218
|
+
"totalTokens": 539301,
|
|
219
|
+
"inputTokens": 381,
|
|
220
|
+
"outputTokens": 7081,
|
|
221
|
+
"totalCost": 0.82,
|
|
222
|
+
"models": {
|
|
223
|
+
"claude-4.5-opus-high-thinking": 3
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
],
|
|
227
|
+
"breakdown": [
|
|
228
|
+
{
|
|
229
|
+
"model": "claude-opus",
|
|
230
|
+
"count": 15,
|
|
231
|
+
"totalTokens": 250000,
|
|
232
|
+
"inputTokens": 20000,
|
|
233
|
+
"outputTokens": 15000,
|
|
234
|
+
"totalCost": 2.0,
|
|
235
|
+
"tokenPercent": 50.0,
|
|
236
|
+
"costPercent": 40.0
|
|
237
|
+
}
|
|
238
|
+
]
|
|
239
|
+
}
|
|
140
240
|
```
|
|
141
241
|
|
|
142
|
-
|
|
242
|
+
### Compact Table Format (`--compact`)
|
|
143
243
|
|
|
144
|
-
|
|
145
|
-
- User ID from `workbench.experiments.statsigBootstrap`
|
|
146
|
-
- Access Token from `cursorAuth/accessToken`
|
|
147
|
-
- Email and membership (optional)
|
|
244
|
+
The `--compact` flag provides a more condensed table layout:
|
|
148
245
|
|
|
149
|
-
|
|
246
|
+
```
|
|
247
|
+
==================================================================================================================
|
|
248
|
+
DAILY USAGE REPORT (Last 7 days)
|
|
249
|
+
==================================================================================================================
|
|
150
250
|
|
|
151
|
-
|
|
251
|
+
Date Events Tokens Cost Models
|
|
252
|
+
2026-01-11 3 539,301 $0.82 claude-4.5-opus-high-thinking(3)
|
|
253
|
+
2026-01-10 5 1,200,450 $1.45 claude-sonnet(4), claude-opus(1)
|
|
254
|
+
2026-01-09 2 89,320 $0.12 claude-haiku(2)
|
|
152
255
|
|
|
153
|
-
|
|
256
|
+
==================================================================================================================
|
|
257
|
+
SUMMARY
|
|
258
|
+
==================================================================================================================
|
|
259
|
+
Total Events: 10
|
|
260
|
+
Total Tokens: 1,829,071
|
|
261
|
+
Total Cost: $2.39
|
|
262
|
+
==================================================================================================================
|
|
263
|
+
```
|
|
154
264
|
|
|
155
265
|
## Environment Variables
|
|
156
266
|
|
|
@@ -168,15 +278,6 @@ src/
|
|
|
168
278
|
└── _consts.ts # Constants & configuration
|
|
169
279
|
```
|
|
170
280
|
|
|
171
|
-
## API Response Structure
|
|
172
|
-
|
|
173
|
-
The tool fetches data from Cursor's `/api/usage-summary` endpoint which returns:
|
|
174
|
-
- Billing cycle information
|
|
175
|
-
- Membership type (pro, hobby, etc.)
|
|
176
|
-
- Plan usage (used/limit/remaining)
|
|
177
|
-
- On-demand usage status
|
|
178
|
-
- Display messages about usage percentage
|
|
179
|
-
|
|
180
281
|
## Features Implemented
|
|
181
282
|
|
|
182
283
|
- ✅ Daily usage reports with table formatting
|
|
@@ -187,17 +288,6 @@ The tool fetches data from Cursor's `/api/usage-summary` endpoint which returns:
|
|
|
187
288
|
- ✅ Flexible date range querying
|
|
188
289
|
- ✅ Colorized CLI output
|
|
189
290
|
|
|
190
|
-
## Future Enhancements
|
|
191
|
-
|
|
192
|
-
- [ ] JSON output format (`--json`)
|
|
193
|
-
- [ ] Date range queries (`--from 2026-01-01 --to 2026-01-31`)
|
|
194
|
-
- [ ] Weekly/monthly aggregations
|
|
195
|
-
- [ ] Historical data caching
|
|
196
|
-
- [ ] Cost projections
|
|
197
|
-
- [ ] Team usage analysis
|
|
198
|
-
- [ ] Export to CSV/JSON
|
|
199
|
-
- [ ] Web dashboard
|
|
200
|
-
- [ ] Webhook notifications
|
|
201
291
|
|
|
202
292
|
## License
|
|
203
293
|
|
package/dist/commands.js
CHANGED
|
@@ -71,50 +71,53 @@ export async function showDailyReport(credentials, days = 7, options = {}, outpu
|
|
|
71
71
|
logger.warn('No usage events found for this period');
|
|
72
72
|
return;
|
|
73
73
|
}
|
|
74
|
-
logger.log('');
|
|
75
74
|
// Group and calculate stats
|
|
76
75
|
const grouped = groupByDay(events);
|
|
77
76
|
const stats = calculateDailyStats(grouped);
|
|
78
|
-
// Display table
|
|
79
|
-
logger.log('\n' + '='.repeat(100));
|
|
80
|
-
logger.log(`DAILY USAGE REPORT (Last ${days} days)`);
|
|
81
|
-
logger.log('='.repeat(100) + '\n');
|
|
82
|
-
const tableData = stats.map((day) => {
|
|
83
|
-
const modelList = Array.from(day.models.entries())
|
|
84
|
-
.map(([model, count]) => `${model}(${count})`)
|
|
85
|
-
.join(', ');
|
|
86
|
-
return [
|
|
87
|
-
day.date,
|
|
88
|
-
day.eventCount.toString(),
|
|
89
|
-
day.totalTokens.toLocaleString(),
|
|
90
|
-
day.inputTokens.toLocaleString(),
|
|
91
|
-
day.outputTokens.toLocaleString(),
|
|
92
|
-
`$${day.totalCost.toFixed(2)}`,
|
|
93
|
-
modelList || 'N/A',
|
|
94
|
-
];
|
|
95
|
-
});
|
|
96
|
-
const table = createTable(['Date', 'Events', 'Total Tokens', 'Input', 'Output', 'Cost', 'Models'], tableData);
|
|
97
|
-
logger.log(table);
|
|
98
|
-
// Summary
|
|
99
|
-
const totalEvents = stats.reduce((sum, day) => sum + day.eventCount, 0);
|
|
100
|
-
const totalTokens = stats.reduce((sum, day) => sum + day.totalTokens, 0);
|
|
101
|
-
const totalCost = stats.reduce((sum, day) => sum + day.totalCost, 0);
|
|
102
|
-
logger.log('\n' + '='.repeat(100));
|
|
103
|
-
logger.log('SUMMARY');
|
|
104
|
-
logger.log('='.repeat(100));
|
|
105
|
-
logger.log(`Total Events: ${totalEvents}`);
|
|
106
|
-
logger.log(`Total Tokens: ${totalTokens.toLocaleString()}`);
|
|
107
|
-
logger.log(`Total Cost: $${totalCost.toFixed(2)}`);
|
|
108
|
-
logger.log('='.repeat(100) + '\n');
|
|
109
|
-
// Show breakdown if requested
|
|
110
|
-
if (options.breakdown) {
|
|
111
|
-
displayBreakdown(events, 'PER-MODEL BREAKDOWN');
|
|
112
|
-
}
|
|
113
|
-
// Output JSON if requested
|
|
114
77
|
if (outputJson) {
|
|
78
|
+
// Output JSON only - no table display
|
|
115
79
|
const jsonOutput = statsToJSON('daily', stats, events, { breakdown: options.breakdown, period: `last ${days} days` });
|
|
116
80
|
console.log(jsonOutput);
|
|
117
81
|
}
|
|
82
|
+
else {
|
|
83
|
+
// Display table and summary
|
|
84
|
+
logger.log('');
|
|
85
|
+
// Display table
|
|
86
|
+
logger.log('\n' + '='.repeat(100));
|
|
87
|
+
logger.log(`DAILY USAGE REPORT (Last ${days} days)`);
|
|
88
|
+
logger.log('='.repeat(100) + '\n');
|
|
89
|
+
const tableData = stats.map((day) => {
|
|
90
|
+
const modelList = Array.from(day.models.entries())
|
|
91
|
+
.map(([model, count]) => `${model}(${count})`)
|
|
92
|
+
.join(', ');
|
|
93
|
+
return [
|
|
94
|
+
day.date,
|
|
95
|
+
day.eventCount.toString(),
|
|
96
|
+
day.totalTokens.toLocaleString(),
|
|
97
|
+
day.inputTokens.toLocaleString(),
|
|
98
|
+
day.outputTokens.toLocaleString(),
|
|
99
|
+
`$${day.totalCost.toFixed(2)}`,
|
|
100
|
+
modelList || 'N/A',
|
|
101
|
+
];
|
|
102
|
+
});
|
|
103
|
+
const table = createTable(['Date', 'Events', 'Total Tokens', 'Input', 'Output', 'Cost', 'Models'], tableData);
|
|
104
|
+
logger.log(table);
|
|
105
|
+
// Summary
|
|
106
|
+
const totalEvents = stats.reduce((sum, day) => sum + day.eventCount, 0);
|
|
107
|
+
const totalTokens = stats.reduce((sum, day) => sum + day.totalTokens, 0);
|
|
108
|
+
const totalCost = stats.reduce((sum, day) => sum + day.totalCost, 0);
|
|
109
|
+
logger.log('\n' + '='.repeat(100));
|
|
110
|
+
logger.log('SUMMARY');
|
|
111
|
+
logger.log('='.repeat(100));
|
|
112
|
+
logger.log(`Total Events: ${totalEvents}`);
|
|
113
|
+
logger.log(`Total Tokens: ${totalTokens.toLocaleString()}`);
|
|
114
|
+
logger.log(`Total Cost: $${totalCost.toFixed(2)}`);
|
|
115
|
+
logger.log('='.repeat(100) + '\n');
|
|
116
|
+
// Show breakdown if requested
|
|
117
|
+
if (options.breakdown) {
|
|
118
|
+
displayBreakdown(events, 'PER-MODEL BREAKDOWN');
|
|
119
|
+
}
|
|
120
|
+
}
|
|
118
121
|
}
|
|
119
122
|
/**
|
|
120
123
|
* Show monthly usage report
|
|
@@ -136,38 +139,41 @@ export async function showMonthlyReport(credentials, months = 3, options = {}, o
|
|
|
136
139
|
logger.warn('No usage events found for this period');
|
|
137
140
|
return;
|
|
138
141
|
}
|
|
139
|
-
logger.log('');
|
|
140
142
|
// Group and calculate stats
|
|
141
143
|
const grouped = groupByMonth(events);
|
|
142
144
|
const stats = calculateMonthlyStats(grouped);
|
|
143
|
-
// Display table
|
|
144
|
-
logger.log('\n' + '='.repeat(100));
|
|
145
|
-
logger.log(`MONTHLY USAGE REPORT (Last ${months} months)`);
|
|
146
|
-
logger.log('='.repeat(100) + '\n');
|
|
147
|
-
const tableData = formatMonthlyStatsTable(stats);
|
|
148
|
-
const table = createTable(['Month', 'Events', 'Total Tokens', 'Input', 'Output', 'Cost', 'Models'], tableData);
|
|
149
|
-
logger.log(table);
|
|
150
|
-
// Summary
|
|
151
|
-
const totalEvents = stats.reduce((sum, month) => sum + month.eventCount, 0);
|
|
152
|
-
const totalTokens = stats.reduce((sum, month) => sum + month.totalTokens, 0);
|
|
153
|
-
const totalCost = stats.reduce((sum, month) => sum + month.totalCost, 0);
|
|
154
|
-
logger.log('\n' + '='.repeat(100));
|
|
155
|
-
logger.log('SUMMARY');
|
|
156
|
-
logger.log('='.repeat(100));
|
|
157
|
-
logger.log(`Total Events: ${totalEvents}`);
|
|
158
|
-
logger.log(`Total Tokens: ${totalTokens.toLocaleString()}`);
|
|
159
|
-
logger.log(`Total Cost: $${totalCost.toFixed(2)}`);
|
|
160
|
-
logger.log(`Average per month: ${(totalTokens / Math.max(1, stats.length)).toLocaleString()} tokens, $${(totalCost / Math.max(1, stats.length)).toFixed(2)}`);
|
|
161
|
-
logger.log('='.repeat(100) + '\n');
|
|
162
|
-
// Show breakdown if requested
|
|
163
|
-
if (options.breakdown) {
|
|
164
|
-
displayBreakdown(events, 'PER-MODEL BREAKDOWN');
|
|
165
|
-
}
|
|
166
|
-
// Output JSON if requested
|
|
167
145
|
if (outputJson) {
|
|
146
|
+
// Output JSON only - no table display
|
|
168
147
|
const jsonOutput = statsToJSON('monthly', stats, events, { breakdown: options.breakdown, period: `last ${months} months` });
|
|
169
148
|
console.log(jsonOutput);
|
|
170
149
|
}
|
|
150
|
+
else {
|
|
151
|
+
// Display table and summary
|
|
152
|
+
logger.log('');
|
|
153
|
+
// Display table
|
|
154
|
+
logger.log('\n' + '='.repeat(100));
|
|
155
|
+
logger.log(`MONTHLY USAGE REPORT (Last ${months} months)`);
|
|
156
|
+
logger.log('='.repeat(100) + '\n');
|
|
157
|
+
const tableData = formatMonthlyStatsTable(stats);
|
|
158
|
+
const table = createTable(['Month', 'Events', 'Total Tokens', 'Input', 'Output', 'Cost', 'Models'], tableData);
|
|
159
|
+
logger.log(table);
|
|
160
|
+
// Summary
|
|
161
|
+
const totalEvents = stats.reduce((sum, month) => sum + month.eventCount, 0);
|
|
162
|
+
const totalTokens = stats.reduce((sum, month) => sum + month.totalTokens, 0);
|
|
163
|
+
const totalCost = stats.reduce((sum, month) => sum + month.totalCost, 0);
|
|
164
|
+
logger.log('\n' + '='.repeat(100));
|
|
165
|
+
logger.log('SUMMARY');
|
|
166
|
+
logger.log('='.repeat(100));
|
|
167
|
+
logger.log(`Total Events: ${totalEvents}`);
|
|
168
|
+
logger.log(`Total Tokens: ${totalTokens.toLocaleString()}`);
|
|
169
|
+
logger.log(`Total Cost: $${totalCost.toFixed(2)}`);
|
|
170
|
+
logger.log(`Average per month: ${(totalTokens / Math.max(1, stats.length)).toLocaleString()} tokens, $${(totalCost / Math.max(1, stats.length)).toFixed(2)}`);
|
|
171
|
+
logger.log('='.repeat(100) + '\n');
|
|
172
|
+
// Show breakdown if requested
|
|
173
|
+
if (options.breakdown) {
|
|
174
|
+
displayBreakdown(events, 'PER-MODEL BREAKDOWN');
|
|
175
|
+
}
|
|
176
|
+
}
|
|
171
177
|
}
|
|
172
178
|
/**
|
|
173
179
|
* Show weekly usage report
|
|
@@ -188,38 +194,41 @@ export async function showWeeklyReport(credentials, weeks = 4, options = {}, out
|
|
|
188
194
|
logger.warn('No usage events found for this period');
|
|
189
195
|
return;
|
|
190
196
|
}
|
|
191
|
-
logger.log('');
|
|
192
197
|
// Group and calculate stats
|
|
193
198
|
const grouped = groupByWeek(events);
|
|
194
199
|
const stats = calculateWeeklyStats(grouped);
|
|
195
|
-
// Display table
|
|
196
|
-
logger.log('\n' + '='.repeat(120));
|
|
197
|
-
logger.log(`WEEKLY USAGE REPORT (Last ${weeks} weeks)`);
|
|
198
|
-
logger.log('='.repeat(120) + '\n');
|
|
199
|
-
const tableData = formatWeeklyStatsTable(stats);
|
|
200
|
-
const table = createTable(['Week', 'Events', 'Total Tokens', 'Input', 'Output', 'Cost', 'Models'], tableData);
|
|
201
|
-
logger.log(table);
|
|
202
|
-
// Summary
|
|
203
|
-
const totalEvents = stats.reduce((sum, week) => sum + week.eventCount, 0);
|
|
204
|
-
const totalTokens = stats.reduce((sum, week) => sum + week.totalTokens, 0);
|
|
205
|
-
const totalCost = stats.reduce((sum, week) => sum + week.totalCost, 0);
|
|
206
|
-
logger.log('\n' + '='.repeat(120));
|
|
207
|
-
logger.log('SUMMARY');
|
|
208
|
-
logger.log('='.repeat(120));
|
|
209
|
-
logger.log(`Total Events: ${totalEvents}`);
|
|
210
|
-
logger.log(`Total Tokens: ${totalTokens.toLocaleString()}`);
|
|
211
|
-
logger.log(`Total Cost: $${totalCost.toFixed(2)}`);
|
|
212
|
-
logger.log(`Average per week: ${(totalTokens / Math.max(1, stats.length)).toLocaleString()} tokens, $${(totalCost / Math.max(1, stats.length)).toFixed(2)}`);
|
|
213
|
-
logger.log('='.repeat(120) + '\n');
|
|
214
|
-
// Show breakdown if requested
|
|
215
|
-
if (options.breakdown) {
|
|
216
|
-
displayBreakdown(events, 'PER-MODEL BREAKDOWN');
|
|
217
|
-
}
|
|
218
|
-
// Output JSON if requested
|
|
219
200
|
if (outputJson) {
|
|
201
|
+
// Output JSON only - no table display
|
|
220
202
|
const jsonOutput = statsToJSON('weekly', stats, events, { breakdown: options.breakdown, period: `last ${weeks} weeks` });
|
|
221
203
|
console.log(jsonOutput);
|
|
222
204
|
}
|
|
205
|
+
else {
|
|
206
|
+
// Display table and summary
|
|
207
|
+
logger.log('');
|
|
208
|
+
// Display table
|
|
209
|
+
logger.log('\n' + '='.repeat(120));
|
|
210
|
+
logger.log(`WEEKLY USAGE REPORT (Last ${weeks} weeks)`);
|
|
211
|
+
logger.log('='.repeat(120) + '\n');
|
|
212
|
+
const tableData = formatWeeklyStatsTable(stats);
|
|
213
|
+
const table = createTable(['Week', 'Events', 'Total Tokens', 'Input', 'Output', 'Cost', 'Models'], tableData);
|
|
214
|
+
logger.log(table);
|
|
215
|
+
// Summary
|
|
216
|
+
const totalEvents = stats.reduce((sum, week) => sum + week.eventCount, 0);
|
|
217
|
+
const totalTokens = stats.reduce((sum, week) => sum + week.totalTokens, 0);
|
|
218
|
+
const totalCost = stats.reduce((sum, week) => sum + week.totalCost, 0);
|
|
219
|
+
logger.log('\n' + '='.repeat(120));
|
|
220
|
+
logger.log('SUMMARY');
|
|
221
|
+
logger.log('='.repeat(120));
|
|
222
|
+
logger.log(`Total Events: ${totalEvents}`);
|
|
223
|
+
logger.log(`Total Tokens: ${totalTokens.toLocaleString()}`);
|
|
224
|
+
logger.log(`Total Cost: $${totalCost.toFixed(2)}`);
|
|
225
|
+
logger.log(`Average per week: ${(totalTokens / Math.max(1, stats.length)).toLocaleString()} tokens, $${(totalCost / Math.max(1, stats.length)).toFixed(2)}`);
|
|
226
|
+
logger.log('='.repeat(120) + '\n');
|
|
227
|
+
// Show breakdown if requested
|
|
228
|
+
if (options.breakdown) {
|
|
229
|
+
displayBreakdown(events, 'PER-MODEL BREAKDOWN');
|
|
230
|
+
}
|
|
231
|
+
}
|
|
223
232
|
}
|
|
224
233
|
/**
|
|
225
234
|
* Show usage for a specific date
|
|
@@ -234,40 +243,43 @@ export async function showDateReport(credentials, date, options = {}, outputJson
|
|
|
234
243
|
logger.warn('No usage events found for this date');
|
|
235
244
|
return;
|
|
236
245
|
}
|
|
237
|
-
logger.log('');
|
|
238
|
-
// Display detailed events
|
|
239
|
-
logger.log('\n' + '='.repeat(120));
|
|
240
|
-
logger.log(`USAGE EVENTS FOR ${date.toDateString()}`);
|
|
241
|
-
logger.log('='.repeat(120) + '\n');
|
|
242
|
-
const tableData = events.map((event) => {
|
|
243
|
-
const timestamp = new Date(event.timestamp).toLocaleTimeString();
|
|
244
|
-
return [
|
|
245
|
-
timestamp,
|
|
246
|
-
event.model,
|
|
247
|
-
event.type,
|
|
248
|
-
event.inputTokens.toLocaleString(),
|
|
249
|
-
event.outputTokens.toLocaleString(),
|
|
250
|
-
event.tokens.toLocaleString(),
|
|
251
|
-
`$${event.cost?.toFixed(4) || '0.0000'}`,
|
|
252
|
-
];
|
|
253
|
-
});
|
|
254
|
-
const table = createTable(['Time', 'Model', 'Type', 'Input Tokens', 'Output Tokens', 'Total Tokens', 'Cost'], tableData);
|
|
255
|
-
logger.log(table);
|
|
256
|
-
// Summary
|
|
257
|
-
const totalTokens = events.reduce((sum, e) => sum + e.tokens, 0);
|
|
258
|
-
const totalCost = events.reduce((sum, e) => sum + (e.cost || 0), 0);
|
|
259
|
-
logger.log('\n' + '='.repeat(120));
|
|
260
|
-
logger.log(`Total Events: ${events.length}`);
|
|
261
|
-
logger.log(`Total Tokens: ${totalTokens.toLocaleString()}`);
|
|
262
|
-
logger.log(`Total Cost: $${totalCost.toFixed(2)}`);
|
|
263
|
-
logger.log('='.repeat(120) + '\n');
|
|
264
|
-
// Show breakdown if requested
|
|
265
|
-
if (options.breakdown) {
|
|
266
|
-
displayBreakdown(events, 'PER-MODEL BREAKDOWN');
|
|
267
|
-
}
|
|
268
|
-
// Output JSON if requested
|
|
269
246
|
if (outputJson) {
|
|
247
|
+
// Output JSON only - no table display
|
|
270
248
|
const jsonOutput = statsToJSON('today', events.map((e, i) => ({ ...e, eventIndex: i })), events, { breakdown: options.breakdown, period: 'today' });
|
|
271
249
|
console.log(jsonOutput);
|
|
272
250
|
}
|
|
251
|
+
else {
|
|
252
|
+
// Display table and summary
|
|
253
|
+
logger.log('');
|
|
254
|
+
// Display detailed events
|
|
255
|
+
logger.log('\n' + '='.repeat(120));
|
|
256
|
+
logger.log(`USAGE EVENTS FOR ${date.toDateString()}`);
|
|
257
|
+
logger.log('='.repeat(120) + '\n');
|
|
258
|
+
const tableData = events.map((event) => {
|
|
259
|
+
const timestamp = new Date(event.timestamp).toLocaleTimeString();
|
|
260
|
+
return [
|
|
261
|
+
timestamp,
|
|
262
|
+
event.model,
|
|
263
|
+
event.type,
|
|
264
|
+
event.inputTokens.toLocaleString(),
|
|
265
|
+
event.outputTokens.toLocaleString(),
|
|
266
|
+
event.tokens.toLocaleString(),
|
|
267
|
+
`$${event.cost?.toFixed(4) || '0.0000'}`,
|
|
268
|
+
];
|
|
269
|
+
});
|
|
270
|
+
const table = createTable(['Time', 'Model', 'Type', 'Input Tokens', 'Output Tokens', 'Total Tokens', 'Cost'], tableData);
|
|
271
|
+
logger.log(table);
|
|
272
|
+
// Summary
|
|
273
|
+
const totalTokens = events.reduce((sum, e) => sum + e.tokens, 0);
|
|
274
|
+
const totalCost = events.reduce((sum, e) => sum + (e.cost || 0), 0);
|
|
275
|
+
logger.log('\n' + '='.repeat(120));
|
|
276
|
+
logger.log(`Total Events: ${events.length}`);
|
|
277
|
+
logger.log(`Total Tokens: ${totalTokens.toLocaleString()}`);
|
|
278
|
+
logger.log(`Total Cost: $${totalCost.toFixed(2)}`);
|
|
279
|
+
logger.log('='.repeat(120) + '\n');
|
|
280
|
+
// Show breakdown if requested
|
|
281
|
+
if (options.breakdown) {
|
|
282
|
+
displayBreakdown(events, 'PER-MODEL BREAKDOWN');
|
|
283
|
+
}
|
|
284
|
+
}
|
|
273
285
|
}
|