ccusage-ui 0.1.1 → 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 +10 -3
- package/package.json +11 -3
- package/public/index.html +97 -18
- package/screenshot.png +0 -0
package/README.md
CHANGED
|
@@ -2,7 +2,9 @@
|
|
|
2
2
|
|
|
3
3
|
Web UI dashboard for [Claude Code](https://claude.ai/code) usage statistics.
|
|
4
4
|
|
|
5
|
-
](screenshot.png)
|
|
6
|
+
|
|
7
|
+

|
|
6
8
|

|
|
7
9
|
|
|
8
10
|
## Quick Start
|
|
@@ -24,6 +26,9 @@ ccusage-ui
|
|
|
24
26
|
- Model breakdown visualization
|
|
25
27
|
- Token usage and cost tracking
|
|
26
28
|
- User level tier display
|
|
29
|
+
- 🟣 **Legendary (100M+)**: Opus 4.5 Class
|
|
30
|
+
- 🟣 **Mega (50M+)**: Sonnet 4.5 Class
|
|
31
|
+
- 🔴 **Power (10M+)**: Haiku 4.5 Class
|
|
27
32
|
|
|
28
33
|
## Requirements
|
|
29
34
|
|
|
@@ -36,10 +41,12 @@ ccusage-ui
|
|
|
36
41
|
|
|
37
42
|
## Author
|
|
38
43
|
|
|
39
|
-
**Doha Park** - [
|
|
44
|
+
**Doha Park** - Creator of [CrewX](https://crewx.dev)
|
|
45
|
+
|
|
46
|
+
> "Do you use Claude Code like an employee? Manage your whole AI team with CrewX."
|
|
40
47
|
|
|
41
48
|
[](https://x.com/dohapark81)
|
|
42
|
-
[](https://www.threads.
|
|
49
|
+
[](https://www.threads.net/@dohapark81)
|
|
43
50
|
[](https://www.linkedin.com/in/dohapark81/)
|
|
44
51
|
|
|
45
52
|
## License
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ccusage-ui",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.3",
|
|
4
4
|
"main": "server.js",
|
|
5
5
|
"bin": {
|
|
6
6
|
"ccusage-ui": "server.js"
|
|
@@ -10,10 +10,18 @@
|
|
|
10
10
|
"test": "echo \"Error: no test specified\" && exit 1"
|
|
11
11
|
},
|
|
12
12
|
"keywords": [],
|
|
13
|
-
"author": "",
|
|
13
|
+
"author": "Doha Park",
|
|
14
14
|
"license": "MIT",
|
|
15
15
|
"description": "Web UI for Claude Code usage statistics",
|
|
16
|
+
"repository": {
|
|
17
|
+
"type": "git",
|
|
18
|
+
"url": "https://github.com/sowonlabs/ccusage-ui.git"
|
|
19
|
+
},
|
|
20
|
+
"homepage": "https://github.com/sowonlabs/ccusage-ui",
|
|
21
|
+
"bugs": {
|
|
22
|
+
"url": "https://github.com/sowonlabs/ccusage-ui/issues"
|
|
23
|
+
},
|
|
16
24
|
"dependencies": {
|
|
17
25
|
"ccusage": "^18.0.0"
|
|
18
26
|
}
|
|
19
|
-
}
|
|
27
|
+
}
|
package/public/index.html
CHANGED
|
@@ -220,7 +220,25 @@
|
|
|
220
220
|
th { color: var(--text-secondary); font-weight: 600; }
|
|
221
221
|
tr:last-child td { border-bottom: none; }
|
|
222
222
|
.cost-positive { color: #ff3b30; font-weight: 600; }
|
|
223
|
-
|
|
223
|
+
|
|
224
|
+
.share-btn {
|
|
225
|
+
background: #000;
|
|
226
|
+
color: #fff;
|
|
227
|
+
border: none;
|
|
228
|
+
padding: 6px 12px;
|
|
229
|
+
border-radius: 16px;
|
|
230
|
+
font-size: 12px;
|
|
231
|
+
font-weight: 600;
|
|
232
|
+
cursor: pointer;
|
|
233
|
+
display: inline-flex;
|
|
234
|
+
align-items: center;
|
|
235
|
+
gap: 6px;
|
|
236
|
+
transition: transform 0.2s;
|
|
237
|
+
margin-top: 8px;
|
|
238
|
+
text-decoration: none;
|
|
239
|
+
}
|
|
240
|
+
.share-btn:hover { transform: scale(1.05); background: #333; }
|
|
241
|
+
</style>
|
|
224
242
|
</head>
|
|
225
243
|
<body>
|
|
226
244
|
<div id="loading">
|
|
@@ -262,9 +280,15 @@
|
|
|
262
280
|
<div>
|
|
263
281
|
<div style="display: flex; align-items: center; gap: 8px;">
|
|
264
282
|
<h2 style="margin:0; font-size:18px;">Usage Trend</h2>
|
|
265
|
-
<span class="tier-info" data-tippy-content="🌱 Starter:
|
|
283
|
+
<span class="tier-info" data-tippy-content="🌱 Starter: <1M<br>⚡ Pro: 1M+ (Daily User)<br>🔴 Power: 10M+ (Haiku 4.5 Class)<br>🟣 Mega: 50M+ (Sonnet 4.5 Class)<br>🟣 Legendary: 100M+ (Opus 4.5 Class)">?</span>
|
|
266
284
|
</div>
|
|
285
|
+
|
|
267
286
|
<div id="userLevel" style="font-size:12px; color:#0071e3; margin-top:4px; font-weight:500;"></div>
|
|
287
|
+
<button onclick="shareStats()" class="share-btn">
|
|
288
|
+
<svg width="12" height="12" viewBox="0 0 24 24" fill="currentColor"><path d="M18.244 2.25h3.308l-7.227 8.26 8.502 11.24H16.17l-5.214-6.817L4.99 21.75H1.68l7.73-8.835L1.254 2.25H8.08l4.713 6.231zm-1.161 17.52h1.833L7.084 4.126H5.117z"/></svg>
|
|
289
|
+
Share Stats
|
|
290
|
+
</button>
|
|
291
|
+
|
|
268
292
|
</div>
|
|
269
293
|
<div class="tabs">
|
|
270
294
|
<button class="tab active" onclick="switchMetric('tokens')">Tokens</button>
|
|
@@ -306,6 +330,12 @@
|
|
|
306
330
|
</div>
|
|
307
331
|
|
|
308
332
|
<footer style="text-align: center; margin-top: 40px; padding: 30px 20px; color: var(--text-secondary); font-size: 13px; border-top: 1px solid #e5e5e7;">
|
|
333
|
+
<div style="margin-bottom: 24px; font-size: 15px;">
|
|
334
|
+
Do you use Claude Code like an employee? <br>
|
|
335
|
+
<a href="https://crewx.dev" target="_blank" style="color: #0071e3; text-decoration: none; font-weight: 600;">
|
|
336
|
+
Manage your whole AI team with CrewX →
|
|
337
|
+
</a>
|
|
338
|
+
</div>
|
|
309
339
|
<div style="display: flex; justify-content: center; align-items: center; gap: 20px; margin-bottom: 16px;">
|
|
310
340
|
<a href="https://github.com/sowonlabs/ccusage-ui" target="_blank" title="GitHub" style="color: var(--text-secondary); transition: color 0.2s;">
|
|
311
341
|
<svg width="22" height="22" viewBox="0 0 24 24" fill="currentColor"><path d="M12 0C5.37 0 0 5.37 0 12c0 5.31 3.435 9.795 8.205 11.385.6.105.825-.255.825-.57 0-.285-.015-1.23-.015-2.235-3.015.555-3.795-.735-4.035-1.41-.135-.345-.72-1.41-1.23-1.695-.42-.225-1.02-.78-.015-.795.945-.015 1.62.87 1.845 1.23 1.08 1.815 2.805 1.305 3.495.99.105-.78.42-1.305.765-1.605-2.67-.3-5.46-1.335-5.46-5.925 0-1.305.465-2.385 1.23-3.225-.12-.3-.54-1.53.12-3.18 0 0 1.005-.315 3.3 1.23.96-.27 1.98-.405 3-.405s2.04.135 3 .405c2.295-1.56 3.3-1.23 3.3-1.23.66 1.65.24 2.88.12 3.18.765.84 1.23 1.905 1.23 3.225 0 4.605-2.805 5.625-5.475 5.925.435.375.81 1.095.81 2.22 0 1.605-.015 2.895-.015 3.3 0 .315.225.69.825.57A12.02 12.02 0 0024 12c0-6.63-5.37-12-12-12z"/></svg>
|
|
@@ -313,7 +343,7 @@
|
|
|
313
343
|
<a href="https://x.com/dohapark81" target="_blank" title="X (Twitter)" style="color: var(--text-secondary); transition: color 0.2s;">
|
|
314
344
|
<svg width="20" height="20" viewBox="0 0 24 24" fill="currentColor"><path d="M18.244 2.25h3.308l-7.227 8.26 8.502 11.24H16.17l-5.214-6.817L4.99 21.75H1.68l7.73-8.835L1.254 2.25H8.08l4.713 6.231zm-1.161 17.52h1.833L7.084 4.126H5.117z"/></svg>
|
|
315
345
|
</a>
|
|
316
|
-
<a href="https://www.threads.
|
|
346
|
+
<a href="https://www.threads.net/@dohapark81" target="_blank" title="Threads" style="color: var(--text-secondary); transition: color 0.2s;">
|
|
317
347
|
<svg width="20" height="20" viewBox="0 0 24 24" fill="currentColor"><path d="M12.186 24h-.007c-3.581-.024-6.334-1.205-8.184-3.509C2.35 18.44 1.5 15.586 1.472 12.01v-.017c.03-3.579.879-6.43 2.525-8.482C5.845 1.205 8.6.024 12.18 0h.014c2.746.02 5.043.725 6.826 2.098 1.677 1.29 2.858 3.13 3.509 5.467l-2.04.569c-1.104-3.96-3.898-5.984-8.304-6.015-2.91.022-5.11.936-6.54 2.717C4.307 6.504 3.616 8.914 3.589 12c.027 3.086.718 5.496 2.057 7.164 1.43 1.783 3.631 2.698 6.54 2.717 2.623-.02 4.358-.631 5.8-2.045 1.647-1.613 1.618-3.593 1.09-4.798-.31-.71-.873-1.3-1.634-1.75-.192 1.352-.622 2.446-1.284 3.272-.886 1.102-2.14 1.704-3.73 1.79-1.202.065-2.361-.218-3.259-.801-1.063-.689-1.685-1.74-1.752-2.96-.065-1.17.408-2.274 1.33-3.109.858-.775 2.071-1.263 3.51-1.413 1.044-.11 2.016-.073 2.91.088-.07-.653-.274-1.176-.617-1.58-.457-.539-1.148-.823-2.002-.823h-.082c-.68.013-1.241.209-1.669.583l-1.394-1.54c.78-.705 1.793-1.082 3.02-1.126h.11c1.515 0 2.725.503 3.6 1.494.78.885 1.207 2.084 1.27 3.56.455.155.874.337 1.255.548 1.253.695 2.17 1.678 2.647 2.843.716 1.748.682 4.494-1.433 6.564-1.905 1.865-4.287 2.727-7.492 2.747zm-1.25-9.01c-1.29.137-2.24.49-2.75.962-.41.382-.594.817-.548 1.298.063 1.04 1.09 1.696 2.61 1.613 1.076-.058 1.907-.453 2.47-1.173.496-.634.783-1.503.855-2.592-.846-.153-1.735-.194-2.637-.108z"/></svg>
|
|
318
348
|
</a>
|
|
319
349
|
<a href="https://www.linkedin.com/in/dohapark81/" target="_blank" title="LinkedIn" style="color: var(--text-secondary); transition: color 0.2s;">
|
|
@@ -463,10 +493,10 @@
|
|
|
463
493
|
let displayHTML = "";
|
|
464
494
|
|
|
465
495
|
const getLevelName = (val) => {
|
|
466
|
-
if (val >=
|
|
467
|
-
if (val >=
|
|
468
|
-
if (val >=
|
|
469
|
-
if (val >=
|
|
496
|
+
if (val >= 100) return "🟣 Legendary (Opus 4.5 Class)";
|
|
497
|
+
if (val >= 50) return "🟣 Mega (Sonnet 4.5 Class)";
|
|
498
|
+
if (val >= 10) return "🔴 Power (Haiku 4.5 Class)";
|
|
499
|
+
if (val >= 1) return "⚡ Pro (Daily User)";
|
|
470
500
|
return "🌱 Starter";
|
|
471
501
|
};
|
|
472
502
|
|
|
@@ -479,10 +509,10 @@
|
|
|
479
509
|
displayHTML = `
|
|
480
510
|
<div style="display:flex; flex-direction:column; gap:4px; border-left: 3px solid #0071e3; padding-left: 10px;">
|
|
481
511
|
<div style="font-size: 14px; color: #1d1d1f; display: flex; align-items: center;">
|
|
482
|
-
Current: <b style="color:#0071e3">${getLevelName(lastVal)}</b> <span style="color:#86868b; margin-left: 5px;">(${lastVal.toFixed(
|
|
512
|
+
Current: <b style="color:#0071e3">${getLevelName(lastVal)}</b> <span style="color:#86868b; margin-left: 5px;">(${lastVal.toFixed(1)}M)</span>
|
|
483
513
|
</div>
|
|
484
514
|
<div style="font-size: 14px; color: #1d1d1f;">
|
|
485
|
-
Pace: <b style="color:#5856d6">${getLevelName(projection)}</b> <span style="color:#86868b">(${projection.toFixed(
|
|
515
|
+
Pace: <b style="color:#5856d6">${getLevelName(projection)}</b> <span style="color:#86868b">(${projection.toFixed(1)}M)</span>
|
|
486
516
|
</div>
|
|
487
517
|
</div>
|
|
488
518
|
`;
|
|
@@ -529,19 +559,19 @@
|
|
|
529
559
|
};
|
|
530
560
|
|
|
531
561
|
if (currentView === 'monthly') {
|
|
532
|
-
drawLine(
|
|
533
|
-
drawLine(
|
|
534
|
-
drawLine(
|
|
562
|
+
drawLine(10, '#ff3b30', 'Power (10M)');
|
|
563
|
+
drawLine(50, '#af52de', 'Mega (50M)');
|
|
564
|
+
drawLine(100, '#5856d6', 'Legendary (100M)');
|
|
535
565
|
} else {
|
|
536
566
|
// Daily Benchmarks
|
|
537
567
|
|
|
538
568
|
// 1. Tier Thresholds (Lighter, background context)
|
|
539
|
-
// Legendary (
|
|
540
|
-
drawLine(
|
|
541
|
-
// Mega (
|
|
542
|
-
drawLine(
|
|
543
|
-
// Power (
|
|
544
|
-
drawLine(
|
|
569
|
+
// Legendary (100M/mo -> ~3.3M/day)
|
|
570
|
+
drawLine(3.3, 'rgba(88, 86, 214, 0.4)', 'Legendary (3.3M)');
|
|
571
|
+
// Mega (50M/mo -> ~1.6M/day)
|
|
572
|
+
drawLine(1.6, 'rgba(175, 82, 222, 0.4)', 'Mega (1.6M)');
|
|
573
|
+
// Power (10M/mo -> ~0.33M/day)
|
|
574
|
+
drawLine(0.33, 'rgba(255, 59, 48, 0.4)', 'Power (0.33M)');
|
|
545
575
|
|
|
546
576
|
// 2. User Average (Stronger, personal metric)
|
|
547
577
|
const sum = datasetData.reduce((a, b) => a + b, 0);
|
|
@@ -698,6 +728,55 @@
|
|
|
698
728
|
});
|
|
699
729
|
}
|
|
700
730
|
|
|
731
|
+
|
|
732
|
+
function shareStats() {
|
|
733
|
+
const now = new Date();
|
|
734
|
+
const currentMonthStr = now.toISOString().slice(0, 7);
|
|
735
|
+
const lastData = monthlyData.find(m => m.month === currentMonthStr);
|
|
736
|
+
// Fallback if no monthly data yet
|
|
737
|
+
let lastVal = 0;
|
|
738
|
+
if (lastData) {
|
|
739
|
+
lastVal = (lastData.totalTokens || (lastData.inputTokens + lastData.outputTokens)) / 1000000;
|
|
740
|
+
} else if (dailyData.length > 0) {
|
|
741
|
+
// Try to sum daily data for this month if monthly api fails or is empty
|
|
742
|
+
const thisMonthDaily = dailyData.filter(d => d.date.startsWith(currentMonthStr));
|
|
743
|
+
const sumTokens = thisMonthDaily.reduce((acc, d) => acc + (d.totalTokens || (d.inputTokens + d.outputTokens)), 0);
|
|
744
|
+
lastVal = sumTokens / 1000000;
|
|
745
|
+
}
|
|
746
|
+
|
|
747
|
+
// Simple Projection Logic for 'Pace' if current month
|
|
748
|
+
const day = now.getDate();
|
|
749
|
+
const daysInMonth = new Date(now.getFullYear(), now.getMonth() + 1, 0).getDate();
|
|
750
|
+
let projected = lastVal;
|
|
751
|
+
if (day > 0) {
|
|
752
|
+
projected = (lastVal / day) * daysInMonth;
|
|
753
|
+
}
|
|
754
|
+
|
|
755
|
+
const getLevelName = (val) => {
|
|
756
|
+
if (val >= 100) return "Legendary (Opus 4.5 Class)";
|
|
757
|
+
if (val >= 50) return "Mega (Sonnet 4.5 Class)";
|
|
758
|
+
if (val >= 10) return "Power (Haiku 4.5 Class)";
|
|
759
|
+
if (val >= 1) return "Pro (Daily User)";
|
|
760
|
+
return "Starter";
|
|
761
|
+
};
|
|
762
|
+
|
|
763
|
+
const level = getLevelName(projected);
|
|
764
|
+
|
|
765
|
+
const text = `I'm a ${level} AI user.
|
|
766
|
+
My monthly usage pace is ${projected.toFixed(1)}M tokens.
|
|
767
|
+
|
|
768
|
+
Check yours:
|
|
769
|
+
npx ccusage-ui
|
|
770
|
+
|
|
771
|
+
Do you use Claude Code like an employee?
|
|
772
|
+
Manage your team with @CrewX
|
|
773
|
+
|
|
774
|
+
#ClaudeCode #CrewX #SowonLabs`;
|
|
775
|
+
|
|
776
|
+
const url = `https://twitter.com/intent/tweet?text=${encodeURIComponent(text)}`;
|
|
777
|
+
window.open(url, '_blank');
|
|
778
|
+
}
|
|
779
|
+
|
|
701
780
|
// Initialize tooltips
|
|
702
781
|
tippy('.tier-info', {
|
|
703
782
|
allowHTML: true,
|
package/screenshot.png
ADDED
|
Binary file
|