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.
@@ -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">&times;</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&times;630</button>
120
- <button id="share-dl-story" class="btn">Download 1080&times;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">&times;</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&times;630</button>
120
+ <button id="share-dl-story" class="btn">Download 1080&times;1350</button>
121
+ </div>
122
+ </div>
123
+ </div>
124
+
125
+ <script src="app.js"></script>
126
+ </body>
127
+ </html>
@@ -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 = snap.buildRate ?? (snap._terminalCount !== undefined
184
- ? Math.round(((snap._editEvents?.length || 0) + (snap._terminalCount || 0)) / Math.max(1, tokens / 1000) * 100) / 100
185
- : 0);
186
- const cupFill = Math.min(95, Math.round(Math.sqrt(br) * 42));
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.4.1",
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",