Initial commit: Claude Live Dashboard

Always-on-Top Electron-Widget für die Claude-Plan-Auslastung unter Windows.
Liest Transkripte lokal, fragt optional den /usage-Endpunkt ab, bietet einen
Einstellungsdialog und lässt sich als NSIS-Installer oder portable Fassung
bauen.
This commit is contained in:
Winkler, Stefan
2026-07-22 12:59:54 +02:00
commit 868f31fa9a
28 changed files with 8971 additions and 0 deletions
+156
View File
@@ -0,0 +1,156 @@
<!doctype html>
<html lang="de">
<head>
<meta charset="utf-8" />
<meta http-equiv="Content-Security-Policy" content="default-src 'none'; style-src 'self'; script-src 'self';" />
<title>Claude Live Dashboard</title>
<link rel="stylesheet" href="styles.css" />
</head>
<body>
<div class="widget" id="widget">
<!-- Kopfzeile: einziger Ziehbereich des rahmenlosen Fensters -->
<header class="titlebar">
<span class="dot-brand" aria-hidden="true"></span>
<span class="title" id="plan-label">Claude</span>
<span class="spacer"></span>
<span class="badge warn" id="error-badge" hidden title="Details öffnen für die Meldung">Hinweis</span>
<span class="badge warn" id="stale-badge" hidden>veraltet</span>
<button class="icon-btn" id="btn-settings" title="Einstellungen" aria-label="Einstellungen">
<svg viewBox="0 0 16 16" width="13" height="13" aria-hidden="true" focusable="false">
<path
fill="currentColor"
d="M8 5.2a2.8 2.8 0 1 0 0 5.6 2.8 2.8 0 0 0 0-5.6Zm0 1.4a1.4 1.4 0 1 1 0 2.8 1.4 1.4 0 0 1 0-2.8Z"
/>
<path
fill="currentColor"
d="M6.9.9a.7.7 0 0 0-.69.58l-.2 1.16a5.6 5.6 0 0 0-1.02.59l-1.1-.42a.7.7 0 0 0-.85.31l-1.1 1.9a.7.7 0 0 0 .16.89l.9.74a5.65 5.65 0 0 0 0 1.18l-.9.74a.7.7 0 0 0-.16.89l1.1 1.9a.7.7 0 0 0 .85.31l1.1-.42c.32.24.66.44 1.02.59l.2 1.16a.7.7 0 0 0 .69.58h2.2a.7.7 0 0 0 .69-.58l.2-1.16c.36-.15.7-.35 1.02-.59l1.1.42a.7.7 0 0 0 .85-.31l1.1-1.9a.7.7 0 0 0-.16-.89l-.9-.74a5.65 5.65 0 0 0 0-1.18l.9-.74a.7.7 0 0 0 .16-.89l-1.1-1.9a.7.7 0 0 0-.85-.31l-1.1.42a5.6 5.6 0 0 0-1.02-.59l-.2-1.16A.7.7 0 0 0 9.1.9H6.9Zm.59 1.4h1.02l.17.99a.7.7 0 0 0 .5.55c.46.14.89.39 1.24.72a.7.7 0 0 0 .73.14l.94-.36.51.88-.77.63a.7.7 0 0 0-.25.7 4.25 4.25 0 0 1 0 1.44.7.7 0 0 0 .25.7l.77.63-.51.88-.94-.36a.7.7 0 0 0-.73.14c-.35.33-.78.58-1.24.72a.7.7 0 0 0-.5.55l-.17.99H7.49l-.17-.99a.7.7 0 0 0-.5-.55 4.2 4.2 0 0 1-1.24-.72.7.7 0 0 0-.73-.14l-.94.36-.51-.88.77-.63a.7.7 0 0 0 .25-.7 4.25 4.25 0 0 1 0-1.44.7.7 0 0 0-.25-.7l-.77-.63.51-.88.94.36a.7.7 0 0 0 .73-.14c.35-.33.78-.58 1.24-.72a.7.7 0 0 0 .5-.55l.17-.99Z"
/>
</svg>
</button>
<button class="icon-btn" id="btn-hide" title="Ausblenden (über das Tray-Symbol zurückholen)"></button>
</header>
<main class="meters">
<!-- Laufende Sitzung: das kurzfristig bindende Limit -->
<section class="meter" id="meter-block">
<div class="meter-head">
<span class="meter-label">Laufende Sitzung</span>
<span class="meter-value" id="block-percent"></span>
</div>
<div class="track" role="img" aria-labelledby="block-a11y">
<div class="fill" id="block-fill"></div>
<div class="projection" id="block-projection" hidden></div>
</div>
<div class="meter-foot">
<span class="status" id="block-status"><span class="status-icon" aria-hidden="true"></span><span class="status-text"></span></span>
<span class="reset" id="block-reset"></span>
</div>
<div class="session-figures">
<div class="figure">
<span class="figure-value" id="session-tokens"></span>
<span class="figure-label">Tokens</span>
</div>
<div class="figure">
<span class="figure-value" id="session-rate"></span>
<span class="figure-label">pro Minute</span>
</div>
</div>
<span class="sr-only" id="block-a11y"></span>
</section>
<!-- Wochenkontingent -->
<section class="meter" id="meter-week">
<div class="meter-head">
<span class="meter-label">Wochenkontingent</span>
<span class="meter-value" id="week-percent"></span>
</div>
<div class="track" role="img" aria-labelledby="week-a11y">
<div class="fill" id="week-fill"></div>
<div class="projection" id="week-projection" hidden></div>
</div>
<div class="meter-foot">
<span class="status" id="week-status"><span class="status-icon" aria-hidden="true"></span><span class="status-text"></span></span>
<span class="reset" id="week-reset"></span>
</div>
<span class="sr-only" id="week-a11y"></span>
</section>
<!-- Nutzungsguthaben — nur wenn der Server es meldet -->
<section class="meter" id="meter-spend" hidden>
<div class="meter-head">
<span class="meter-label">Nutzungsguthaben</span>
<span class="meter-value" id="spend-value"></span>
</div>
<div class="track" role="img" aria-labelledby="spend-a11y">
<div class="fill" id="spend-fill"></div>
</div>
<div class="meter-foot">
<span class="status" id="spend-status"><span class="status-icon" aria-hidden="true"></span><span class="status-text"></span></span>
<span class="reset" id="spend-limit"></span>
</div>
<span class="sr-only" id="spend-a11y"></span>
</section>
<p class="runway" id="session-runway"></p>
</main>
<button class="expander" id="btn-expand" aria-expanded="false" aria-controls="details">
<span id="expander-label">Details</span>
<span class="chevron" aria-hidden="true"></span>
</button>
<!-- Detailansicht -->
<div class="details" id="details" hidden>
<section class="detail-block">
<h2>Tokenverbrauch im laufenden Fenster</h2>
<div class="stacked" id="model-bar" role="img" aria-labelledby="model-a11y"></div>
<ul class="legend" id="model-legend"></ul>
<span class="sr-only" id="model-a11y"></span>
<table class="model-table" id="model-table">
<thead>
<tr>
<th scope="col">Modell</th>
<th scope="col" class="num">Ausgabe</th>
<th scope="col" class="num">Cache</th>
<th scope="col" class="num">Gesamt</th>
</tr>
</thead>
<tbody></tbody>
</table>
</section>
<section class="detail-block">
<h2>Tempo</h2>
<dl class="facts">
<dt>Burn-Rate</dt>
<dd id="fact-burn"></dd>
<dt>Woche in 1 Std.</dt>
<dd id="fact-projection"></dd>
<dt>Kontingent reicht noch</dt>
<dd id="fact-ttl"></dd>
<dt>Nachrichten in der Sitzung</dt>
<dd id="fact-messages"></dd>
</dl>
</section>
<section class="detail-block">
<h2>Datengrundlage</h2>
<dl class="facts">
<dt id="fact-confidence-label" hidden>Genauigkeit 5 Std.</dt>
<dd id="fact-confidence" hidden></dd>
<dt>Genauigkeit Woche</dt>
<dd id="fact-confidence-week"></dd>
<dt>Serverabfrage</dt>
<dd id="fact-oauth"></dd>
<dt>Aktualisiert</dt>
<dd id="fact-updated"></dd>
</dl>
<p class="hint" id="confidence-hint"></p>
<ul class="errors" id="errors" hidden></ul>
</section>
</div>
</div>
<script src="app.js"></script>
</body>
</html>