DEV Community

Cover image for AI quotas in three spoonfuls: a HUD for the KDE panel
Cristián Labra
Cristián Labra

Posted on Edited on Originally published at 3cucharadas.cl AI-assisted

AI quotas in three spoonfuls: a HUD for the KDE panel

I currently use Claude Code, Codex, Gemini (through agy on the command line), and DeepSeek on Arch Linux with KDE Plasma 6. For me, as for many others, the problem has become knowing which one still has quota—especially when a task already carries a lot of context, reviewed files, and an hour of iteration.

That is how I ended up building a viewer, or HUD, for the KDE panel: five indicators showing how much room each agent has left and when its quota should reset. No extra tab, no separate dashboard, and—most importantly—no surprise when the quota runs out while I am wrapping up a task or a git rebase 😱.

First spoonful: the token-week

Each provider invented its own way of measuring how much we can use it.

Claude speaks in windows of hours and days. Codex reports the windows available for the plan. Gemini requires a local estimate of requests. Copilot counts premium requests against a calendar cutoff. DeepSeek, by contrast, speaks in monetary balance.

Five agents, five clocks, and no shared unit.

The industry has achieved something rather peculiar: turning token-hours and token-weeks into real planning units. It is no longer enough to ask how long a task will take. I also have to calculate whether the agent can finish it before leaving me to do things the old-fashioned way :).

On the panel I reduced it to five rings, or donuts. A nearly full one means the agent still has room. A nearly empty one means it is probably time to thank it for its service and try the next one.

Compact AI Quota HUD bar on the KDE Plasma panel, with five circular indicators.

Figure 1 — Compact AI Quota HUD view on the KDE Plasma panel. The five rings summarize the available margin by agent. The coloured arc is what remains free, and the outer white marks count the days until reset. Source: own screenshot with synthetic data.

Hovering over one donut shows that agent in detail: its windows and their reset times.

AI Quota HUD hover panel showing the four Antigravity and Gemini quota windows, each with its free percentage and reset time.

Figure 2 — The hover panel shows the windows of the agent under the cursor without leaving the active task. Antigravity carries two independent weekly quotas on separate clocks: one for Google models and one for third-party ones. The badge says where each figure comes from: OFFICIAL if the provider reports it, LOCAL if it is a local count. Source: own screenshot with synthetic data.

Clicking opens the detailed view, with the five agents on top and the windows of whichever one is selected below.

AI Quota HUD detailed view: a row of five selectors with each agent's free percentage and, below, Claude's four windows with percentage, provenance and reset time.

Figure 3 — The detailed view. On top, the five agents with their tightest margin; below, the windows of whichever one is selected. Each line says how much is left, when it renews, and where the figure comes from. Source: own screenshot with synthetic data.

Figure 4 — The walkthrough from the KDE panel to the detailed view. The recording is from July and shows the earlier design, with four agents and no selector row; figures 1 to 3 show the current state. The values are synthetic and do not represent personal quotas. Source: own screen recording.

Second spoonful: the data decides, not the order

The first version worked well for weeks. Codex returned two windows: a short five-hour one and a weekly one.

My code interpreted them by position:

  1. The first window, or outer ring, was the five-hour one.
  2. The second was the weekly one.

It was simple—until Codex changed the schema.

One day the widget showed 5% available in the supposed “5h” window, but with a reset scheduled six days later. Even for a technology company, five hours lasting almost a week seemed like too much innovation.

The raw response contained a single window:

604800 seconds
Enter fullscreen mode Exit fullscreen mode

That is seven days.

Codex had stopped reporting the short window, but my code still called whatever appeared first “5h.” At the same time, the old weekly window remained frozen in the cache because the “keep the last good value” logic could not distinguish between a failed query and a window that had ceased to exist. 👻

The correction had two parts.

First, each window stopped being identified by its position and began to be identified by its actual duration. A short duration is a session; an extended duration is a weekly window or equivalent.

Second, the monitor now distinguishes between:

  • a query that failed, in which case it temporarily preserves the previous value and marks it as cached;
  • a valid query that no longer contains a window, in which case it removes that window from the current state.

The interface also stopped assuming that every agent has the same structure. If two windows arrive, it draws a double donut. If one arrives, it draws a single ring. The data defines the interface, not the other way around.

The lesson is small but fairly general: if the provider supplies the duration, that is the identity of the data; its position in an array is only a temporary coincidence.

Third spoonful: local, useful, and not very universal

This project is not meant to be a cross-platform application.

