DEV Community

E Daugherty LLC
E Daugherty LLC

Posted on

How a Menu Bar App Reconstructs Codex and Claude Code Usage Limits

If you have typed /status in Codex, or /usage in Claude Code, and then opened Settings → Usage to double-check, you already know the awkward part. The remaining allowance is not one number. It is at least two windows, they do not always reset together, and official docs point you at more than one place to read them.

A macOS menu bar meter is a small UI on top of that problem. The interesting work is reconstructing a trustworthy reading from a session the provider already gave you, then deciding what to show when the reading is incomplete, stale, or about to change. This post is about that plumbing. I'm citing official provider docs for how the limits work, and the public docs of CodexBar, Peter Steinberger's MIT-licensed macOS 14+ menu bar app, as an open-source reference for how a meter fetches them.

The limit is a set of windows, not a tank

OpenAI's help center is explicit about Codex and ChatGPT Work on plans that have both constraints: usage limits "may apply over a five-hour window and a weekly window," and "where both apply, you need allowance remaining in both to continue." A new five-hour window starts with your first message after the previous window ends, and you can fill it "before five hours have passed, even if you still have weekly usage remaining." Check remaining allowance and reset times in Settings → Usage. The percentage is not a message count either. Your allowance "does not correspond to a fixed number of messages or tasks." How far it goes depends on the model, the task, and the settings. (Managing usage with GPT-6 Astra in Work and Codex) In the Codex CLI, /status shows "the chat ID, context usage, and rate limits." (Developer commands) OpenAI's resets guide also describes a /usage command in the Codex CLI for redeeming a banked reset. (How resets work in Codex)

Anthropic describes a similar shape for paid Claude plans: "a session limit that resets every five hours, and weekly limits that reset once every week." The five-hour period starts with your first message and "resets in full five hours later." Weekly limits reset at a fixed time each week assigned to your account. Usage on claude.ai, Claude Code, and Claude Desktop "counts towards the same usage limit." (How do usage and length limits work?) In Claude Code, /usage shows "session cost, plan usage limits, and activity stats." (Commands)

The windows are not universal. OpenAI currently says Pro 100, Pro 200, and Pro 500 have no five-hour usage limit in Work and Codex. Anthropic says verified Ultra accounts don't have a five-hour limit, and some plans also have a separate weekly limit for Fable. (Astra usage, Claude Code on Pro, Max, or Ultra) A meter that assumes every account has a five-hour bar will invent a window the provider does not report.

Reset times can also move. OpenAI documents banked, automatic, and purchased resets that restore covered allowances and can change the next refresh time without changing the billing date. On plans with both limits, "the same usage counts against the 5-hour and weekly allowances, but those periods can end at different times." Its example is a weekly period ending at noon while a five-hour period continues until 3 p.m., leaving you with a full weekly window and almost no session window. (How resets work in Codex) The honest display is "this window, this percentage, this reset time," not a single "you are fine until Friday."

The shape changes over time, too. As of mid-November 2026, OpenAI's help center says that starting in December, Plus, Pro, and Business usage will be shared across ChatGPT and Codex, measured in tokens, with remaining usage and reset times in Settings → Usage. Instant chat will not draw from that usage. (Understanding ChatGPT and Codex usage limits) A meter has to read what the provider reports now, not a hardcoded plan table. Context-window length is also a different kind of limit from usage: hitting a session cap means waiting or changing plan, while hitting a length limit means the current conversation is too large. Those should not be the same bar.

The hard part is the data source

None of that official data arrives as a single public "menu bar API." CodexBar's authoring guide describes the practical response: each provider is a descriptor plus a pipeline of fetch strategies (CLI, OAuth, API token, browser cookies, a local probe, a web dashboard), tried in priority order, with fallback when a strategy is unavailable. (Provider authoring guide) As of November 12, 2026, its provider overview says it registers 113 provider IDs, in part because one company can expose more than one surface with a different auth source and quota shape. (providers.md)

The data flow is straightforward: a background refresh runs provider probes, writes a snapshot into a store, and the menu, icon, and widgets read from that store. (Architecture) The interesting policy is how each probe gets a session without asking for a password. CodexBar's README puts it as reusing existing provider sessions (OAuth, device flow, API keys, browser cookies, local files) so "no passwords are stored."

For Codex, the documented Auto order is a personal access token if one is available, then the OAuth API using credentials already on disk at ~/.codex/auth.json (or $CODEX_HOME/auth.json), then a local CLI RPC server started as codex app-server, which exposes account/read and account/rateLimits/read. The app maps primary_window and secondary_window onto the session and weekly lanes. An optional OpenAI web dashboard path is off by default and is not an Auto fallback. Parsing the rendered /status panel in a Codex TUI is a manual diagnostic only, because a bare codex TUI "can start interactive auth and open browser tabs." Automatic refresh does not take that path. (docs/codex.md)

