I run two AI coding assistants side by side: Claude Code as the primary driver, and Antigravity - CLI and IDE for Gemini models. Both are capped on rolling windows - five hours and a week. To manage that quota better I need a tool that visualizes and alerts me on quota usage. In my cluster I already have Prometheus and Grafana running, and I decided using them would be the best way to achieve it.
Claude Code OpenTelemetry exporter
Claude Code ships its own OpenTelemetry exporter for tokens, cost, and session counts - it’s off by default. Turning it on is just environment variables in ~/.claude/settings.json:
{
"env": {
"CLAUDE_CODE_ENABLE_TELEMETRY": "1",
"OTEL_METRICS_EXPORTER": "otlp",
"OTEL_EXPORTER_OTLP_ENDPOINT": "http://x.x.x.x:30418",
"OTEL_EXPORTER_OTLP_PROTOCOL": "http/protobuf"
}
}That endpoint is a NodePort on an OTel Collector running in the cluster (otel-collector/), which fans metrics out to a Prometheus exporter. This alone gets me cost-per-day, token burn rate, and session counts.
The problem is that this OTel exporter doesn’t export the quota percentage - the most valuable information for me. That number only exists as text, printed when you run /usage interactively.
> claude -p "/usage"
You are currently using your subscription to power your Claude Code usage
Current session: 22% used · resets Jul 31, 7:29pm (Europe/Warsaw)
Current week (all models): 62% used · resets Aug 3, 12:59am (Europe/Warsaw)
What's contributing to your limits usage?
Approximate, based on local sessions on this machine — does not include other devices or claude.ai. Behaviors are independent characteristics, not a breakdown.
Last 24h · 308 requests · 5 sessions
89% of your usage was at >150k context
37% of your usage came from subagent-heavy sessions
Top MCP servers: playwright 25%, antigravity-cli-mcp 11%
Last 7d · 1693 requests · 13 sessions
81% of your usage was at >150k context
60% of your usage came from subagent-heavy sessions
53% of your usage came from sessions active for 8+ hours
Top skills: /graphify 1%
Top subagents: graphify 7%
Top MCP servers: playwright 7%, antigravity-cli-mcp 5%
Above is sample output. I’m interested in the first 3 lines of it.
I decided to grab that information using brute force. I created a CronJob that does exactly that every 5 minutes:
result = subprocess.run(['claude', '-p', '/usage'], capture_output=True, text=True, check=True)After parsing the output with regex, I send the quota usage to the OTel endpoint. The only problem I had to solve was credentials. Initially I provided them as a secret, but they need to be refreshed periodically, so new versions are stored on a PVC.
Antigravity exporter
With Antigravity, the situation is even worse. It doesn’t provide a handy command like claude -p /usage. Instead, I had to execute and parse the TUI… It doesn’t seem like a good idea, but eventually it worked. I wrapped it in a similar CronJob to Claude Code’s, and set the timer to execute every 5 minutes. After all that trouble I ended up with 6 metrics in Prometheus: Claude Code 5h and 7d quota, Gemini 5h and 7d quota, and Claude Code + ChatGPT 5h and 7d quota - provided by Gemini as well.
orest@tuxedo:~$ curl -s 'http://x.x.x.x:9999/api/v1/query?query=claude_pro_session_percentage' | jq
{
"status": "success",
"data": {
"resultType": "vector",
"result": [
{
"metric": {
"__name__": "claude_pro_session_percentage",
"container": "otel-collector",
"endpoint": "metrics",
"exported_job": "claude-quota-exporter",
"instance": "10.42.0.134:8889",
"job": "otel-collector",
"namespace": "otel-collector",
"pod": "otel-collector-6cd94474d8-8d95n",
"service": "otel-collector"
},
"value": [
1785509792.133,
"20"
]
}
]
}
}
In this example, the value field is a 2-value pair: timestamp and percentage used.
Grafana dashboard
Having all that info in Prometheus, I started working on a Grafana dashboard. I wanted to show token burn rate and quota reset time. But the problem was that quota reset is a future date, and sending a future event isn’t possible in Prometheus. But I found a good workaround - Grafana annotations.
Grafana has its own annotation store, separate from Prometheus, and it can render a marker at any timestamp - past or future. The script writes one annotation per panel every run, via Grafana’s REST API:
def upsert_grafana_annotations(session_reset_ts, week_reset_ts):
for tag, panel_id, reset_ts, label_base, fallback_window in panels:
tag_full = f"quota-reset-{tag}"
# delete the stale annotation for this tag before writing a fresh one
existing = _grafana_request('GET', f'/api/annotations?tags={tag_full}&limit=100')
for ann in existing:
_grafana_request('DELETE', f"/api/annotations/{ann['id']}")
future_ms = int(reset_ts * 1000) if reset_ts else int((now + fallback_window) * 1000)
_grafana_request('POST', '/api/annotations', {
'dashboardUID': DASHBOARD_UID,
'panelId': panel_id,
'time': future_ms,
'tags': ['quota-reset', tag_full],
'text': label_base,
})A few things that made this work reliably:
For make it work, I had to setup grafana service account with editor role, its token is passed to the CronJob.
Usage delta
A flat “62% used” doesn’t tell you if that’s fine or alarming - it depends how much of the window has elapsed. 62% used with 90% of the week gone is nothing to worry about; 62% used with 10% of the week gone is a problem. I wanted a single number for that.
I tried different solutions, but finally landed on an idea borrowed from burndown charts: remaining% − time_remaining%. 40% quota left with 80% of the week still to go is 40 − 80 = −40 - you’re behind.
The dashboard
All of it lands on one Grafana dashboard: gauges for current usage, stat panels counting down to the next reset, and the Pace Δ panels, split across the three pools and their five-hour/weekly windows.

Next steps
In the future I would like to use this data to implement orchestrator-worker pattern. Heavy/expensive model will be dispatching work to cheaper models based on the quota left, and then synthesizing the results. Some tasks - like searching the web - can be easly offloaded to Gemini. When getting responses for fairly easy questions, orchestrator can call agents multiple times and get “multi call consensus”. All of this has researched. I would like to to create quota/budget aware orchestration. Adding local GPU to the mix will make it even more interesting.