claude-cup 0.4.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/web/index.html +127 -127
- package/mcp-server/src/index.js +25 -4
- package/package.json +1 -1
- package/src/aggregator.js +317 -297
- package/src/cli.js +55 -19
- package/src/leaderboard.js +370 -49
- package/src/statusline.js +71 -71
- package/src/tui.js +218 -20
- package/src/usage-api.js +250 -250
package/dist/web/index.html
CHANGED
|
@@ -1,127 +1,127 @@
|
|
|
1
|
-
<!doctype html>
|
|
2
|
-
<html lang="en">
|
|
3
|
-
<head>
|
|
4
|
-
<meta charset="utf-8" />
|
|
5
|
-
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
6
|
-
<title>claude-cup</title>
|
|
7
|
-
<link rel="stylesheet" href="styles.css" />
|
|
8
|
-
<link rel="icon" href="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 32 32'%3E%3Crect width='32' height='32' rx='7' fill='%23faf9f5'/%3E%3Cg stroke='%23d97757' stroke-width='3' stroke-linecap='round'%3E%3Cpath d='M16 5v22M5 16h22M8.2 8.2l15.6 15.6M23.8 8.2L8.2 23.8'/%3E%3C/g%3E%3C/svg%3E" />
|
|
9
|
-
</head>
|
|
10
|
-
<body>
|
|
11
|
-
<div id="app">
|
|
12
|
-
<header>
|
|
13
|
-
<div class="brand">
|
|
14
|
-
<svg width="22" height="22" viewBox="0 0 32 32" aria-hidden="true">
|
|
15
|
-
<g stroke="#d97757" stroke-width="3.4" stroke-linecap="round">
|
|
16
|
-
<path d="M16 3.5v25M3.5 16h25M7.2 7.2l17.6 17.6M24.8 7.2L7.2 24.8"/>
|
|
17
|
-
</g>
|
|
18
|
-
</svg>
|
|
19
|
-
<h1>claude-cup</h1>
|
|
20
|
-
<span id="live-dot" class="live-dot" title="connecting..."></span>
|
|
21
|
-
</div>
|
|
22
|
-
|
|
23
|
-
<div class="usage-pills">
|
|
24
|
-
<div class="pill pill-5h" id="pill-5h" title="5-hour rolling limit">
|
|
25
|
-
<span class="pill-label">5h window</span>
|
|
26
|
-
<span class="pill-value" id="pct-5h">--%</span>
|
|
27
|
-
<span class="pill-sub" id="reset-5h"></span>
|
|
28
|
-
</div>
|
|
29
|
-
<div class="pill pill-7d" id="pill-7d" title="weekly limit (all models)">
|
|
30
|
-
<span class="pill-label">weekly</span>
|
|
31
|
-
<div class="mini-bar"><div class="mini-bar-fill" id="bar-7d"></div></div>
|
|
32
|
-
<span class="pill-value small" id="pct-7d">--%</span>
|
|
33
|
-
</div>
|
|
34
|
-
</div>
|
|
35
|
-
|
|
36
|
-
<button id="eco-toggle" class="eco-toggle" aria-pressed="false" title="Eco mode - token saver (preview)">
|
|
37
|
-
<span class="eco-label">Eco</span>
|
|
38
|
-
<span class="eco-switch" aria-hidden="true"></span>
|
|
39
|
-
<span class="eco-state" id="eco-state">off</span>
|
|
40
|
-
</button>
|
|
41
|
-
|
|
42
|
-
<button id="share-btn" class="share-btn">Share my jar</button>
|
|
43
|
-
</header>
|
|
44
|
-
|
|
45
|
-
<div id="banner" class="banner hidden"></div>
|
|
46
|
-
|
|
47
|
-
<main>
|
|
48
|
-
<section id="jar-stage">
|
|
49
|
-
<div id="overflow-badge" class="overflow-badge hidden">OVERFLOWING</div>
|
|
50
|
-
<div id="empty-hint" class="empty-hint hidden">
|
|
51
|
-
<p>Your jar is ready.</p>
|
|
52
|
-
<p class="sub">Run Claude Code (or the desktop app) and watch the tokens drop in.</p>
|
|
53
|
-
</div>
|
|
54
|
-
<canvas id="jar-canvas"></canvas>
|
|
55
|
-
</section>
|
|
56
|
-
|
|
57
|
-
<aside id="stats-panel">
|
|
58
|
-
<div class="stat-card big">
|
|
59
|
-
<div class="stat-label">tokens today</div>
|
|
60
|
-
<div class="stat-value" id="stat-tokens">0</div>
|
|
61
|
-
<div class="stat-sub" id="stat-tokens-sub">in 0 / out 0</div>
|
|
62
|
-
</div>
|
|
63
|
-
<div class="stat-grid">
|
|
64
|
-
<div class="stat-card">
|
|
65
|
-
<div class="stat-label">est. cost</div>
|
|
66
|
-
<div class="stat-value" id="stat-cost">$0.00</div>
|
|
67
|
-
</div>
|
|
68
|
-
<div class="stat-card">
|
|
69
|
-
<div class="stat-label">build rate</div>
|
|
70
|
-
<div class="stat-value" id="stat-eff">0</div>
|
|
71
|
-
<div class="stat-sub" id="stat-eff-sub">eco mode off</div>
|
|
72
|
-
</div>
|
|
73
|
-
<div class="stat-card">
|
|
74
|
-
<div class="stat-label">messages</div>
|
|
75
|
-
<div class="stat-value" id="stat-messages">0</div>
|
|
76
|
-
</div>
|
|
77
|
-
<div class="stat-card">
|
|
78
|
-
<div class="stat-label">sessions</div>
|
|
79
|
-
<div class="stat-value" id="stat-sessions">0</div>
|
|
80
|
-
</div>
|
|
81
|
-
<div class="stat-card">
|
|
82
|
-
<div class="stat-label">rank</div>
|
|
83
|
-
<div class="stat-value" id="stat-burn">--</div>
|
|
84
|
-
</div>
|
|
85
|
-
<div class="stat-card">
|
|
86
|
-
<div class="stat-label">cache read</div>
|
|
87
|
-
<div class="stat-value" id="stat-cache">0</div>
|
|
88
|
-
</div>
|
|
89
|
-
</div>
|
|
90
|
-
<div class="legend" id="legend">
|
|
91
|
-
<div class="legend-item"><span class="dot dot-read"></span>read <b id="cat-read">0</b></div>
|
|
92
|
-
<div class="legend-item"><span class="dot dot-edit"></span>edit <b id="cat-edit">0</b></div>
|
|
93
|
-
<div class="legend-item"><span class="dot dot-terminal"></span>terminal <b id="cat-terminal">0</b></div>
|
|
94
|
-
<div class="legend-item"><span class="dot dot-web"></span>web <b id="cat-web">0</b></div>
|
|
95
|
-
<div class="legend-item"><span class="dot dot-agent"></span>agents <b id="cat-agent">0</b></div>
|
|
96
|
-
<div class="legend-item"><span class="dot dot-ai"></span>replies <b id="cat-ai">0</b></div>
|
|
97
|
-
</div>
|
|
98
|
-
</aside>
|
|
99
|
-
</main>
|
|
100
|
-
|
|
101
|
-
<footer id="shelf">
|
|
102
|
-
<div class="shelf-title">
|
|
103
|
-
<span>last 7 days</span>
|
|
104
|
-
<span id="streak" class="streak"></span>
|
|
105
|
-
</div>
|
|
106
|
-
<div id="shelf-jars" class="shelf-jars"></div>
|
|
107
|
-
</footer>
|
|
108
|
-
</div>
|
|
109
|
-
|
|
110
|
-
<div id="share-modal" class="modal hidden">
|
|
111
|
-
<div class="modal-card">
|
|
112
|
-
<div class="modal-head">
|
|
113
|
-
<h2>Share your jar</h2>
|
|
114
|
-
<button id="share-close" class="icon-btn">×</button>
|
|
115
|
-
</div>
|
|
116
|
-
<canvas id="share-preview"></canvas>
|
|
117
|
-
<div class="modal-actions">
|
|
118
|
-
<button id="share-copy" class="btn primary">Copy image</button>
|
|
119
|
-
<button id="share-dl-land" class="btn">Download 1200×630</button>
|
|
120
|
-
<button id="share-dl-story" class="btn">Download 1080×1350</button>
|
|
121
|
-
</div>
|
|
122
|
-
</div>
|
|
123
|
-
</div>
|
|
124
|
-
|
|
125
|
-
<script src="app.js"></script>
|
|
126
|
-
</body>
|
|
127
|
-
</html>
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="utf-8" />
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
6
|
+
<title>claude-cup</title>
|
|
7
|
+
<link rel="stylesheet" href="styles.css" />
|
|
8
|
+
<link rel="icon" href="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 32 32'%3E%3Crect width='32' height='32' rx='7' fill='%23faf9f5'/%3E%3Cg stroke='%23d97757' stroke-width='3' stroke-linecap='round'%3E%3Cpath d='M16 5v22M5 16h22M8.2 8.2l15.6 15.6M23.8 8.2L8.2 23.8'/%3E%3C/g%3E%3C/svg%3E" />
|
|
9
|
+
</head>
|
|
10
|
+
<body>
|
|
11
|
+
<div id="app">
|
|
12
|
+
<header>
|
|
13
|
+
<div class="brand">
|
|
14
|
+
<svg width="22" height="22" viewBox="0 0 32 32" aria-hidden="true">
|
|
15
|
+
<g stroke="#d97757" stroke-width="3.4" stroke-linecap="round">
|
|
16
|
+
<path d="M16 3.5v25M3.5 16h25M7.2 7.2l17.6 17.6M24.8 7.2L7.2 24.8"/>
|
|
17
|
+
</g>
|
|
18
|
+
</svg>
|
|
19
|
+
<h1>claude-cup</h1>
|
|
20
|
+
<span id="live-dot" class="live-dot" title="connecting..."></span>
|
|
21
|
+
</div>
|
|
22
|
+
|
|
23
|
+
<div class="usage-pills">
|
|
24
|
+
<div class="pill pill-5h" id="pill-5h" title="5-hour rolling limit">
|
|
25
|
+
<span class="pill-label">5h window</span>
|
|
26
|
+
<span class="pill-value" id="pct-5h">--%</span>
|
|
27
|
+
<span class="pill-sub" id="reset-5h"></span>
|
|
28
|
+
</div>
|
|
29
|
+
<div class="pill pill-7d" id="pill-7d" title="weekly limit (all models)">
|
|
30
|
+
<span class="pill-label">weekly</span>
|
|
31
|
+
<div class="mini-bar"><div class="mini-bar-fill" id="bar-7d"></div></div>
|
|
32
|
+
<span class="pill-value small" id="pct-7d">--%</span>
|
|
33
|
+
</div>
|
|
34
|
+
</div>
|
|
35
|
+
|
|
36
|
+
<button id="eco-toggle" class="eco-toggle" aria-pressed="false" title="Eco mode - token saver (preview)">
|
|
37
|
+
<span class="eco-label">Eco</span>
|
|
38
|
+
<span class="eco-switch" aria-hidden="true"></span>
|
|
39
|
+
<span class="eco-state" id="eco-state">off</span>
|
|
40
|
+
</button>
|
|
41
|
+
|
|
42
|
+
<button id="share-btn" class="share-btn">Share my jar</button>
|
|
43
|
+
</header>
|
|
44
|
+
|
|
45
|
+
<div id="banner" class="banner hidden"></div>
|
|
46
|
+
|
|
47
|
+
<main>
|
|
48
|
+
<section id="jar-stage">
|
|
49
|
+
<div id="overflow-badge" class="overflow-badge hidden">OVERFLOWING</div>
|
|
50
|
+
<div id="empty-hint" class="empty-hint hidden">
|
|
51
|
+
<p>Your jar is ready.</p>
|
|
52
|
+
<p class="sub">Run Claude Code (or the desktop app) and watch the tokens drop in.</p>
|
|
53
|
+
</div>
|
|
54
|
+
<canvas id="jar-canvas"></canvas>
|
|
55
|
+
</section>
|
|
56
|
+
|
|
57
|
+
<aside id="stats-panel">
|
|
58
|
+
<div class="stat-card big">
|
|
59
|
+
<div class="stat-label">tokens today</div>
|
|
60
|
+
<div class="stat-value" id="stat-tokens">0</div>
|
|
61
|
+
<div class="stat-sub" id="stat-tokens-sub">in 0 / out 0</div>
|
|
62
|
+
</div>
|
|
63
|
+
<div class="stat-grid">
|
|
64
|
+
<div class="stat-card">
|
|
65
|
+
<div class="stat-label">est. cost</div>
|
|
66
|
+
<div class="stat-value" id="stat-cost">$0.00</div>
|
|
67
|
+
</div>
|
|
68
|
+
<div class="stat-card">
|
|
69
|
+
<div class="stat-label">build rate</div>
|
|
70
|
+
<div class="stat-value" id="stat-eff">0</div>
|
|
71
|
+
<div class="stat-sub" id="stat-eff-sub">eco mode off</div>
|
|
72
|
+
</div>
|
|
73
|
+
<div class="stat-card">
|
|
74
|
+
<div class="stat-label">messages</div>
|
|
75
|
+
<div class="stat-value" id="stat-messages">0</div>
|
|
76
|
+
</div>
|
|
77
|
+
<div class="stat-card">
|
|
78
|
+
<div class="stat-label">sessions</div>
|
|
79
|
+
<div class="stat-value" id="stat-sessions">0</div>
|
|
80
|
+
</div>
|
|
81
|
+
<div class="stat-card">
|
|
82
|
+
<div class="stat-label">rank</div>
|
|
83
|
+
<div class="stat-value" id="stat-burn">--</div>
|
|
84
|
+
</div>
|
|
85
|
+
<div class="stat-card">
|
|
86
|
+
<div class="stat-label">cache read</div>
|
|
87
|
+
<div class="stat-value" id="stat-cache">0</div>
|
|
88
|
+
</div>
|
|
89
|
+
</div>
|
|
90
|
+
<div class="legend" id="legend">
|
|
91
|
+
<div class="legend-item"><span class="dot dot-read"></span>read <b id="cat-read">0</b></div>
|
|
92
|
+
<div class="legend-item"><span class="dot dot-edit"></span>edit <b id="cat-edit">0</b></div>
|
|
93
|
+
<div class="legend-item"><span class="dot dot-terminal"></span>terminal <b id="cat-terminal">0</b></div>
|
|
94
|
+
<div class="legend-item"><span class="dot dot-web"></span>web <b id="cat-web">0</b></div>
|
|
95
|
+
<div class="legend-item"><span class="dot dot-agent"></span>agents <b id="cat-agent">0</b></div>
|
|
96
|
+
<div class="legend-item"><span class="dot dot-ai"></span>replies <b id="cat-ai">0</b></div>
|
|
97
|
+
</div>
|
|
98
|
+
</aside>
|
|
99
|
+
</main>
|
|
100
|
+
|
|
101
|
+
<footer id="shelf">
|
|
102
|
+
<div class="shelf-title">
|
|
103
|
+
<span>last 7 days</span>
|
|
104
|
+
<span id="streak" class="streak"></span>
|
|
105
|
+
</div>
|
|
106
|
+
<div id="shelf-jars" class="shelf-jars"></div>
|
|
107
|
+
</footer>
|
|
108
|
+
</div>
|
|
109
|
+
|
|
110
|
+
<div id="share-modal" class="modal hidden">
|
|
111
|
+
<div class="modal-card">
|
|
112
|
+
<div class="modal-head">
|
|
113
|
+
<h2>Share your jar</h2>
|
|
114
|
+
<button id="share-close" class="icon-btn">×</button>
|
|
115
|
+
</div>
|
|
116
|
+
<canvas id="share-preview"></canvas>
|
|
117
|
+
<div class="modal-actions">
|
|
118
|
+
<button id="share-copy" class="btn primary">Copy image</button>
|
|
119
|
+
<button id="share-dl-land" class="btn">Download 1200×630</button>
|
|
120
|
+
<button id="share-dl-story" class="btn">Download 1080×1350</button>
|
|
121
|
+
</div>
|
|
122
|
+
</div>
|
|
123
|
+
</div>
|
|
124
|
+
|
|
125
|
+
<script src="app.js"></script>
|
|
126
|
+
</body>
|
|
127
|
+
</html>
|
package/mcp-server/src/index.js
CHANGED
|
@@ -171,6 +171,9 @@ async function startMcpServer() {
|
|
|
171
171
|
|
|
172
172
|
if (name === 'get-cup-stats') {
|
|
173
173
|
const fmt = (n) => (n >= 1e6 ? (n / 1e6).toFixed(2) + 'M' : n >= 1e3 ? (n / 1e3).toFixed(1) + 'k' : String(n ?? 0));
|
|
174
|
+
const fmtRank = (n) => Number(n || 0).toLocaleString('en-US');
|
|
175
|
+
|
|
176
|
+
// Daily stats (today)
|
|
174
177
|
let snap = {};
|
|
175
178
|
try {
|
|
176
179
|
const histPath = join(jarDir, 'history.json');
|
|
@@ -178,13 +181,23 @@ async function startMcpServer() {
|
|
|
178
181
|
const today = new Date().toISOString().slice(0, 10);
|
|
179
182
|
snap = hist.days?.[today]?._full || {};
|
|
180
183
|
} catch { /* no history yet */ }
|
|
184
|
+
|
|
185
|
+
// Leaderboard cache (rank, tier, neighbors)
|
|
186
|
+
let lb = {};
|
|
187
|
+
try {
|
|
188
|
+
const lbPath = join(jarDir, 'leaderboard-cache.json');
|
|
189
|
+
lb = JSON.parse(readFileSync(lbPath, 'utf8')) || {};
|
|
190
|
+
} catch { /* no leaderboard yet */ }
|
|
191
|
+
|
|
181
192
|
const tokens = snap.totalTokens || 0;
|
|
182
193
|
const msgs = snap.assistantMessages || 0;
|
|
183
|
-
const br =
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
194
|
+
const br = lb.buildRate ?? snap.buildRate ?? 0;
|
|
195
|
+
const cupFill = lb.percentile > 0
|
|
196
|
+
? lb.percentile
|
|
197
|
+
: Math.min(95, Math.round(Math.sqrt(br) * 42));
|
|
198
|
+
|
|
187
199
|
const result = {
|
|
200
|
+
// Daily / cup stats
|
|
188
201
|
build_rate: br,
|
|
189
202
|
cup_fill: `${cupFill}%`,
|
|
190
203
|
tokens_today: fmt(tokens),
|
|
@@ -193,6 +206,14 @@ async function startMcpServer() {
|
|
|
193
206
|
est_cost: `$${(snap.cost ? Math.round(snap.cost * 100) / 100 : 0).toFixed(2)}`,
|
|
194
207
|
burn_rate: `${fmt(snap.burnRate || 0)} tok/min`,
|
|
195
208
|
eco_mode: 'check TUI',
|
|
209
|
+
// Worldwide leaderboard
|
|
210
|
+
rank: lb.rank ? `#${fmtRank(lb.rank)}` : null,
|
|
211
|
+
rank_number: lb.rank || null,
|
|
212
|
+
total_builders: lb.total ? fmtRank(lb.total) : null,
|
|
213
|
+
percentile: lb.percentile ?? null,
|
|
214
|
+
tier: lb.tier || null,
|
|
215
|
+
above: lb.nextName ? { name: lb.nextName, rank: `#${fmtRank(lb.nextRank || (lb.rank ? lb.rank - 1 : 0))}` } : null,
|
|
216
|
+
below: lb.belowName ? { name: lb.belowName, rank: `#${fmtRank(lb.belowRank || (lb.rank ? lb.rank + 1 : 0))}` } : null,
|
|
196
217
|
};
|
|
197
218
|
return { content: [{ type: 'text', text: JSON.stringify(result) }] };
|
|
198
219
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "claude-cup",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.7.0",
|
|
4
4
|
"description": "Claude Jar v2 — native desktop visual companion (Tauri + Svelte) with MCP/hook integration for live Claude activity. Beautiful accumulating jar + live intensity meter. The jar is the usage meter.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|