Questions people ask
- How Subtank reads usage
- No Claude sign-in window
- What a ChatGPT row counts
- The menu-bar number
- Running out before it refills
- Your own order
- Three layouts
- Folding idle accounts
- Switching accounts
- “Claude Code switched to …”
- The marks after a name
- Why reads start
claude - What each service needs
- Jev, and why it has no balance
- Keychain prompts
- Can’t see the icon
- Dashes and dimmed numbers
- Alerts
- The Console
- Hide personal info
- The
subtankcommand - Numbers for other apps
- Links from other apps
- Updates
- “Downloaded from the Internet”
- Uninstalling
- Reporting a problem
How does Subtank read usage?
It depends on how you pay.
- Subscription plans — Claude, ChatGPT · Codex, Cursor and Copilot — are read through the tools already on your Mac: your own Claude Code, OpenAI’s Codex, the Cursor app’s sign-in and the GitHub CLI. Each answers with the numbers it shows you. Subtank never signs in to these services itself, and never renews a sign-in. Cursor keeps its sign-in encrypted, so Subtank decrypts it with Cursor’s own key from your Keychain, after you allow it (Keychain prompts). Kilo Code’s credits come the same way, through the Kilo CLI’s sign-in or Kilo’s device code.
- Services read with a key are read with a key you paste: OpenRouter, the Anthropic and OpenAI APIs, DeepSeek, Moonshot, xAI, Ollama Cloud, Synthetic, MiniMax, NanoGPT, Vercel AI Gateway, Jev (TypeSafe) and, new in 0.0.10, OpenCode Go, Poe, Novita AI and SiliconFlow. The key is kept in your Keychain and sent only to that service’s own API. Some of them report a balance or this month’s spend rather than a limit, and two only confirm that the key works: What each service needs says what each one gives.
Nothing is read until you add an account. After that, each account is read every 5 minutes by default (Settings → General → Refresh every), again when you open the list and its numbers are more than a minute old, and right after one of its busy windows resets. Choose Automatic there and each account is read at its own service’s pace instead: Codex every 2 minutes, Cursor every 3, Claude every 5 minutes, or every 2 while its numbers are moving, most others every 5, and less often while its numbers are not moving. Turn off Read in the background for an account you rarely use, in Settings → Accounts or its menu, and it is read only when you open the list or press refresh (a Claude account also whenever Claude Code’s status line reports).
Why is there no Claude sign-in window?
Because Subtank never signs in to Claude itself. Claude’s numbers come from your own Claude Code: Subtank runs the claude you installed and asks it for its usage — the same numbers Claude Code shows you, with no model request. Anthropic’s terms rule out signing in to claude.ai inside other apps, and Claude Code renews its sign-in with a single-use token: an app that renewed it would sign Claude Code out.
- The account Claude Code uses now needs nothing extra. Sign in to Claude Code as you always do, and Subtank finds it; a small prompt sign () after its name shows which account that is.
- Another Claude account: Add account ( at the foot of the list) → Claude → Sign in with your browser. That runs Claude Code’s own sign-in into a separate profile inside Subtank’s folder. Your browser opens on Claude’s page, and your current Claude Code login stays as it is.
- Claude Code not installed? Subtank needs it to read Claude. Install it, sign in, then choose “Scan this Mac again” from Subtank’s menu.
- Pro, Max and Ultra. On 30 October 2026 Anthropic renamed Max 20× to Ultra and Max 5× to Max, at the same prices, and Subtank uses the new names. Once Anthropic has verified an Ultra account, it has no 5-hour limit: its row shows the week and Fable’s week, and no 5-hour bar, because a limit the plan doesn’t have is not an unknown. Until then it keeps a temporary 5-hour limit, and pointing at the plan’s name says that it goes away once the account is verified. Accounts Subtank already knew take the new names by themselves, and a price you typed stays.
- Saved limit resets. A Claude account can save a limit reset and use it later on claude.ai, under Settings → Usage; Claude Code can’t use one. Claude Code doesn’t tell Subtank whether you have one, so Subtank never counts them. A Claude row at its limit says “If you saved a limit reset, you can use it on claude.ai” with Open Claude usage, which opens that page.
What a ChatGPT row counts
Since OpenAI’s changes of 29 September 2026, a ChatGPT plan has one limit, and Codex is no longer the only thing that spends it. ChatGPT’s Work shares it, apps you signed in to with your ChatGPT account spend it, and so do the tasks a dot starts. The row’s small label still says “Codex”. Point at the row’s name to see what its number covers: “Codex · Work”, with “dot’s tasks” on a plan that has a dot. A row at its limit names them in its message too. The number can move while your Mac is asleep, because a dot works without it.
- Talking to a dot is free. OpenAI does not count conversations with a dot toward the limit. The tasks it starts or manages in Work or Codex count as if you had started them.
- A dot’s own allowance can’t be read. A plan with a dot includes an allowance for its longer work. OpenAI states no size for it and gives Codex no number for it, so Subtank shows none rather than a guess.
- Plan names. The Pro tiers are Pro 100, Pro 200 and Pro 500, as OpenAI and Codex now call them. An account Subtank knew as “Pro 5×” or “Pro 20×” keeps the price it had.
- A Pro 200 row that jumped. A Pro 200 plan that was active in the week to 29 September 2026 kept its earlier, larger allowance until 29 October 2026. After that OpenAI gave it the smaller one, so its row’s used figure jumped up once without any use behind it: the limit got smaller, not your usage bigger. The price stays $200.
- Credits. Credits bought on top of a plan show as a quiet line on the row. They are a count, not dollars. A row at its limit with credits behind it says it is running on credits, and can still be the account to use next.
A row at its limit says why in OpenAI’s own terms: the plan’s limit, a workspace out of credits, or a spend cap. Usage settings on the row opens ChatGPT’s usage page.
What the number in the menu bar means
It is what is left on the account to use next, on that account’s tightest window: the 5-hour window on plans that have one, the week, or a model’s own week such as Fable’s, whichever has the least room. Everything that stands for a whole account says what is left: the menu-bar tank, the account’s own figure in the list (“66% left”), and the tanks and rings of the other layouts. The bars under an account count the other way: they fill with what is used, as Claude Code’s own usage bars do, and the percentage beside each bar is what is used. The caption “used · resets in” sits over the first bars in the list to say so, and the menu bar puts a tiny “LEFT” over its number. Hover over it and the tooltip names the account.
The account to use next is picked from fresh numbers only: one whose numbers are unknown, 15 minutes old with its reads failing, or more than 30 minutes old is never the pick, and neither is one you turned Suggest this account off for. When either leaves out an account with more room, “Use next” says so. Between two accounts of the same service less than 10 points apart, Subtank prefers one that lasts to its reset at the pace you are going, then the one Claude Code is signed in to, then the one whose week refills sooner. The list’s header names the pick, under “Use next”, or under “Keep using” when it is the account Claude Code is already signed in to. When no account has room, the header says “Room again in …” and names the account that refills first.
Settings → Appearance → Menu bar item has five styles:
- Left (the default): a slim gauge and a tiny “LEFT” over the number.
- Service: the service’s name over the number, such as “Claude”.
- Limit: the name of the limit the number comes from, over the number: 5H, WEEK, DAY, a model’s own week such as FABLE, or one of Cursor’s pools, CURSOR or OTHER. A Claude Ultra account, which has no 5-hour limit, says WEEK, or FABLE when Fable’s week is tighter. An account with one limit that counts shows the service’s name instead, as Service does, unless that limit is a week: then it says WEEK.
- Tank: the tank with the number beside it.
- Icon: the tank alone, filled to what is left.
In every style, pointing at the item names the limit and lists every limit as what is left, and VoiceOver says the same. With accounts but no number yet, the item shows —; with no accounts, the empty tank.
Color the number by what’s left, in the same place: the number and the gauge’s fill are green when the tank is full, amber at 40% left and red at 10%, and a blend of the two in between, so half a tank is still greenish. These are the bands the list colours each account’s figure by, so the menu bar and the row never disagree. “LEFT” and the outline keep the menu bar’s own ink, the Icon style colours only the tank’s fill, and a — is never coloured. A new copy starts with it on; a copy updated from 0.0.6 or earlier keeps its one-colour item until you switch it on.
Stay bright on every display, on unless you turn it off. With more than one display, macOS dims the menu bar on the displays you aren’t using, and until 0.0.7 it dimmed Subtank’s tank to about a third of its brightness, as it does any one-colour icon. Subtank now draws the item itself, without the image macOS dims, so it keeps nearly all of its brightness there, more than most items beside it. Off, macOS dims it like the rest. If a macOS update ever stops Subtank from drawing it this way, it goes back to the plain tank by itself.
Running out before it refills
When a limit is about an hour from running out at the pace of the last hour, the account’s row says so in one amber line: “5h limit runs out in about 40 min at this pace”. It is a warning, not a forecast. It shows only then, never days ahead, and it goes when you stop for 20 minutes, when the window refills, or when the limit is reached and the row says so itself. It never shows for a window that would refill first. Point at the line for the pace, in points an hour, and the time it would run out.
The pace comes from the numbers Subtank read in the last hour, kept on your Mac. It needs a few readings over at least 20 minutes and a rise of 2 points, so a slow creep never raises it (the 95% alert covers that), and an account read only when you look seldom has one.
Whether a whole week will last is a planning question, and its answer is in the Console: each limit’s chart says “Caps in about … at this pace” from the whole cycle. Between two close accounts, Subtank still suggests the one that lasts. To hear about it too, switch on Warn about an hour before an account runs out in Settings → Alerts; a new copy has it on.
Your own order
Accounts are listed by service until you arrange them. There are three ways, and each move is saved at once:
- Settings → Accounts. Drag an account by the handle at its left edge, or click the handle for Move to top, Move up, Move down and Move to bottom. With an account selected, Command-↑ and Command-↓ move it one place, and Option-Command-↑ and Option-Command-↓ to either end.
- In the list. Hold Command and drag a row. A plain drag does nothing, so reaching for a button never moves a row, and Escape puts it back.
- A row’s menu (right-click the row) has the same four Move items.
Command-Z undoes a move, in Settings and in the list while it stays open. The order is the same everywhere: the list, the Console and what the subtank command prints. New accounts go at the end, and Sort by service in Settings → Accounts puts the order back. Where an account sits never changes which one Subtank suggests: the pick comes from the numbers alone.
Three layouts for the list
Settings → Appearance → Layout changes the shape of the list, as the theme beside it changes its colours. Every layout shows the same accounts and numbers, and an account in trouble always shows its message and its way out without a click.
- Ledger, the default: the list as it has always been, a row per account with a bar per limit.
- Tank farm: a tank per account, five to a row, filled to what is left like the one in the menu bar. Click a tank for that account’s limits on the placard under the tanks, which opens on the account to use next.
- Gauges: a ring per account in a grid, like Control Center. The ring is what is left; the account to use next gets a wide tile with its limits.
Tanks and rings say what is left, like the menu bar; the limits listed with them count what is used, like the bars in Ledger. An empty tank or ring always means empty. A balance with no limit gets an open “$” tank, or no ring, so it never looks empty, and a number Subtank doesn’t know stays —.
Folding idle accounts
Every account in the list is an open row: its name, its figure and a bar for each limit it has. If your list is taller than your screen, Settings → Appearance → Layout → Fold idle accounts makes an account with nothing used take one line. The switch is off until you turn it on.
With it on, three kinds of account fold: one whose limits are all at 0% or have not started, a prepaid balance with nothing else to say, and a single month’s spend with no limit. A folded row shows the same name and the same figure as before, and nothing is added to it. Point at its name to see what the fold hides. The row opens to its full size by itself the moment one of its limits moves.
An account in trouble never folds, and neither does the one the menu bar speaks for. A row in trouble keeps its message and its way out at full size. When the list is still taller than your screen and such an account is out of sight, the foot of the list says how many need attention, and a click scrolls to the first.
Switching accounts
Subtank can start your next Claude Code or Codex session on the account with room. Click “Use next” in the list’s header, or right-click a Claude or Codex row, and choose:
- Start Claude Code on it. Terminal opens and starts your own
claudein that account’s profile folder, the waysubtank claude --as <nickname>does. Command-Return in the list does it for the account to use next. On a Codex row it is Start Codex on it, which runs your owncodexwith that account’s home folder. - Copy the terminal command, for a terminal that is already open. It is one line with a folder path in it, no secret.
- Switch Cursor’s Claude panel to it. Subtank sets one entry,
CLAUDE_CONFIG_DIRunderclaudeCode.environmentVariables, in Cursor’ssettings.json. The first time, it names the file and the entry and asks; nothing is written until you allow it. New conversations in the panel use that account; one that is already open keeps its own. Switching back to the account Claude Code signs in to by default removes the entry.
The same menu has Tell me when it has room again, Quiet until it refills, Suggest this account, Read in the background, Alerts for this account, Refresh, Show in Console and the Move items (Your own order). Right-click any row for its menu. From the keyboard, press Tab until a row is focused, move between rows with the arrow keys, and press Return: the menu opens under the row’s name. In Tank farm and Gauges, right-click a tank or a tile, or focus it and press Control-Return. A row that can’t switch has the same menu without the switch items. Until 0.0.8 each row had a ⋯ button for this.
Which account, before it starts. Start … on it, subtank claude and subtank codex first print the account, the folder the tool will use and what is left on it. For the account Claude Code signs in to by default, Subtank also checks that ~/.claude is still signed in to that account, comparing only an account id, never a token. If it has changed, the banner says so and waits: Return starts anyway, Control-C stops. A script with no terminal gets an error instead of a question. subtank env claude makes the same check since 0.0.8: when ~/.claude has moved to another account it prints an error and no variable, so a shell is never pointed at the wrong one.
This works for the account Claude Code (or Codex) already uses and for every account added with Add account, because each of those has its own folder, signed in by the tool itself. Nothing reads, copies or renews a token, and a conversation that is running is never moved.
Start every new session there. Settings → Advanced → When you start Claude Code → Start on the account with the most room makes a plain claude in a new terminal do what subtank claude does. It works through one line in your shell profile, an alias that makes claude run subtank claude. Subtank shows you the file and the exact line, adds it only after you confirm, and removes it when you switch the option off. It is off until you choose it. Only new sessions follow it: a conversation that is running is never moved, and no sign-in is copied. Subtank edits the profile for zsh and bash; in another shell it leaves the profile alone and shows the line to add yourself.
Share your Claude Code setup. An account added with Add account starts as a blank Claude Code: no MCP servers, no instructions, none of your skills. Settings → Advanced → Claude Code setup across accounts → Manage… lists what your main setup in ~/.claude has, item by item: each MCP server by name, CLAUDE.md, each skill, agent and command, your plugins and your settings in groups. For each account you choose what reaches it, by dragging items across or ticking them. Linked follows your main setup; Copied is the account’s own copy, which you can update later. Before anything is written, Review changes lists exactly what will be, and Apply does exactly that, after saving what was there. Restore puts an account back as it was, and keeps anything you changed in it since. Sign-ins and history always stay with each account, settings that decide who pays are never shared, and nothing in ~/.claude is written, either by Subtank or by Claude Code in another account. When you add a Claude account with +, Subtank asks whether to bring your setup to it (Settings can change that to “use my last choice” or “don’t”). An MCP server that signs in on its own asks once in each account, through /mcp. New in 0.0.9; the switch from 0.0.4 is gone, and if it was on, Settings offers a review that turns its links into the new kind.
“Claude Code switched to …”
Claude Code keeps one default sign-in, in ~/.claude.json, and it belongs to whichever account claude was last signed in to. Subtank reads your default account through it. So when you sign Claude Code in to a different account, the old row can no longer be read that way. Rather than put the new account’s numbers on the old account’s row, Subtank stops, keeps that row’s last numbers dimmed, and says “Claude Code switched to …” with the account it now finds. It notices the new sign-in within about a minute and offers to add it.
To keep reading both, add the other account with Add account → Claude → Sign in with your browser. It gets a profile folder of its own, which never switches away. The prompt sign () after an account’s name marks the one Claude Code is signed in to right now.
The marks after a name new in 0.0.9
A row can carry small marks after its name. Each one is a choice you made or a fact about the account, never trouble: trouble always gets words and a way to fix it. Point at a mark for what it means for that account.
- The prompt sign (): Claude Code is signed in to this account right now.
- The crossed-out sparkle (): you turned off Suggest this account, and it would otherwise be the account to use next. It shows only then: on an account with less room than the one Subtank suggests, turning it on would change nothing, so the mark stays away. Right-click the account to turn suggesting back on, or use Settings → Accounts.
- The crossed-out bell (): the account is quiet. You chose Quiet until it refills in its menu, and it sends no alerts until the time its tooltip names.
- A refresh arrow with a number ( 2), in a corner in Tank farm and Gauges: a ChatGPT account’s saved resets. In the list they are a line of their own under the bars, and on the day one expires that line says “expires today”.
Why reading Claude starts claude
Claude’s numbers come from Claude Code itself, so each read starts your own claude, asks it for its usage and lets it quit a few seconds later. There is no model request and no prompt, and nothing lands in your history. You may see claude in Activity Monitor for a moment.
- How often. On its own, Subtank reads each Claude account every 5 minutes, or every 2 while its numbers are moving; longer after a failure, and longer still after Anthropic turns a read away. That is as often as it goes, whatever Settings → General → Refresh every says, and the 2-minute pace needs Refresh every under 5 minutes, or Automatic. Opening the list or pressing refresh can read it sooner, never more than once a minute. With Read in the background off, that is the only time it is read, apart from what Claude Code’s status line reports.
- Which
claude. The one you installed, unmodified. Subtank looks in the folders installers use —~/.local/bin,~/.claude/local,/opt/homebrew/bin,/usr/local/bin,~/.npm-global/bin,~/.volta/bin,~/.bun/binand~/bin— and then, once, asks your login shell for itsPATH. An app opened from Finder does not get your shell’sPATH, so this is how it finds aclaudeinstalled with nvm or somewhere else. - A clean start.
claudegets your home folder, aPATH, a locale and nothing else from Subtank’s environment, so a strayANTHROPIC_API_KEYcan never switch it to API billing. It runs from a folder inside Subtank’s own, with no settings files, MCP servers or plugins loaded.
What each service needs
Subtank reads each service through something already on your Mac or a key you paste. What has to be there first:
| Service | What it needs |
|---|---|
| Claude | Claude Code, installed and signed in. More accounts: Add account → Claude, which runs Claude Code’s own browser sign-in. |
| ChatGPT · Codex | The Codex CLI, or the ChatGPT app (Subtank uses the codex inside it), signed in with ChatGPT. A sign-in with an API key has no plan limits to read. |
| Cursor | The Cursor app, signed in. Cursor keeps its sign-in encrypted, so its row waits for you the first time: click Allow access, and macOS asks for your login password before Subtank may use Cursor’s key (Keychain prompts). Only the account Cursor is signed in to can be read. If Cursor needs to renew its sign-in, open it once. |
| GitHub Copilot | The GitHub CLI, signed in: run gh auth login in Terminal, then “Scan this Mac again”. |
| Kilo Code | The Kilo CLI, signed in, or Kilo’s device code from Add account (approved at app.kilo.ai; the token is kept in your Keychain). |
| OpenRouter | A key. A management key, made at openrouter.ai/settings/management-keys, shows your account’s balance and, in the Console, spend by model; set an expiry when you make it. A regular key shows only its own spending and limit. Subtank only reads with either. |
| DeepSeek, Moonshot · Kimi | An API key. |
| Anthropic API | An organization key: in the Claude Console, Settings → API keys → Create key, linked to an admin, with Scope “Organization”; or an Admin key (sk-ant-admin01-…). Individual Console accounts cannot read usage or cost with any key: that is Anthropic’s rule, and an individual account has to become a team organization first (Settings → Organization). |
| OpenAI API | An Admin key (sk-admin-…), from Settings → Organization → Admin keys on platform.openai.com. An ordinary key cannot read usage or cost. |
| xAI | An API key. The row shows only whether the key works: xAI gives API keys no usage or balance to read. |
| Ollama Cloud | An API key from ollama.com. The numbers come from Ollama’s balance API: session and weekly limits with their reset times, or the monthly credits on newer plans, and credits you bought. |
| Synthetic | An API key (syn_…). The row shows your subscription’s limits as Synthetic reports them. |
| MiniMax | A coding plan’s M Plan API key (sk-cp-…). The row shows the 5-hour and weekly counts for each model. |
| NanoGPT | A management token made as “Usage only” (sk-nano-mgmt-…), which can read usage and nothing else. An ordinary NanoGPT key cannot read usage. The row shows the subscription’s daily and weekly limits. |
| Vercel AI Gateway | An AI Gateway API key (vck_…). The row shows the credit balance and what has been used in total. |
| Jev · TypeSafe | A TypeSafe API key (apikey_…). The row shows only whether the key works: see Jev, and why it has no balance. |
| OpenCode Go | An API key from the OpenCode console (oc_sk_…, or an older sk-… key). The row shows the 5-hour, weekly and monthly limits with their resets. OpenCode’s own client reads them from an address its documentation doesn’t list yet, so the row is marked experimental. The answer doesn’t name your plan, so you choose Go, Go Plus or Go Teams, and its price follows. |
| Poe | A Poe API key. The row shows your points balance: plan points and add-on points together. |
| Novita AI | A Novita AI API key. The row shows the account balance. The same key can start paid machines on Novita, so Subtank only ever reads the balance with it. |
| SiliconFlow | A SiliconFlow API key (sk-…). The row shows the account balance. |
| Anything else | Nothing: type the price and the renewal date, and Subtank reminds you before it renews. |
Synthetic, MiniMax, NanoGPT, Vercel AI Gateway, Poe, Novita AI and SiliconFlow were built from each service’s own documentation, and OpenCode Go from OpenCode’s own client. If one of their rows reads wrong for your account, report it with the report from Console → Diagnostics: it carries the shape of the answer, never your key.
Some keys look alike: a plain sk-… key can be DeepSeek’s, Moonshot’s, SiliconFlow’s or an older OpenCode one. For a key like that, Add account asks which service it is for, and nothing is sent until you say.
Jev, and why it has no balance
Add account → Jev · TypeSafe takes a TypeSafe API key. Subtank checks it by asking TypeSafe for its list of models, a request that costs nothing, and the row says the key works. It checks again every 30 minutes, so a key that was revoked shows within the half hour.
The row’s figure is a —, and that is not a fault. TypeSafe’s API has two addresses, one that asks Jev and one that lists models, and neither says what is left or what was spent. The balance is only in TypeSafe’s console, behind your browser’s sign-in, and Subtank reads no service through a website’s cookies. Open console on the row takes you there. The row is in place for the day TypeSafe’s API gives a balance.
Two other routes do give numbers, if you already use Jev through them:
- OpenRouter. With a management key, Console → By model lists what each model cost per day, Jev beside the large models.
- Vercel AI Gateway. Its row shows the gateway’s credit balance, which is what Jev spends there.
Keychain prompts
Subtank reads one other app’s Keychain item, and only after you allow it: Cursor’s. Cursor keeps its sign-in encrypted, with a key it stores in your Keychain as Cursor Safe Storage. A Cursor row that needs the key says Allow access and waits: nothing is read and nothing is sent to Cursor until you click it. macOS then asks for your login password. Always Allow keeps later reads silent; Allow lets this read through, and the row asks again after Subtank restarts. Subtank uses the key to decrypt Cursor’s access token and nothing else, keeps the key in memory only, never stores, logs or sends it, and never changes Cursor’s item. If you click Deny, the row says so and offers Cursor’s own usage page.
Taking it back. Open Keychain Access, search for “Cursor Safe Storage” and open it, choose Access Control, select Subtank in the list (it may be named Subtank Helper), click the minus button and then Save Changes. Subtank never edits that list itself, so removing the account or Reset everything leaves it there. The Cursor row asks again the next time it needs the key.
When Subtank looks around on first launch, it checks only whether Claude Code’s and Codex’s items exist, which raises no prompt; Claude Code, Codex and the GitHub CLI read their own.
Subtank does keep secrets of its own in your Keychain, under the service subtank: Kilo device-code sign-ins and the API keys you paste. Electron, which Subtank is built on, adds one more, named after the app and ending in Safe Storage: the key that encrypts the cookies of in-app sign-in pages.
macOS asks for your password before a different copy of Subtank opens those items — a build made from source, or a copy restored onto a new Mac. Enter it and click Always Allow, and that copy is not asked again. Updates are signed by the same developer, so an update does not ask. If you click Deny, only the account that needs the item stops updating, and Subtank does not ask again until you press refresh.
I can’t see the icon in the menu bar
Press Option Shift Space to open the list from anywhere (Settings → General changes the shortcut), or open Subtank again from Applications or Spotlight: it shows its Settings window instead of doing nothing. Then:
- Behind the notch. On a MacBook with a notch, icons that do not fit beside it are hidden. Quit a few menu-bar apps, or make room with a menu-bar manager.
- A menu-bar manager such as Bartender or Ice may have put Subtank in its hidden section. Move it to the visible one.
- Turned off. On macOS 26 and later, open System Settings → Menu Bar and check that Subtank is on under “Allow in the Menu Bar”. The last step of Subtank’s setup has a button that opens that page.
Why is a number a dash, or dimmed?
A — means the service did not give that number; Subtank never shows a guess as 0. When a read fails, the numbers stay as they were while Subtank tries again — a timeout or a busy server never erases them. Once they are 15 minutes old, the figure is dimmed and its age sits beside it, “66% left · 42m ago”, and the foot of the list says how many accounts are not answering; point at it to see which, and since when. When the sign-in behind an account needs you, the row says Sign in where its figure would be, with the way to fix it right under it.
When Subtank starts, each account shows the last number it had, pulsing, until the new one arrives. A pulsing number is the old one with a read on its way, not a new reading. Only an account with no number to keep shows a spinner. With Reduce motion on, the number is dimmed instead.
Two things look like gaps but aren’t. A 5-hour window you haven’t started yet has no reset time, so its last column is a —; point at its bar and it says “not started”: it starts with your next message. And an API account that reports only this month’s spend shows that spend as its figure, “$0 this month” included, with no bar, since a spend has no limit to measure against. A spend over any other period says “spent”.
A key that expires, such as an OpenRouter key made with an expiry, says so on its row in a quiet line from two weeks before. Once it has expired the line turns amber with Replace key, because the service will refuse it.
The last column counts down to each window’s reset. Click its caption, “resets in”, to show clock times instead (“Mon 19:00”); pointing at a bar shows both. Once a window has reset, it says “refilling…” until the next read, which Subtank makes within about a minute.
Alerts and notifications
Alerts are off until you switch them on, in Settings → Alerts or on the last step of setup. Switching them on is when macOS asks whether Subtank may send notifications; click Allow.
- When they come. Once per limit per reset: when a window passes your threshold (80% unless you change it), at 95%, and at the limit. Optionally, when a limit resets. Never at launch for limits that were already high.
- About an hour before a limit runs out, at the pace of the last hour: once per limit each cycle, never when it would refill first, with the account to use next and a Switch button. A new copy has it on once alerts are on; a copy updated from 0.0.6 or earlier keeps what it had.
- A week about to refill unused, if you switch it on: in the evening before a weekly window refills with half or more of it left, so it does not go to waste.
- Extra usage billed, with alerts on: when included usage is spent and further use is billed, such as Cursor’s on-demand spend, Claude’s usage credits or Copilot’s AI Credits beyond the allowance.
- A session hit its limit. With the hook under The
subtankcommand, Claude Code tells Subtank the moment a session hits its limit, and a notification names the account with room. Start there opens Terminal on that account, and Switch opens its menu. Nothing switches by itself, and an account you set to Quiet until it refills stays quiet here too. - Renewal reminders, a few days before a plan renews, need alerts on.
- A saved Codex reset about to expire: the day before, once, like a renewal reminder. On the day itself the row’s line says “expires today” with the time, and no second notification comes.
- At a human hour. Since 0.0.8 those two reminders come at 9 in the morning, or when you next wake your Mac after that, never at midnight.
- Room again. Tell me when it has room again, in an account’s menu or on the “hit its limit” notification, tells you once that account’s tightest window has refilled, with what is left. Subtank reads the account right after the reset, so the news is not late.
- Quiet until it refills. From an account’s menu (right-click its row), silence that one account until its window resets.
- Never for one account. Turn Alerts off for an account in Settings → Accounts, or Alerts for this account in its menu, and it is still read and shown but sends no notification of any kind: for a test key, or an account you watch somewhere else.
- Nothing arrives? If you clicked Don’t Allow, open System Settings → Notifications → Subtank and turn on Allow notifications. A Focus can hold them back too.
The Console: next refills, and spend by model
The Console keeps what Subtank has read: each limit’s history, what you spend, and Diagnostics. Open it from Console… in Subtank’s menu, the chart button at the foot of the list, or Show in Console in a row’s menu. Two parts of it answer questions the list can’t:
- Next refills. Usage opens with one line for the coming seven days: when each limit resets, and when each saved Codex reset expires. It answers “when does room come back?” for every account at once.
- By model. For an OpenRouter account read with a management key, a table of what each model cost per day, from OpenRouter’s own activity report. The report covers whole days in UTC, so today’s spend appears tomorrow. A regular key cannot read it, and the table says so.
Hide personal info
Settings → General → Hide personal info replaces emails and nicknames with “Claude 1”, “Claude 2” and so on, for screen sharing and screenshots. It covers the list, the menu-bar tooltip, notifications and the line the subtank command prints. The report in Console → Diagnostics carries no emails, names or keys either way.
The subtank command and Claude Code’s status line
Whenever its numbers change, Subtank writes one line — the account to use, what is left, the next reset — and the subtank command prints it, in the language Subtank is set to. The Homebrew cask puts the command on your PATH; from the disk image it is inside the app, at /Applications/Subtank.app/Contents/Resources/bin/subtank (a copy that updated itself from 0.0.9 or earlier may still be named subtank.app; on a Mac’s usual disk either spelling works).
subtank # the one-line status (also: subtank status)
subtank json # every account, as JSON (Numbers for other apps, below)
subtank next # the account to use next, per service
subtank claude # start Claude Code on the account to use next
subtank claude --as work # … or on the one you nicknamed “work”
subtank codex # the same for Codex
subtank open # open Subtank
eval "$(subtank env claude)" # point this shell at it
subtank status --then 'my-line' # the status line, in front of one you already had
Since 0.0.8, subtank claude and subtank codex with no account to choose from start the tool as it is, instead of stopping with an error. And the status line adds the hour-ahead warning when the account has one: “5h limit runs out in 40 min at this pace”.
To show it under Claude Code’s prompt, Settings → Advanced → Add to Claude Code… adds it for you, since 0.0.9: it shows you the file and the exact lines first, keeps a copy of the file, and keeps a status line you already had running: subtank status --then takes the numbers and lets your own command print the line. Remove from Claude Code takes it out again. Or add a statusLine block to ~/.claude/settings.json yourself:
{"statusLine":{"type":"command","command":"subtank status","refreshInterval":60}}
That works once the cask has linked the command. Settings → Advanced in Subtank shows the exact block for your copy, with the full path when the command is not on your PATH. refreshInterval keeps the line current while a session sits idle. The status commands only read a file Subtank wrote: they hold no token and talk to no one, and when the line is more than 20 minutes old they say so.
As the status line, it names the account that session runs on, found from the session’s own folder, and adds the account to use next only when that is a different one. It also passes on the limits Claude Code reports after each turn, the weekly window and the 5-hour one on plans that have it, so Claude rows stay current between Subtank’s own reads. Subtank reads each of those files once and deletes it.
To hear the moment a session hits its limit, add this hook to the same file. Settings → Advanced shows the exact block for your copy, with the command’s full path:
{
"hooks": {
"StopFailure": [
{
"matcher": "rate_limit",
"hooks": [{ "type": "command", "command": "subtank hook stop-failure" }]
}
]
}
}
The hook only drops Claude Code’s note about the stop into Subtank’s folder. Subtank looks at which profile the session ran in, deletes the note, and says which other account has room.
Use Subtank’s numbers elsewhere
subtank json prints every account as JSON. It is the file ~/Library/Application Support/subtank/status.json, which Subtank rewrites whenever a number changes and at least every five minutes while it runs (updatedAt says when). Version 2, in 0.0.7, has a version field and headline, the id of the account the menu bar speaks for. Each account, in your order, has its id, label, health and left (percent, or null when unknown), pick for its service’s account to use next, valueAt for when its numbers were read, its balance and spend where it has them, and windows, each with used, resetsAt, notStarted and its own valueAt. No email and no token. Check version in a script: fields may be added, and a change that would break a script gets a new number.
An account lists only the windows it has, so find a window by its label (5h, 7d, Fable), never by its place: on Claude Ultra or a ChatGPT Pro plan, which have no 5-hour window, the first one is the week. For example, how much of each account’s 5-hour window is used, and — where it has none:
F="$HOME/Library/Application Support/subtank/status.json"
jq -r '.accounts[] | "\(.label) \((first(.windows[] | select(.label == "5h")) | .used) // "—")"' "$F"
Anything that can run a command can show it, and nothing new reaches the network. Three short recipes; the first two use jq, which macOS 15 and later include (brew install jq before that).
A SketchyBar item, the menu bar’s own number:
# sketchybarrc
sketchybar --add item subtank right \
--set subtank update_freq=60 script="$PLUGIN_DIR/subtank.sh"
#!/bin/sh
# plugins/subtank.sh (chmod +x)
F="$HOME/Library/Application Support/subtank/status.json"
LEFT=$(jq -r '.headline as $h | (first(.accounts[] | select(.id == $h)) | .left) // "—"' "$F")
case "$LEFT" in —) ;; *) LEFT="$LEFT%" ;; esac
sketchybar --set "$NAME" label="$LEFT"
A Raycast script command, every account in Raycast’s root search, refreshed every five minutes:
#!/bin/bash
# @raycast.schemaVersion 1
# @raycast.title Subtank
# @raycast.mode inline
# @raycast.refreshTime 5m
F="$HOME/Library/Application Support/subtank/status.json"
jq -r '[.accounts[] | "\(.label) \(if .left == null then "—" else "\(.left)%" end)"] | join(" · ")' "$F"
An Übersicht widget on the desktop, with no jq (save it as subtank.jsx in Übersicht’s widgets folder):
export const command = 'cat "$HOME/Library/Application Support/subtank/status.json"';
export const refreshFrequency = 60000;
export const className = 'left: 20px; bottom: 20px; color: white; font: 13px -apple-system';
export const render = ({ output }) => {
const accounts = output ? JSON.parse(output).accounts : [];
return (
<div>
{accounts.map((a, i) => (
<div key={i}>{a.label}: {a.left == null ? '—' : `${a.left}% left`}</div>
))}
</div>
);
};
When Subtank isn’t running, the file stops changing, so its numbers age: compare updatedAt with the time if that matters.
Links from other apps
Subtank answers subtank:// links, so Raycast, Shortcuts, a Stream Deck or a bookmark can drive it:
subtank://open # the list
subtank://refresh # read every account again
subtank://settings?tab=alerts # Settings, on one tab
subtank://console # the Console
subtank://add # Add account
subtank://switch?account=work # that account’s switch menu
A link never switches by itself: switch shows the account’s menu, and you choose. It takes a nickname or an account’s id, and without a match shows the menu of the Claude account to use next. Settings’ tabs are general, accounts, alerts, appearance, advanced and about.
Updates
Subtank checks dl.subtank.dev for a new version about every six hours, when your Mac wakes after six hours or more, and whenever you choose “Check for updates…” from its menu, whether it came from this site or from Homebrew. When there is one, it downloads by itself.
- Keep it in Applications. macOS does not let a copy that runs from the disk image or from Downloads replace itself. Settings → About says so, and offers Move to Applications.
- The channel is Settings → General → Channel. Stable gets tested releases; Beta gets new versions first, a little less tested. Back on Stable, a copy running a beta waits for the next stable version newer than it.
- When it installs is Settings → General → Install updates. When idle, the default, restarts into a ready update once no Subtank window is open and your Mac has been idle for 10 minutes; When I quit waits until Subtank quits. Restart now, in Settings → About or at the foot of the list, installs it at once, and What’s new shows its notes first.
- An update that did not install is not tried again on its own. Settings → About says so until you press Try again, and then it installs when you restart or quit Subtank. A newer version replaces it as usual.
- How much it downloads. The first update after installing from a disk image downloads the whole update. Later ones download only the parts that changed.
“Subtank is an app downloaded from the Internet”
The first time you open Subtank, macOS asks whether you are sure you want to open an app downloaded from the Internet. It asks this once about every app from outside the App Store. Subtank is signed with its developer’s ID and notarized by Apple, so the same dialog says Apple checked it for malicious software and none was detected. Click Open.
If macOS says instead that Subtank is damaged or cannot be checked, the download is incomplete or has been changed. Delete it, download it again from the download page, and compare its SHA-256 with the one printed there.
Uninstalling
- Reset first, to leave nothing behind. Settings → Advanced → Reset everything removes your accounts, the profiles Subtank created and its own Keychain items — the part no uninstaller can reach.
- Quit Subtank from its menu, then drag it from Applications to the Trash. Its data stays in
~/Library/Application Support/subtank, and its log in~/Library/Logs/subtank, until you delete those folders. - With Homebrew,
brew uninstall --cask subtankremoves the app, andbrew uninstall --zap --cask subtankalso deletes its files in~/Library: Application Support, caches, preferences and logs.
What zap cannot reach Keychain items are not files, so neither the Trash nor --zap removes them: the items under the service subtank, and the one named after the app and ending in Safe Storage. Reset everything removes Subtank’s own; to be sure, open Keychain Access, search for “subtank” and delete what it finds.
Nothing Subtank reads belongs to it: ~/.claude, ~/.codex, Cursor and the GitHub CLI stay exactly as they are. If you let Subtank switch Cursor’s Claude panel, its one entry stays in Cursor’s settings.json until you switch back to your default account or delete the entry. And if you chose “Start on the account with the most room”, switch it back in Settings → Advanced before you uninstall, which removes its line from your shell profile, or delete the line that ends in # subtank there yourself. If you added Subtank’s status line to Claude Code, Reset everything (or Remove from Claude Code) takes it and the limit hook out of ~/.claude/settings.json, and puts back a status line you had before. If you let Subtank use Cursor’s key with Always Allow, it stays in the Access Control list of Cursor’s Keychain item until you remove it there, as Keychain prompts shows.
Reporting a problem
Open an issue at github.com/subtank-dev/subtank/issues, and say which service it is about and what you saw.
The quickest way to add the rest: open the Console (Console… in Subtank’s menu, or the chart button at the foot of the list), choose Diagnostics, click Copy report and paste it into the issue. The report has your version of Subtank and macOS, how each account is read and what went wrong last. It carries no emails, names or keys, and anything in an error that looks like a token is removed.
Never paste a token, an API key, or a file such as auth.json or .claude.json into an issue. Nobody working on Subtank will ask for one.
Issues are public. For anything that should not be — a security problem, say — write to support@lonelyduck.io instead. Subtank is a LonelyDuck app, and that mailbox is where its mail is read.