clauddy 1.16.0 → 1.17.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 +2 -0
- package/package.json +2 -1
- package/renderer/pet.js +17 -3
- package/renderer/style.css +6 -2
package/README.md
CHANGED
|
@@ -179,6 +179,8 @@ Switching is instant — no restart. (On Windows/Linux the icon lives in the sys
|
|
|
179
179
|
|
|
180
180
|
Optional **macOS notifications** when your session or weekly usage crosses the thresholds you set (default **80%** and **95%**) — e.g. _"Your session is over 80% — now at 82%"_. They re-arm automatically once usage drops back below a threshold (after a reset). Toggle them and edit the thresholds in **⚙ Settings**.
|
|
181
181
|
|
|
182
|
+
The first alert asks macOS for permission; after that the app shows up in **System Settings > Notifications** like any other.
|
|
183
|
+
|
|
182
184
|
## Configure (`config.json`)
|
|
183
185
|
|
|
184
186
|
Settings saved from the UI live in `~/.claude-usage-monitor/config.json`, so you can tweak them without rebuilding:
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "clauddy",
|
|
3
3
|
"desktopName": "clauddy.desktop",
|
|
4
|
-
"version": "1.
|
|
4
|
+
"version": "1.17.1",
|
|
5
5
|
"description": "A cute desktop pet that tracks your Claude Code usage",
|
|
6
6
|
"main": "main.js",
|
|
7
7
|
"bin": {
|
|
@@ -61,6 +61,7 @@
|
|
|
61
61
|
},
|
|
62
62
|
"build": {
|
|
63
63
|
"appId": "app.clauddy",
|
|
64
|
+
"afterPack": "scripts/adhoc-sign.js",
|
|
64
65
|
"productName": "Clauddy",
|
|
65
66
|
"directories": {
|
|
66
67
|
"output": "dist"
|
package/renderer/pet.js
CHANGED
|
@@ -162,6 +162,19 @@ function fmtReset(ms) {
|
|
|
162
162
|
const m = Math.floor((ms % 3600000) / 60000)
|
|
163
163
|
return h > 0 ? `${h}h ${m}m` : `${m}m`
|
|
164
164
|
}
|
|
165
|
+
// wall-clock time of the reset, in the machine's own locale + timezone.
|
|
166
|
+
// Past 24h the day matters too, so prefix the weekday.
|
|
167
|
+
function fmtResetClock(ms) {
|
|
168
|
+
if (!ms || ms <= 0) return null
|
|
169
|
+
const at = new Date(Date.now() + ms)
|
|
170
|
+
const time = at.toLocaleTimeString([], { hour: 'numeric', minute: '2-digit' })
|
|
171
|
+
return ms >= 86400000 ? `${at.toLocaleDateString([], { weekday: 'short' })} ${time}` : time
|
|
172
|
+
}
|
|
173
|
+
// "2h 22m (14:35)" — countdown plus the clock time it lands on
|
|
174
|
+
function fmtResetIn(ms) {
|
|
175
|
+
const at = fmtResetClock(ms)
|
|
176
|
+
return at ? `${fmtReset(ms)} (${at})` : fmtReset(ms)
|
|
177
|
+
}
|
|
165
178
|
// burn-rate projection lives in burn.js (shared with the tests)
|
|
166
179
|
const burn = Burn.createBurnTracker()
|
|
167
180
|
|
|
@@ -420,7 +433,7 @@ function renderScoped(list, byModel) {
|
|
|
420
433
|
m.innerHTML =
|
|
421
434
|
`<div class="meter-top"><span>weekly · ${esc(key)}</span><span>${Math.round(s.pct)}%</span></div>` +
|
|
422
435
|
`<div class="track"><div class="fill week${s.pct >= 80 ? ' high' : ''}" style="width:${s.pct}%"></div></div>` +
|
|
423
|
-
`<div class="sub">${s.resetMs != null ? `resets in ${
|
|
436
|
+
`<div class="sub">${s.resetMs != null ? `resets in ${fmtResetIn(s.resetMs)} · ` : ''}${fmtTokens(tokens)} tokens</div>`
|
|
424
437
|
box.appendChild(m)
|
|
425
438
|
}
|
|
426
439
|
}
|
|
@@ -568,7 +581,7 @@ function render(d) {
|
|
|
568
581
|
sf.style.width = `${sessPct}%`
|
|
569
582
|
sf.classList.toggle('high', sessPct >= 80)
|
|
570
583
|
el('session-sub').textContent = sessActive
|
|
571
|
-
? `resets in ${
|
|
584
|
+
? `resets in ${fmtResetIn(sessReset)} · ${fmtTokens(d.session.tokens)} tokens`
|
|
572
585
|
: 'no active session'
|
|
573
586
|
|
|
574
587
|
// where this pace is taking you — hidden until there's enough trail to tell
|
|
@@ -589,7 +602,7 @@ function render(d) {
|
|
|
589
602
|
wf.classList.toggle('high', wkPct >= 80)
|
|
590
603
|
el('week-sub').textContent =
|
|
591
604
|
wkReset != null
|
|
592
|
-
? `resets in ${
|
|
605
|
+
? `resets in ${fmtResetIn(wkReset)} · ${fmtTokens(d.week.tokens)} tokens`
|
|
593
606
|
: `${fmtTokens(d.week.tokens)} tokens · last 7 days`
|
|
594
607
|
|
|
595
608
|
renderScoped(liveOn ? realUsage.scoped || [] : [], d.byModel || [])
|
|
@@ -1006,6 +1019,7 @@ if (typeof module === 'object' && module.exports) {
|
|
|
1006
1019
|
render,
|
|
1007
1020
|
fmtTokens,
|
|
1008
1021
|
fmtReset,
|
|
1022
|
+
fmtResetIn,
|
|
1009
1023
|
setState,
|
|
1010
1024
|
renderModels,
|
|
1011
1025
|
renderProjects,
|
package/renderer/style.css
CHANGED
|
@@ -1744,10 +1744,14 @@ body.state-tired #status-text {
|
|
|
1744
1744
|
|
|
1745
1745
|
/* meter subtitle */
|
|
1746
1746
|
.sub {
|
|
1747
|
-
|
|
1747
|
+
/* small enough that "resets in 69h 15m (Fri 7:01 AM) · 1.02B tokens" stays on one line */
|
|
1748
|
+
font-size: 9px;
|
|
1748
1749
|
color: var(--muted);
|
|
1749
1750
|
margin-top: 4px;
|
|
1750
|
-
letter-spacing:
|
|
1751
|
+
letter-spacing: 0px;
|
|
1752
|
+
white-space: nowrap;
|
|
1753
|
+
overflow: hidden;
|
|
1754
|
+
text-overflow: ellipsis;
|
|
1751
1755
|
}
|
|
1752
1756
|
|
|
1753
1757
|
/* burn-rate projection — calm by default, warm when you'd run out first */
|