For Claude, the documented app Auto order is an OAuth usage API, then a Claude CLI probe, then a browser-cookie web API. The OAuth path reuses Claude Code credentials and maps five_hour to the session window and seven_day to the weekly window, only when those fields actually report utilization. The CLI fallback runs claude in a dedicated probe directory, sends /usage, and parses the "Current session" and "Current week" headers. A working Claude Code login or a signed-in browser tab does not, by itself, mean the meter can read that session. Some Education and organization-managed subscriptions return only a notice, with no numeric quota fields. In that case the docs say to report those limits as unavailable and never derive a percentage from spend or token totals. (docs/claude.md)

That last rule is the one I would keep even if everything else changed. If the provider did not give you a quota, you do not get to invent one.

Quota is not the same as cost

A second easy lie is turning a remaining-quota percentage into a dollar amount. CodexBar's docs draw the line directly: "Account quota and estimated API cost have different coverage." Remote quota can include work with no readable local token record, and "CodexBar cannot convert a quota percentage into dollars." Local cost scans, where they exist, read known session logs. The Settings → Usage & Spend view is "a local estimated-cost history page, not a billing receipt and not the menu-bar quota card." Amounts are list-price equivalents unless a source also reports plan-metered spend, and the app "never adds or ranks amounts across currencies." (docs/codex.md, providers.md) Keep those as two separate numbers, and say on screen which one the provider confirmed and which one is a local estimate.

How often to ask, and what to show when the answer is old

Limits move while you work, but polling every few seconds is a bad deal for battery, for rate limits, and for any provider that treats a usage fetch as a real request. CodexBar's refresh loop makes the tradeoff visible. Fresh installs default to Adaptive cadence, a function of recent menu interaction, Low Power Mode, thermal state, and, only in an opt-in "agent-aware" mode, recent local coding activity. Every decision lands between 2 and 30 minutes. Manual refresh is always available. Transient network failures keep the last successful snapshot and its original measurement time; authentication failures and account changes still invalidate it. Stale or error states dim the icon instead of pretending the number is fresh. (docs/refresh-loop.md)

Two other documented choices are worth copying. CodexBar does not redeem or modify Codex reset credits; it can list them and optionally warn before they expire, but the provider remains in charge of the allowance. And the permissions it asks for are narrow: optional Full Disk Access only to read Safari cookies or local storage, Keychain access when you import a Chromium session or repair Claude OAuth, and Files & Folders prompts when a launched CLI needs a working directory. It does not request Screen Recording or Accessibility in the background, and it does not store passwords. (README) A stale percentage with a capture time is more honest than a blank icon or a guessed refill.

Where TokenBar fits

We build TokenBar, a macOS 14+ menu bar app at Aura Technologies. It keeps AI usage, credits, costs, and reset windows visible across supported providers, and it is built on CodexBar. The public trust page states that the app's repository history descends from Peter Steinberger's MIT-licensed project and includes later contributor work as well as our changes. TokenBar also includes a Pixel Agents panel, powered by a local installation of Pixel Agents, a separate MIT-licensed project.

The site currently features Claude, Codex, Cursor, Gemini, and Copilot, and exact coverage varies by integration. Basic is $5 a month per Mac. Pro is $15 once, a lifetime license for one Mac. You download the app and choose a plan inside it. Provider subscriptions and API charges stay separate: TokenBar monitors connected tools, and it does not give you extra quota. If you only want limits and reset times in the menu bar, CodexBar is free, open source, and documents a much longer provider list.

What I would tell anyone building a meter

  1. Model the windows the provider reports. Do not assume every plan has a five-hour session bar, and do not collapse session and weekly remaining into one "you are fine" state.
  2. Keep quota and cost apart. A remaining percentage is not an invoice, and a local log scan is not a substitute for missing remote token records.
  3. Reuse a session the user already has. OAuth files, a local CLI, or an opt-in browser session are enough to start. Store no passwords.
  4. Prefer a stale snapshot with a timestamp over a blank, and over a fabricated number. If the provider returned no quota, show the limit as unavailable.

If you have built anything that reads these allowances, I'm curious about a narrower question than "which API is nicest." When the CLI and the website disagree on remaining quota, which one do you treat as source of truth, and how stale do you let a menu bar reading get before you hide it?

Top comments (0)