Je suis en train de construire Tokamak, une app de barre de menu pour macOS qui surveille votre quota Claude Max. Il y a quelques semaines, Anthropic a publié ça dans ses Terms of Service :
“You may not use OAuth or similar authorization mechanisms to allow third-party applications to access Claude on behalf of users.”
Et moi, qui lis le quota Claude Max en utilisant les cookies du navigateur pour appeler un endpoint non documenté, je suis resté à fixer l’écran en pensant : “Et maintenant quoi ?”
Comment ça marche aujourd’hui (le bricolage qui fonctionne)
Tokamak a besoin de connaître votre pourcentage de quota. Ce 42% que vous voyez sur claude.ai quand vous l’avez bien sollicité. Le problème, c’est qu’Anthropic n’a pas d’API publique de quota. Il n’existe pas de GET /api/quota documenté avec une API key.
Ce qui existe, c’est un endpoint interne qu’utilise le site claude.ai lui-même :
GET /api/organizations/{org_id}/usage
Il renvoie quelque chose comme ça :
| |
Pour appeler cet endpoint, vous avez besoin des cookies de session d’un utilisateur connecté. Tokamak résout ça avec un WKWebView caché : l’utilisateur se connecte sur claude.ai dans l’app, les cookies restent dans la WebView, et l’app les utilise pour faire du polling toutes les 30 secondes.
Ça marche. Ça marche depuis des mois. Mais c’est un bricolage élégant, pas une solution robuste. Nous utilisons une API interne qu’Anthropic peut modifier, casser ou bloquer sans préavis.
Le limbe juridique
L’interdiction d’OAuth est claire. Mais est-ce que ça s’applique aux cookies ? Techniquement, nous n’utilisons ni OAuth ni des “mécanismes d’autorisation similaires”. L’utilisateur se connecte directement sur claude.ai dans une WebView standard. C’est comme ouvrir Safari dans l’app.
Mais “similar authorization mechanisms” est une phrase suffisamment ambiguë pour qu’un avocat d’Anthropic l’interprète comme bon lui semble. Aujourd’hui, nous sommes dans un limbe juridique : ce n’est pas explicitement interdit, mais pas explicitement autorisé non plus.
Et si un jour Anthropic décide que les cookies tiers, ça ne lui plaît pas non plus, nous nous retrouvons sans données de quota. Comme ça, du jour au lendemain.
Le plan B : estimer sans API
C’est là que ça devient intéressant. La question est : pouvons-nous estimer votre pourcentage de quota en utilisant uniquement des données locales ?
Avant de répondre, vous devez comprendre comment fonctionne le quota Claude Max. Ce n’est pas un simple compteur de tokens.
Le quota, c’est du coût équivalent, pas des tokens
Anthropic ne compte pas les tokens comme des cacahouètes dans un bol. Il compte le coût équivalent aux prix de l’API. Chaque token a un “prix” différent selon son type et son modèle :
| Type de token | Poids relatif |
|---|---|
| Output (réponse) | 5x plus qu’input |
| Input (votre message) | 1x (référence) |
| Cache read | 0.1x (presque gratuit) |
| Opus | 1.67x plus que Sonnet |
En clair : un message court à Opus où Claude réfléchit beaucoup et écrit une longue réponse consomme bien plus de quota qu’un long message de votre part à Haiku avec une réponse courte.
C’est comme la facture d’électricité. Vous ne payez pas pour les “heures branchées”. Vous payez en kWh, et le four consomme 10x plus que l’ampoule des toilettes.
La fenêtre de 5 heures
Le quota ne s’accumule pas indéfiniment. Il fonctionne comme une fenêtre glissante de 5 heures. Chaque token que vous envoyez “expire” exactement 5 heures plus tard. Si à 10h00 vous avez brûlé 30% de quota avec une session intensive, à 15h00 ces 30% se libèrent.
Imaginez un seau d’eau avec un trou. L’eau que vous versez (vos messages) s’évacue par le bas 5 heures plus tard. Le niveau d’eau, c’est votre utilisation.
Les trois composants
Bon, on sait que le quota c’est du coût équivalent et que ça bouge par fenêtres de 5 heures. Peut-on répliquer ça localement ?
La réponse honnête : pas avec une précision chirurgicale, mais avec une précision utile. On ne va pas tomber pile sur 73%. Mais on va savoir que vous êtes “en zone orange, attention”. Et il se trouve que c’est exactement ce qu’il vous faut.
Le système a trois pièces, chacune avec un rôle clair :
1. L’Estimateur (M1) : le comptable
C’est celui qui fait les comptes. Il lit les fichiers locaux de ~/.claude/ (qui contiennent tous les tokens que vous avez envoyés et reçus, avec timestamps et modèle), additionne le coût équivalent des 5 dernières heures, et divise par le “budget total” du tier.
estimation = coût_fenêtre_5h / budget_tier * 100
C’est comme tenir les comptes de votre consommation électrique du mois : vous connaissez les kWh du four, du frigo, de l’ordinateur. Vous additionnez, divisez par votre tarif, et vous avez une estimation de la facture.
Le problème : on ne connaît pas le budget total exact. Anthropic ne le publie pas. Donc on doit le calibrer. C’est là qu’intervient le deuxième composant.
2. Le Calibrateur (A3) : celui qui apprend en observant
C’est le plus élégant. Il s’appelle Decay Estimator et fonctionne comme ça :
Quand vous arrêtez de travailler (vous allez manger, en réunion, dormir), les tokens que vous avez envoyés il y a 5 heures commencent à expirer. Le quota baisse tout seul. Et comme nous savons exactement quels tokens on a envoyés et quand (ils sont dans les JSONL locaux), on peut observer de combien baisse le quota quand ces tokens précis expirent.
C’est comme le seau d’eau de l’exemple : si vous versez un litre d’eau rouge et un autre d’eau bleue, et que vous voyez que quand l’eau rouge sort le niveau baisse de 3 marques et quand la bleue sort il baisse d'1 marque, maintenant vous savez que l’eau rouge pèse 3x plus que la bleue. Sans que personne vous le dise. Juste en observant.
Attention : ça se passe naturellement. Ça ne consomme pas de quota. Pas besoin d’expériences. Chaque fois que vous vous levez pour un café, le calibrateur apprend les poids réels de chaque type de token.
3. Le Classificateur (A5) : celui qui traduit les chiffres en décisions
Il y a ici une intuition contre-intuitive. Le premier réflexe, c’est d’essayer d’estimer le pourcentage exact : “vous êtes à 73%”. Mais il se trouve que c’est mathématiquement très difficile de le faire avec précision. L’API renvoie des entiers de 0 à 100, il y a des facteurs cachés qu’on ne peut pas mesurer, et l’activité depuis d’autres appareils (claude.ai web, mobile) nous est invisible.
Mais avez-vous besoin de savoir si vous êtes à 73% ou 77% ? Non. Vous devez savoir dans quelle zone vous êtes :
| Zone | Plage | Signification |
|---|---|---|
| Verte | 0-60% | Tranquille, foncez |
| Jaune | 60-80% | Modérez, surtout avec Opus |
| Orange | 80-95% | Attention, vous approchez de la limite |
| Rouge | 95-100% | Arrêtez ou passez à Haiku |
Classer en 4 zones plutôt que de régresser 100 valeurs, c’est beaucoup plus facile et beaucoup plus utile. Si le quota réel est 72% et que le classificateur dit “jaune”, il a bon. Si l’estimateur dit “72% +-20%”, la plage 52-92% traverse trois zones et ne vous dit rien.
C’est la différence entre un thermomètre numérique à deux décimales et un thermomètre à mercure à trois couleurs : froid, tiède, fièvre. Pour décider si vous prenez un ibuprofène, celui à trois couleurs vous sert aussi bien, voire mieux.
Le pipeline complet
graph TD
A["~/.claude/*.jsonl<br/>(tokens locaux)"] --> B["Estimateur M1<br/>(comptable)"]
B --> |"coût équivalent<br/>fenêtre 5h"| D["Classificateur A5<br/>(feux tricolores)"]
C["Calibrateur A3<br/>(observe le decay)"] --> |"poids réels<br/>par type de token"| B
E["API de quota<br/>(tant que ça marche)"] --> |"ground truth<br/>pour calibrer"| F["QuotaCalibrationLog<br/>(données appariées)"]
F --> |"calibrage<br/>continu"| C
F --> |"budget<br/>du tier"| B
D --> G["🟢 Verte"]
D --> H["🟡 Jaune"]
D --> I["🟠 Orange"]
D --> J["🔴 Rouge"]
style E stroke-dasharray: 5 5
style F stroke-dasharray: 5 5
Tant que l’API marche, on a la donnée réelle et simultanément on entraîne l’estimateur avec des données appariées : “quand vous aviez ces tokens locaux, l’API disait 42%”. On accumule des milliers de ces paires. Le jour où l’API disparaît, l’estimateur sait déjà combien “pèse” chaque type de token parce qu’il l’a appris en observant.
Comment la précision s’améliore avec le temps
L’astuce de tout le système, c’est le QuotaCalibrationLog : un registre qui se sauvegarde toutes les 30 secondes avec deux choses :
- Ce que dit l’API (la donnée réelle, le ground truth).
- Ce qu’on calcule localement (tokens dans la fenêtre, coût équivalent, modèle utilisé).
Chaque enregistrement est un point de calibrage. Avec 2'880 points par jour (un toutes les 30 secondes pendant les heures d’usage), en deux semaines on a assez de données pour :
- Calibrer le budget du tier : on sait que quand le coût local atteint $X, l’API dit 100%. Maintenant on connaît $X.
- Vérifier les poids : si nos ratios (output 5x input, Opus 1.67x Sonnet) sont faux, les données appariées le révèlent.
- Détecter les changements d’Anthropic : si un jour les résidus de l’estimateur s’envolent, on sait que la formule a changé. On recalibre automatiquement.
Le premier jour, l’estimateur utilise les prix publics d’API comme approximation. Au bout d’une semaine, il a déjà des poids empiriques. Au bout d’un mois, il a un modèle assez ajusté du comportement réel.
Les limitations honnêtes
Ce serait malhonnête de vendre ça comme une solution miracle. Il y a des choses qu’on ne pourra jamais capturer :
- Activité depuis d’autres appareils. Si vous utilisez claude.ai depuis le mobile, ces tokens consomment du quota mais sont invisibles pour Tokamak. L’estimateur sous-estimera.
- Facteurs cachés. Si Anthropic applique des pénalités selon l’heure, la charge serveur, ou la complexité de la tâche, on ne peut pas le mesurer.
- Précision ponctuelle. L’erreur de l’estimateur tourne autour de +-15-25%. Pour un % exact, ce n’est pas suffisant. Pour savoir si vous êtes en vert, jaune, orange ou rouge, si.
C’est pourquoi le classificateur est le composant que voit l’utilisateur, pas l’estimateur directement. On ne vous dit pas “vous êtes à 73%”. On vous dit “vous êtes en zone jaune”. Et ça, on le trouve 85-90% du temps.
“Et pourquoi tu y colles pas un modèle de ML ?”
Si vous êtes arrivé jusque-là, vous pensez probablement : “Mec, pourquoi tu n’entraînes pas un modèle CoreML avec les données de calibrage et basta ?” C’est la question évidente. Et la réponse, c’est que ce serait comme prendre un bazooka pour tuer une mouche qui en plus est derrière une vitre blindée.
Le problème c’est la vitre, pas le bazooka
Imaginez le bocal de bonbons d’un bar. Vous savez qu’il y a des oursons, de la réglisse et des chewing-gums, chacun avec un “prix” différent. Vous voulez savoir quel pourcentage du bocal vous avez mangé. Mais vous ne pouvez regarder le bocal que de l’extérieur et la vitre déforme : vous distinguez seulement s’il est “plein”, “à moitié”, “presque vide” ou “vide”. Vous ne voyez pas les bonbons individuels.
Peu importe que vous mettiez des lunettes à 10'000 francs ou un microscope électronique. La vitre déforme pareil. Plus de puissance optique ne vous donne pas plus d’information si le signal que vous recevez est flou à la base.
C’est exactement ce qui se passe ici :
- Une seule observable : l’API renvoie un entier entre 0 et 100. Un chiffre. C’est toute l’information qu’on reçoit du système réel.
- Quantification brutale : la plupart des observations consécutives (toutes les 30s) ont delta = 0. Quand il y a changement, c’est de 1% ou plus. Pas d’information fine.
- 6+ inconnues : poids d’output, input, cache read, cache write, par modèle, plus le budget total, plus d’éventuels facteurs cachés (GPU time, charge serveur).
Un système à 6 inconnues et 1 équation. Peu importe que vous utilisiez de la régression linéaire, du gradient boosting, un réseau neuronal ou un transformer. C’est un problème sous-déterminé. Il n’y a pas assez d’information dans le signal pour résoudre toutes les inconnues, même avec un milliard de paramètres.
Ce que gagne le ML vs. ce qu’il perd
| Régression linéaire (M1) | CoreML / Réseau neuronal | |
|---|---|---|
| Précision | +-15-25% | +-15-25% (même plafond) |
| Interprétabilité | Totale (vous voyez chaque poids) | Boîte noire |
| Debugging | “Le poids d’output_opus est faux” | “L’accuracy a baissé” |
| Taille bundle | 0 KB | 2-5 MB de framework |
| Recalibrage | Changer un JSON | Re-entraîner + convertir .mlmodel |
| Détection de drift | Comparer les résidus | Comparer… quoi ? |
Si Anthropic change sa formule de quota demain, avec l’estimateur linéaire vous voyez exactement quel résidu s’est envolé et quel poids il faut ajuster. Avec un modèle ML vous voyez que la métrique a baissé et vous devez re-entraîner à l’aveugle avec les nouvelles données, en espérant que ça converge.
L’analogie du thermomètre
Si votre thermomètre à mercure a une résolution d'1°C, acheter un thermomètre numérique de 0.001°C n’améliore pas la mesure si ce que vous mesurez c’est la température d’un four à travers la même paroi de verre épais. Le goulot d’étranglement, c’est la paroi, pas l’instrument.
Ici la “paroi” c’est la quantification entière + les facteurs cachés + l’activité invisible des autres appareils. Aucun modèle, si sophistiqué soit-il, ne peut voir à travers.
Le Phase Detector (les feux tricolores) fonctionne précisément parce qu’il accepte cette limitation : au lieu d’essayer de deviner “73.2%”, il classe en 4 zones. Et ça, c’est robuste avec l’information disponible.
Ce qu’on fait maintenant
Le plus urgent, c’est de commencer à enregistrer des données. Chaque jour sans logging est un jour de calibrage perdu. Donc la priorité c’est :
- Maintenant : implémenter le QuotaCalibrationLog. Sans changement dans l’UI. Juste accumuler des données appariées en silence.
- Dans 2-4 semaines : avec des données accumulées, activer l’estimateur comme fallback automatique quand l’API plante.
- Dans 4+ semaines : activer le calibrateur passif (Decay Estimator) pour apprendre les poids empiriques.
Si demain Anthropic ferme le robinet, l’estimateur sera déjà calibré et les utilisateurs verront des feux tricolores au lieu d’un pourcentage. Ce n’est pas parfait. Mais c’est utile. Et c’est honnête sur ses limitations, ce qui est déjà plus qu’on peut dire de la plupart des tableaux de bord qui traînent.
Parfois le meilleur plan B, c’est celui qu’on commence à construire avant d’en avoir besoin.