I built it for an environment very much like mine:

  • Arch Linux;
  • KDE Plasma 6;
  • systemd --user;
  • Python;
  • Bash;
  • QML;
  • the local sessions and credentials of the tools I already use.

It can probably be adapted to other distributions running Plasma 6. I do not promise that it will work unchanged on GNOME, Plasma 5, Windows, or macOS. Nor did I abstract every possible authentication method. It is a tool for my own desktop that I decided to organize and publish, not an attempt to solve every possible combination of operating systems, providers, and plans.

Inside, the path is short:

                 systemd --user timer
                          │
                     every five minutes
                          ▼
 helpers/*.sh ──► Python monitor ──► status.json
                                           │
                            ┌──────────────┴──────────────┐
                            ▼                             ▼
                    QML widget                      MCP server
              panel · tooltip · popup       checks before delegation
Enter fullscreen mode Exit fullscreen mode

The helpers are the only component that touches credentials. They return sanitized JSON, without authentication tokens or conversation content.

The Python monitor queries, validates, and merges the information. If it encounters a timeout, an expired credential, or a 429 error, it preserves the last known value and marks it as cached.

The systemd timer runs the update every five minutes. The widget does not query providers directly; it only reads a local file with 0600 permissions. That way I avoid triggering a rate limit by checking the rate limit too often, which would be an especially elegant way of closing the loop. 🫠

The same status.json can be read by an MCP server. This lets an agent ask which provider still has quota before delegating a task. The desktop bar and the orchestrator receive exactly the same state.

Closing

The repository is published under the MIT license. It is designed for KDE Plasma 6, does not require sudo, and installs into the user's local paths:

git clone https://github.com/tatanlabra/ai-quota-kde.git
cd ai-quota-kde
scripts/install-user.sh
ai-quota-monitor doctor
Enter fullscreen mode Exit fullscreen mode

View the repository on GitHub

It does not create more quota, negotiate better plans, or eliminate the token-week. It only prevents me from discovering halfway through a task that the chosen agent has gone off in search of additional quota 🤑.

It is a small spoonful of sovereignty over my own workflow: knowing how much remains, when it resets, and who should get the next handoff.

Update, 8 September 2026

The HUD changed enough that the July screenshots no longer represented it.
Figures 1 to 3 above show the current state; the recording in figure 4 is still
from July and is kept because the walkthrough —panel, hover panel, detailed
view— has not changed, even though the design has.

What is different:

  • Five agents instead of four. Copilot was added; it counts premium requests against a calendar cutoff. The post said "four" in seven places and has been corrected.
  • A different hover panel. It used to squeeze all five agents into one cramped list. It now shows the detail of the agent under the cursor, with a badge per line saying whether the figure is reported by the provider (OFFICIAL) or counted locally (LOCAL).
  • A different click view. The five agents moved into a row of selectors showing their tightest margin, with the windows of the selected one below. Previously it was five simultaneous columns that did not fit.
  • Slightly thicker strokes and larger logos. The quota arc went from 0.055 to 0.060 of the diameter and the logos grew by 3 %, measured at runtime. The central aperture was recovered by tightening the gap between rings, because widening the stroke was shrinking it.
  • The interface is translated. Source strings moved to English and Spanish lives in a gettext catalogue, so the widget speaks the language of the desktop.

And two things that surfaced precisely while preparing these screenshots, which
matter more than the screenshots themselves:

  • Dates rendered in English on a Spanish desktop. Qt.formatDate with a hand-written format uses the C locale, not the system one: with everything else already translated, it still said "Sat 12 Sep" where "sáb 12 sept" belonged. Measured with QLocale("es_CL") on the same date.
  • Four labels were written in Spanish by the collector and reached the screen without passing through the catalogue, so on an English desktop they read in Spanish among translated strings.

The screenshots are generated by a script in the repository, not by hand, and
that is where the three new figures come from:

scripts/capture_previews.sh build/previews en 3
Enter fullscreen mode Exit fullscreen mode

It renders the three views offscreen, with the same component the tests verify,
at whatever scale is asked for —3× for these. The data comes from
ai-quota-monitor sample, which writes a synthetic report into a temporary
directory: the real cache is neither read nor touched, and every line of the
render is labelled as synthetic. That is why the figures do not show my quotas,
and why they can be regenerated identically.

xkcd 303, Compiling: two programmers play while waiting for compilation to finish.

Figure 5Compiling, xkcd no. 303, by Randall Munroe. The old excuse was that the code was compiling; now I can say the quota resets next week. Licensed under CC BY-NC 2.5.

Top comments (0)