Codex Desktop signs in one account at a time. If you hold more than one subscription, switching means signing out, signing in, and finding out only afterwards whether the account you picked had any quota left.
Codex Quota keeps each account's credentials in its own profile, shows every account's remaining quota side by side, and switches the live credential in one click — backing up what was there before it does.
- Every account's quota at a glance. Plan, remaining percentage, reset time and available reset credits, fetched per account in the background so nothing blocks.
- Lives in the menu bar or notification area. The icon carries the headroom you have left, and its panel holds a swipeable card per account with an Activate button on each one.
- One-click switching. Move the live Codex credential to any account, with the previous one backed up automatically.
- Honest state. If something moved
~/.codex/auth.jsonoutside the app, that account reads as drifted rather than pretending to be live. - Token history. Lifetime tokens, daily activity, streaks and longest run, straight from your Codex profile.
- Quota window priming. Start an account's window from a moment you choose with one minimal billed request, instead of waiting for whenever you next happen to use it.
- Automatic sync. One switch keeps usage current in the background and starts a window that never started, so its reset arrives sooner without you thinking about it.
- Full account lifecycle. Add, sign in, sign out, import the live credential, delete stored credentials, remove accounts.
Note
This is a full port of the CodeX-Quota bash CLI into TypeScript. It reads and writes the same files, so the two can be used interchangeably on the same machine.
Closing the window does not quit the app. The icon stays, showing the headroom left on the account in use, or the best account to switch to marked with an arrow when nothing is in use. Clicking it opens a panel you can swipe through, one card per account, and switching from a card is a single click — the same guard applies as in the window, so switching under a running Codex Desktop asks first.
The panel keeps reading quota while it is hidden, which is what keeps the figure beside the icon honest. Right-clicking the icon offers the window, a refresh, the automatic sync switch, a start-at-login switch, and quit. Settings has the same switches plus one to hide the Dock icon entirely.
The Auto switch in the window header, mirrored in the menu bar icon's menu, governs everything the app does on its own. It is on by default, and it does two things.
The first is refreshing. Usage is re-read on a timer so the figure beside the menu bar icon means something when you glance at it, rather than dating from whenever the app last happened to be opened.
The second follows from the first, and matters more. A weekly allowance does not begin when the week begins — it begins with the first billed request. Until something starts it, the usage API reports a reset time that simply slides along with the clock, always the same distance away. Sampling that reset time twice tells the two states apart: a reset that moved along with the clock belongs to a window nobody has started, and one that held still is already counting down towards a fixed moment. That check costs nothing extra, because it reads the samples the refresh already collected.
When an account's window turns out never to have started, the app sends the same single minimal request the Start window button sends. The week then begins now instead of whenever that account is next picked up, and its reset arrives that much sooner — which is the whole point, since an account whose window has not started is an account whose spent allowance is not yet on its way back. It is easy to leave an account sitting in that state for days without noticing.
The safeguards are worth stating plainly, because this spends money quietly:
- It only ever happens with the switch on, and only for an account that has a stored credential to bill.
- It costs one minimal request, at the model and effort shown in Settings.
- It is announced with the same notice as any action you took yourself, and it appears in the panel too.
- One account at a time, and never retried within six hours, so a window that refuses to start cannot become a loop.
- Sampling runs every two minutes only while some window is still undecided or waiting; once every window is known to be counting it drops to every ten.
Turn the switch off and the app reads nothing and spends nothing unless you ask it to.
Every command has a counterpart in the interface, with two exceptions worth knowing before you switch.
| CLI command | Where it went |
|---|---|
status, list |
The account rows, with meter, plan, reset time and warnings |
add, remove |
Add account dialog; remove from the account page, behind a confirmation |
login, logout |
Sign in and sign out on the account page |
activate |
Switch Codex Desktop, guarded by the running-app check and the backup |
import-active |
Import the live credential, per account |
delete-auth |
Delete stored credential, for Desktop-switching profiles |
start-5h |
Start the quota window |
use |
Not implemented |
Codex no longer enforces a rolling 5-hour limit, so only the subscription window is tracked; start-5h keeps its real purpose, priming that window, under a name not tied to a bucket that no longer exists. Running an arbitrary command under a profile home, which use did, has no interface counterpart — keep the CLI around if you need it.
Download the latest DMG from the releases page, open it, and drag Codex Quota to Applications.
The build is signed ad-hoc rather than with a Developer ID, so a downloaded copy arrives quarantined and Gatekeeper will refuse it until you either right-click → Open once, or clear the flag:
xattr -dr com.apple.quarantine "/Applications/Codex Quota.app"Important
Apple silicon only, and there is no auto-update — download a newer DMG to upgrade.
Download the latest NSIS installer (CodexQuota-*-win-x64.exe) from the releases page and run it. Closing the window leaves the app in the notification area; quit from the tray icon.
The installer is unsigned. Windows may show a SmartScreen warning on first launch — choose More info and Run anyway if you trust the build you downloaded. There is no auto-update; download a newer installer to upgrade.
On Windows the live credential is still %USERPROFILE%\.codex\auth.json. The file inherits the directory's ACLs; the app does not set POSIX 600 permissions.
- macOS on Apple silicon, or Windows 10/11 (x64).
- Codex Desktop or the ChatGPT app, for the credential this app switches. Codex now ships inside the ChatGPT app rather than as its own app; either one counts, and the running check looks for both.
- The
codexCLI on yourPATH(includingcodex.exe/codex.cmdon Windows), used for signing in and out and for priming a quota window. Nothing is bundled; the app runs the install you already trust.
Each account gets a profile directory holding its own auth.json. Switching copies that credential into the location Codex Desktop reads, after backing up the credential already there.
~/.codex-quota/
accounts.txt the accounts you have registered
accounts/<name>/ per-account auth.json and profile.json
backups/ the live credential as it was before each switch
active.json which account the live credential belongs to
~/.codex/auth.json the credential Codex Desktop actually reads
Quota comes from the same endpoints Codex itself uses, authenticated with each account's own token: the usage endpoint for the live allowance, and the profile endpoint for token history. Expired access tokens are refreshed on read.
Tip
Codex Desktop caches the credential at startup. After switching, restart it before expecting the new account to be in effect.
Everything has a working default; these are the escape hatches.
| Variable | Purpose |
|---|---|
CODEX_QUOTA_CODEX_BIN |
The codex to run, when the search finds the wrong one or none |
CQ_HTTP_PROXY |
Proxy for API calls; off disables the default http://127.0.0.1:7897 |
CQ_QUOTA_USAGE_URL |
Override the usage endpoint |
CQ_START_5H_MODEL |
Model used to prime a quota window (default gpt-5.4-mini) |
CQ_START_5H_REASONING_EFFORT |
Reasoning effort for that request (default low) |
Settings shows the resolved paths, the proxy, and which codex was found.
Node 22 or newer, and pnpm. Node 20 cannot load undici@8, which the tests need; the packaged app is unaffected because Electron embeds its own Node.
pnpm install
pnpm dev # Electron with hot reload
pnpm dev:web # Renderer only, in a browser, on fixture data
pnpm test
pnpm typecheck
pnpm dist # arm64 .dmg and .zip in release/
pnpm dist:win # x64 NSIS installer in release/pnpm dev:web runs the interface against an in-memory fixture service, so layout and states can be worked on without touching real credentials. The menu bar panel is a second page on the same server, at /panel.html.
src/
main/ Electron main process: files, HTTP, spawning codex, tray and panel
preload/ Context bridge
shared/ Domain model, the service contract, and the shell contract
renderer/ React interface: the window and the menu bar panel
Pushing a v* tag builds on a GitHub-hosted Apple silicon runner and a windows-latest runner, then publishes the DMG, zip, and Windows installer to a release. No secrets are involved: the macOS bundle is signed ad-hoc, the Windows installer is unsigned, and the run's own token creates the release. The Windows job never runs codesign.
gh workflow run Release # rehearse: builds and uploads an artifact, publishes nothing
git tag v0.4.0 && git push origin v0.4.0The macOS job stops before publishing if the runner is not arm64 or if the packed bundle's signature does not verify. Either job stops if the tag disagrees with the version in package.json. The Windows job never runs codesign. Publishing waits until both artifacts exist.

