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.
230 lines
9.2 KiB
Markdown
230 lines
9.2 KiB
Markdown
# Claude Live Dashboard
|
||
|
||
Ein rahmenloses Always-on-Top-Widget für Windows, das die Auslastung des
|
||
Claude-Plans live anzeigt: 5-Stunden-Fenster, Wochenverbrauch, Reset-Countdown,
|
||
Tokenverbrauch je Modell und die Hochrechnung auf das Fensterende.
|
||
|
||
Die Daten stammen aus den Transkripten, die Claude Code ohnehin unter
|
||
`~/.claude/projects/**/*.jsonl` schreibt. Es wird nichts installiert, nichts
|
||
mitgeschnitten und standardmäßig keine Netzwerkverbindung aufgebaut.
|
||
|
||
## Start
|
||
|
||
Node.js wird benötigt. Ist es nicht im `PATH` (etwa bei nvm-windows ohne
|
||
aktive Version), genügt der Versionspfad:
|
||
|
||
```powershell
|
||
$env:PATH = "$env:APPDATA\nvm\v22.22.1;$env:PATH"
|
||
npm install
|
||
npm start
|
||
```
|
||
|
||
Das Tray-Symbol landet unter Windows zunächst im Überlaufbereich hinter dem
|
||
`^` in der Taskleiste; per Drag lässt es sich dauerhaft sichtbar machen.
|
||
|
||
## Bedienung
|
||
|
||
| Aktion | Wirkung |
|
||
|---|---|
|
||
| Kopfzeile ziehen | Fenster verschieben (Position wird gemerkt) |
|
||
| ⚙ | Einstellungen öffnen |
|
||
| „Details“ | Modell-Aufschlüsselung, Tempo und Datengrundlage aufklappen |
|
||
| `–` | Ausblenden — Rückkehr über das Tray-Symbol |
|
||
| Tray-Klick | Ein-/Ausblenden |
|
||
| Tray-Menü | Deckkraft, Klick-Durchlässigkeit, Autostart, Einstellungen, Beenden |
|
||
|
||
### Einstellungen
|
||
|
||
Das Zahnrad in der Kopfzeile öffnet einen Dialog für alle Felder der
|
||
`config.json`: Deckkraft, Klick-Durchlässigkeit, Autostart, Serverabfrage,
|
||
Bezugsgrößen, Gewichtung und Wochenfenster.
|
||
|
||
Gespeicherte Änderungen greifen **sofort** — ohne Neustart. Der Dialog liest
|
||
und schreibt dieselbe Datei, die sich auch von Hand bearbeiten lässt:
|
||
Kommentarfelder (`_hinweis` und Verwandte) und unbekannte Einträge bleiben
|
||
dabei unangetastet, weil die vorhandene Datei nur ergänzt und nicht ersetzt
|
||
wird. `Strg`+`S` speichert, `Esc` schließt.
|
||
|
||
Autostart ist kein Feld der Datei, sondern ein Systemzustand — er wird deshalb
|
||
sofort beim Umschalten übernommen, unabhängig vom Speichern.
|
||
|
||
„Klicks durchlassen“ macht das Widget für Mausereignisse transparent — es liegt
|
||
dann über der Arbeit, ohne sie zu behindern. Zurückschalten geht über das
|
||
Tray-Menü.
|
||
|
||
## Was angezeigt wird
|
||
|
||
**Laufende Sitzung** — Auslastung des aktuellen 5-Stunden-Fensters, dazu
|
||
verbrauchte Tokens und Tempo.
|
||
|
||
**Wochenkontingent** — das übergeordnete Limit über alle Modelle, mit exaktem
|
||
Reset-Zeitpunkt.
|
||
|
||
**Nutzungsguthaben** — der Budget-Zustand jenseits des Plan-Kontingents
|
||
(verbraucht von Monatslimit). Erscheint nur, wenn der Server ihn meldet.
|
||
|
||
Darunter die eigentliche Kernaussage: *wie lange das Kontingent bei diesem
|
||
Tempo noch reicht* — gerechnet in **aktiver Arbeitszeit**, nicht in
|
||
Kalenderzeit. Eine Hochrechnung der Burn-Rate auf fünf Kalendertage wäre
|
||
Unsinn, weil niemand durchgehend arbeitet.
|
||
|
||
## Woher die Werte kommen
|
||
|
||
Standardmäßig fragt das Dashboard denselben Endpunkt ab, den auch `/usage`
|
||
nutzt (`GET /api/oauth/usage` bei `api.anthropic.com`). Damit sind die
|
||
Prozentwerte, Schweregrade und Reset-Zeitpunkte **exakt** — sekundengenau und
|
||
ohne Schätzung.
|
||
|
||
Das Zugriffstoken wird aus `~/.claude/.credentials.json` gelesen, nie
|
||
gespeichert, nie protokolliert und nur an diesen Host gesendet. Es gibt bewusst
|
||
keinen eigenen Refresh-Flow: Läuft das Token ab, pausiert die Abfrage, bis
|
||
Claude Code es erneuert hat. Nach drei Fehlversuchen schaltet sie sich für die
|
||
Sitzung ab.
|
||
|
||
Abschalten über `config.json`:
|
||
|
||
```json
|
||
{ "oauth": { "enabled": false } }
|
||
```
|
||
|
||
**Wichtig:** Der Endpunkt ist nicht dokumentiert und kann durch ein Update
|
||
brechen. Deshalb rechnet das Dashboard *immer* auch lokal weiter — fällt die
|
||
Abfrage aus, läuft es ohne Unterbrechung auf den eigenen Zahlen weiter, nur
|
||
eben mit Näherungswerten. Die Anzeige sagt jederzeit, welcher Fall vorliegt:
|
||
|
||
| Anzeige | Bedeutung |
|
||
|---|---|
|
||
| **exakt (Server)** | Wert vom Server, entspricht `/usage` — nur mit Stufe 2 |
|
||
| **eigener Wert** | `limits` aus `config.json` |
|
||
| **kalibriert** | aus mindestens 5 eigenen abgeschlossenen Fenstern abgeleitet |
|
||
| **geschätzt** | noch zu wenige Messungen, grober Anhaltspunkt |
|
||
|
||
Solange die Serverabfrage läuft, kalibriert sich das Dashboard **selbst**: Der
|
||
Server nennt den exakten Anteil, lokal ist der gewichtete Verbrauch im selben
|
||
Fenster bekannt — daraus folgt die Bezugsgröße unmittelbar. Auch das
|
||
Wochenfenster wird aus dem gemeldeten Reset-Zeitpunkt abgeleitet, nicht
|
||
geraten.
|
||
|
||
Die folgenden Abschnitte betreffen nur den Fall, dass die Abfrage **nicht**
|
||
verfügbar ist.
|
||
|
||
### Kalibrieren (Rückfallebene)
|
||
|
||
Ohne Serverabfrage nimmt das Dashboard das höchste je beobachtete
|
||
Fenstervolumen als untere Schranke des Limits. Das ist grob. Besser: den
|
||
Prozentwert in **Einstellungen ▸ Nutzung** ablesen und unmittelbar danach:
|
||
|
||
```powershell
|
||
npm run calibrate -- --week 14 # nur rechnen
|
||
npm run calibrate -- --week 14 --write # in config.json übernehmen
|
||
npm run calibrate -- --block 37 --write # 5-Stunden-Fenster
|
||
```
|
||
|
||
Das Werkzeug teilt den aktuellen Verbrauch durch den angezeigten Anteil und
|
||
erhält so die Bezugsgröße exakt. Danach das Dashboard neu starten.
|
||
|
||
Steht in der Nutzungsanzeige ein fester Reset-Zeitpunkt („Zurücksetzung Mo.,
|
||
21:59“), gehört er in `config.json` — sonst passt das Fenster nicht zum
|
||
kalibrierten Wert:
|
||
|
||
```json
|
||
{ "weekResetWeekday": 1, "weekResetHour": 21, "weekResetMinute": 59 }
|
||
```
|
||
|
||
(0 = Sonntag, 1 = Montag …) Ohne diese Angabe rechnet das Dashboard mit einem
|
||
rollierenden 7-Tage-Fenster und zeigt bewusst keinen Countdown, weil ein
|
||
rollierendes Fenster keinen Reset-Zeitpunkt hat.
|
||
|
||
### Gewichtung
|
||
|
||
Tokens zählen nicht gleich: Ausgabe wiegt stärker als ein Cache-Treffer, Opus
|
||
stärker als Sonnet oder Haiku. Die Faktoren stehen in `config.json`.
|
||
|
||
Weichen zwei Kalibrierungen mit **unterschiedlichem Modellmix** deutlich
|
||
voneinander ab, stimmen diese Gewichte nicht — dann dort nachziehen, statt das
|
||
Limit hin- und herzuschieben. Ein einzelner Kalibrierpunkt legt nur den
|
||
Maßstab fest, nicht die Gewichte.
|
||
|
||
## Aufbau
|
||
|
||
```
|
||
src/main/index.js Fenster, Tray, IPC, Autostart
|
||
src/main/collector.js Watch-Schleife, Zustandsaufbau
|
||
src/main/jsonl.js inkrementeller Reader, Parser, Dedup
|
||
src/main/blocks.js 5h-Blöcke, Wochenfenster, Burn-Rate
|
||
src/main/limits.js Plan-Erkennung, Kalibrierung, Gewichtung
|
||
src/main/oauth-usage.js Serverabfrage, gekapselt und ausfallsicher
|
||
src/main/calibrate.js Kalibrierung gegen die echte Anzeige
|
||
src/main/store.js state.json, config.json
|
||
src/main/paths.js Speicherorte für Konfiguration und Zustand
|
||
src/preload.js contextBridge fürs Widget
|
||
src/settings-preload.js contextBridge für den Einstellungsdialog
|
||
src/renderer/ Widget-Oberfläche
|
||
src/settings/ Einstellungsdialog
|
||
```
|
||
|
||
Alle Dateizugriffe und Rechnungen passieren im Main-Prozess; der Renderer
|
||
bekommt fertige Zahlen und lässt nur den Countdown lokal weiterlaufen.
|
||
|
||
Zwei Details, die nicht offensichtlich sind:
|
||
|
||
- **Datei-Offsets werden nicht persistiert.** Innerhalb einer Sitzung sorgen sie
|
||
dafür, dass nur das Delta gelesen wird. Über einen Neustart hinweg wären sie
|
||
schädlich, weil der Aggregator leer startet und die Historie sonst
|
||
übersprungen würde. Ein Vollscan über 15 MB kostet rund 70 ms.
|
||
- **Dedup ist nicht optional.** Claude Code schreibt dieselbe Nachricht bei
|
||
Retries und beim Kompaktieren mehrfach ins Transkript; ohne Dedup über
|
||
`message.id` wären alle Zahlen zu hoch.
|
||
|
||
## Release bauen
|
||
|
||
```powershell
|
||
npm run dist # Installer + portable Fassung nach release/
|
||
npm run pack # nur entpackt nach release/win-unpacked (schneller Test)
|
||
```
|
||
|
||
Ergebnis in `release/`:
|
||
|
||
| Datei | Zweck |
|
||
|---|---|
|
||
| `Claude Live Dashboard-1.0.0-x64.exe` | NSIS-Installer, ~97 MB |
|
||
| `Claude Live Dashboard-1.0.0-portable.exe` | läuft ohne Installation |
|
||
|
||
Der Installer läuft **ohne Administratorrechte** (`perMachine: false`),
|
||
installiert also ins Benutzerprofil. Zielverzeichnis ist wählbar, Desktop- und
|
||
Startmenü-Verknüpfung werden angelegt. Bei der Deinstallation bleiben
|
||
Konfiguration und Kalibrierung erhalten (`deleteAppDataOnUninstall: false`).
|
||
|
||
**Nicht signiert.** Ohne Code-Signing-Zertifikat zeigt Windows beim ersten
|
||
Start einen SmartScreen-Hinweis („Der Computer wurde durch Windows geschützt“)
|
||
— über *Weitere Informationen ▸ Trotzdem ausführen* zu bestätigen. Für eine
|
||
Weitergabe an andere wäre ein Zertifikat nötig; für den Eigenbedarf ist es
|
||
verzichtbar.
|
||
|
||
### Konfiguration und Zustand
|
||
|
||
Beides liegt im Benutzerprofil, nicht im Programmverzeichnis — dort wäre es
|
||
nach der Installation im asar-Archiv und schreibgeschützt:
|
||
|
||
```
|
||
%APPDATA%\Claude Live Dashboard\config.json
|
||
%APPDATA%\Claude Live Dashboard\state.json
|
||
```
|
||
|
||
Beim ersten Start wird `config.json` aus der mitgelieferten Vorlage angelegt.
|
||
Erreichbar über das Tray-Menü (*Konfiguration öffnen* / *Datenordner öffnen*).
|
||
|
||
> Die mitgelieferte Vorlage enthält unter `limits` einen auf **diesem** System
|
||
> kalibrierten Wert als Rückfallebene. Für eine Weitergabe an andere sollte er
|
||
> entfernt werden — bei aktiver Serverabfrage wird er ohnehin nicht benutzt.
|
||
|
||
## Gegenprobe
|
||
|
||
```powershell
|
||
npm run dump # Modell-Summen und alle 5h-Blöcke auf der Konsole
|
||
npx ccusage blocks # unabhängige Referenz für Blockgrenzen und Summen
|
||
```
|
||
|
||
`npm run dump` gibt außerdem die Dauer des zweiten Polls aus — ohne neue Daten
|
||
muss er 0 Bytes lesen und im einstelligen Millisekundenbereich liegen.
|