#!/usr/bin/env python3 """Sonde de l'endpoint /usage Claude pour valider le parser de Monitorink. Lit l'access token depuis un fichier .credentials.json (login Claude isolé) puis appelle /usage. Affiche la structure JSON brute (uniquement des % d'usage, aucun secret) + l'interprétation de Monitorink. Sortie partageable sans risque. Usage (sur le serveur, après le login isolé) : python3 dev/probe_usage.py ~/.monitorink-claude/.credentials.json ou via env : MONITORINK_CLAUDE_CREDS=~/.monitorink-claude/.credentials.json python3 dev/probe_usage.py """ import json import os import sys import urllib.error import urllib.request URL = "https://api.anthropic.com/api/oauth/usage" path = (sys.argv[1] if len(sys.argv) > 1 else "") or os.environ.get("MONITORINK_CLAUDE_CREDS", "") path = path.strip() if not path: sys.exit("Chemin du .credentials.json requis (arg ou MONITORINK_CLAUDE_CREDS)") try: creds = json.load(open(path)) token = creds["claudeAiOauth"]["accessToken"] except (OSError, KeyError, json.JSONDecodeError) as e: sys.exit(f"Lecture credentials impossible: {e}") req = urllib.request.Request(URL, headers={ "Authorization": f"Bearer {token}", "anthropic-beta": "oauth-2025-04-20", "User-Agent": "claude-code/2.1.172", "Content-Type": "application/json", }) try: with urllib.request.urlopen(req, timeout=15) as r: data = json.load(r) print("HTTP", r.status) except urllib.error.HTTPError as e: sys.exit(f"HTTP {e.code}: {e.read().decode()[:300]}") print("=== RÉPONSE BRUTE ===") print(json.dumps(data, indent=2, ensure_ascii=False)) print("\n=== INTERPRÉTATION MONITORINK ===") for key in ("five_hour", "seven_day", "seven_day_opus", "seven_day_sonnet"): w = data.get(key) if isinstance(w, dict): util = w.get("utilization", 0) print(f"{key:18s}: {100 - util:.0f}% restant (util={util}, reset={w.get('resets_at')})") else: print(f"{key:18s}: {w!r}")