# Intent: Anzeige der verbleibenden Claude-/Codex-Sitzungslimits im Intent-Board ## Ziel Ein kleines, dauerhaft sichtbares UI-Element im Intent-Board (z. B. in der Kopfzeile neben Titel/Untertitel), das anzeigt, wie viel Prozent des aktuellen Nutzungslimits für Claude Code und für Codex CLI noch übrig sind — für die eine interaktive `drone`-Identität, deren Login/Kontingent von den meisten Board-Rollen gemeinsam genutzt wird (Reviewer/Researcher/ Planner über Claude, Builder/Worker/Agent über Codex; siehe `board-agent.nix`s eigene Kommentare zu diesem geteilten Login-Tradeoff). Zweck: auf einen Blick sehen, ob gerade noch Spielraum für weitere Board-Läufe ist, bevor eine Karte losgeschickt wird. ## Rechercheergebnis (geklärt, 10.09.2026) Live auf blunix nachrecherchiert (interaktive Klärung mit dem Operator, 10.09.2026), nachdem der ursprüngliche Rechercheversuch vom 09.09.2026 (reine `--help`/`doctor`-Prüfung) korrekt feststellte, dass keine der offensichtlichen CLI-Unterprozeduren einen Prozentsatz liefert. Ein tieferer Blick fand für beide Runtimes eine echte, nicht-interaktive Quelle: **Codex:** `codex app-server` (dokumentiertes, wenn auch als „[experimental]" markiertes CLI-Subcommand) beantwortet über sein Stdio-JSON-RPC-Protokoll die Methode `account/rateLimits/read` nach einem `initialize`-Handshake, ohne dass eine interaktive Sitzung nötig ist — live getestet, Antwortzeit deutlich unter einer Sekunde. Die Antwort enthält `rateLimits.primary.usedPercent` (5-Stunden-Fenster, `windowDurationMins: 300`) und `rateLimits.secondary.usedPercent` (Wochenfenster, `windowDurationMins: 10080`), je mit `resetsAt` (Unix-Timestamp). Eine bereits laufende `codex app-server`-Instanz ist dafür nicht nötig; ein kurzlebiger Kindprozess pro Abfrage reicht. Einschränkung: `codex app-server` schreibt beim Start in mehrere Dateien im eigenen `CODEX_HOME` (u. a. `logs_2.sqlite`, `goals_1.sqlite`, `state_5.sqlite`, `models_cache.json`, Plugin-/Skill-Cache) — kein enger, vorhersagbarer Satz, sondern praktisch der gesamte Home-Baumstand. Da `board-agent-trigger.service` mit `ProtectHome = "read-only"` läuft, ist ein direkter Aufruf gegen das echte `/home/drone/.codex` nicht schreibfähig. Entscheidung: ein eigenes, dauerhaftes, beschreibbares Probe-`CODEX_HOME` unterhalb des Board-Agent-State-Verzeichnisses anlegen (kein neuer `ProtectHome`-Downgrade), dessen `auth.json` vor jeder Anfrage frisch aus `/home/drone/.codex/auth.json` kopiert wird — nicht nur einmalig beim Servicestart wie beim bestehenden `prepareCodexHome`-Muster für die isolierte Builder-Identität, weil dieser Dienst dauerhaft läuft (`Restart = "always"`) und ein zwischenzeitlich rotiertes Token sonst erst nach einem Neustart wieder funktionieren würde. Die Kopierkosten (wenige KB) sind gegenüber dem ohnehin unter einer Sekunde liegenden RPC-Aufruf vernachlässigbar, bei einem Frontend-Poll-Intervall von rund 60 Sekunden erst recht. **Claude:** Es gibt kein offizielles CLI-Subcommand analog zu `codex app-server`. `claude auth status --json` liefert Konto-Metadaten (u. a. `subscriptionType`), aber keinen Prozentsatz. Ein Blick in die Strings des installierten `claude`-Binaries (`.claude-wrapped`, aktuell Version 2.1.257) zeigt jedoch echte, im Client verdrahtete API-Oberflächen: HTTP-Antwort-Header nach dem Muster `anthropic-ratelimit-unified-5h-utilization` / `anthropic-ratelimit-unified-7d-utilization` (analog zu Codex' primärem/ sekundärem Fenster) sowie den Pfad `/api/oauth/usage`. Live getestet mit dem in `~/.claude/.credentials.json` gespeicherten OAuth-Access-Token (`Authorization: Bearer …`, zusätzlich Header `anthropic-beta: oauth-2025-04-20`, gefunden als Literal-String im selben Binary) gegen `https://api.anthropic.com/api/oauth/usage`: Antwort `200 OK` mit direkt nutzbarem JSON-Body, u. a. `five_hour.utilization` (Prozentzahl, 5-Stunden-Fenster), `seven_day.utilization` (Prozentzahl, Wochenfenster) und je einem `resets_at`-ISO-Zeitstempel — keine Header-Auswertung nötig. Zum Vergleich probeweise auch das offizielle, öffentliche und kostenlose `/v1/messages/count_tokens` aufgerufen: authentifiziert erfolgreich (kein 401), aber im Test mit `404` auf ein veraltetes Modellkürzel gescheitert und selbst korrekt beantwortet nur die Rate-Limit-Header, nicht diesen direkt nutzbaren Body. Entscheidung: `/api/oauth/usage` verwenden, trotz des Risikos eines undokumentierten, privaten Endpunkts — bewusst dieselbe Abwägung wie bei Codex' selbst als „[experimental]" markiertem `app-server`. Der Aufruf braucht keinerlei Schreibzugriff (nur Lesen von `~/.claude/.credentials.json`, das bestehende `ProtectHome = "read-only"` reicht) und `board-agent-trigger` hat schon heute uneingeschränkten ausgehenden Netzwerkzugriff — hier ist also keine Sandbox-Anpassung nötig, anders als bei Codex. Damit ist die ursprünglich blockierende Recherche abgeschlossen und beide Quellen sind bestätigt nicht-interaktiv, ohne TUI-Sitzung abrufbar. ## Umfang - Neuer, ausschließlich lesender API-Endpunkt in `board-agent/trigger.py` (`GET /api/board/usage`): - Codex-Seite: `auth.json` aus `/home/drone/.codex` in ein eigenes, dauerhaftes Probe-`CODEX_HOME` unterhalb des Board-Agent-State- Verzeichnisses kopieren, `codex app-server` als kurzlebigen Kindprozess starten, `initialize` + `account/rateLimits/read` per Stdio-JSON-RPC senden, `rateLimits.primary.usedPercent` und `rateLimits.secondary.usedPercent` auslesen. - Claude-Seite: Access-Token aus `~/.claude/.credentials.json` lesen, `GET https://api.anthropic.com/api/oauth/usage` mit `Authorization: Bearer …` und `anthropic-beta: oauth-2025-04-20` aufrufen, `five_hour.utilization` und `seven_day.utilization` auslesen. - Der Endpunkt gibt ausschließlich die berechneten Prozentwerte (plus optional die `resets_at`-Zeitstempel) zurück — nie Access-Tokens, rohe Limit-/Dollar-Felder oder sonstige Rohdaten an das Frontend durchreichen. - Schlägt eine der beiden Quellen fehl, liefert der Endpunkt für genau diese Seite eine Leerdarstellung statt den ganzen Aufruf fehlschlagen zu lassen — die jeweils andere Quelle bleibt unabhängig nutzbar. - Kleines, unauffälliges UI-Element in `board-agent/board.html` (Kopfzeile oder schmale eigene Leiste), das den Endpunkt periodisch abruft (alle 60 Sekunden) und knapp anzeigt, etwa „Claude: 60 % übrig · Codex: 0 % übrig". Kein neuer Dialog, keine eigene Spalte. - Bei fehlender/nicht auslesbarer Quelle: klare, unaufdringliche Leerdarstellung (z. B. „—") statt eines falschen oder geratenen Werts. ## Explizit ausgeschlossen - Keine historische Verlaufsanzeige/Graph über die Zeit — nur der aktuelle Momentanwert. - Keine Alarmierung/Benachrichtigung bei niedrigem Kontingent (z. B. XMPP-Nachricht) — reine passive Anzeige in diesem Schritt. - Keine Aufschlüsselung pro Rolle/Spalte (Reviewer vs. Builder vs. Researcher) — ein einziger Wert je Anbieter (Claude, Codex) für die eine geteilte Identität. - Keine Änderung an den Board-Spalten/Trigger-Logik — rein additiv. ## Annahmen - Die relevante Zahl bezieht sich auf die geteilte interaktive `drone`-Identität (ein Login, viele Rollen), nicht auf einen hypothetischen Wert pro Rolle/Secret. - Ein grober, klar als Schätzung gekennzeichneter Näherungswert ist besser als gar keine Anzeige, aber nur falls das Rechercheergebnis keine echte Quelle findet — Priorität liegt auf einer echten Zahl, falls verfügbar. ## Erfolgskriterien - Das Board zeigt einen aktuellen, unaufdringlichen Prozentwert für Claude und für Codex (oder eine klare Leerdarstellung, falls technisch nicht möglich). - Keine Secrets/Tokens/Rohdaten verlassen den Server-Endpunkt. - Die Anzeige aktualisiert sich automatisch, ohne dass die Seite neu geladen werden muss.