Subtank Download
Privacy

What leaves your Mac

No account, no telemetry. The only request to a Subtank server is the update check.

Last changed 31 October 2026, for Subtank 0.0.10: Cursor now encrypts its sign-in, and Subtank decrypts it with Cursor’s key after you allow it; four new services and their addresses; and files Subtank keeps that this page had left out. This page changes together with the code it describes.

Only the services you add

On first launch Subtank only looks. It checks a fixed list of paths on this Mac: whether files exist and when they changed, the signed-in account in ~/.claude.json, four identity rows in Cursor’s state database, the user: line of the GitHub CLI’s hosts.yml, and whether Claude Code’s or Codex’s Keychain item exists — never what is in it. It starts no vendor tool and makes no network request.

Nothing reaches a service until you add an account for it, and then only that service:

ServiceWho talks to itWhere to
ClaudeYour own Claude Code. Subtank runs your claude and asks it for its usage; Subtank sends nothing itself.Anthropic, as Claude Code always does
ChatGPT · CodexOpenAI’s codex app-server. Subtank sends nothing itself.OpenAI, as Codex always does
CursorSubtank, with the sign-in the Cursor app holds; Cursor encrypts it, and Subtank decrypts it with Cursor’s key from your Keychain after you allow itapi2.cursor.sh
Kilo CodeSubtankapi.kilo.ai, app.kilo.ai
GitHub CopilotSubtank, with the token gh auth token hands over for that one request; it is not keptapi.github.com
OpenRouterSubtank, with the key you pastedopenrouter.ai
API keysSubtank, with the key you pasted, to the service it belongs toapi.deepseek.com, api.moonshot.ai or api.moonshot.cn, api.x.ai, api.anthropic.com, api.openai.com, api.typesafe.ai, api.synthetic.new, www.minimax.io, nano-gpt.com, ai-gateway.vercel.sh, api.poe.com, api.novita.ai, api.siliconflow.com
Ollama CloudSubtank, with the key you pastedollama.com
OpenCode GoSubtank, with the key you pastedopencode.ai
A bill you trackNobodyNowhere

A browser sign-in — Claude Code’s, OpenAI’s or Kilo’s — happens on that service’s own page, in your browser, and is covered by that service’s privacy policy.

A key that can do more than read. OpenRouter shows an account’s balance only to a management key, and a management key can also create and delete your other OpenRouter keys. Subtank makes only GET requests with it, to a fixed list of OpenRouter addresses, and never creates, changes or deletes a key. Set an expiry when you create one; Subtank says when it is two weeks from expiring. The Anthropic and OpenAI keys that read an organization’s costs carry an admin’s permissions too, and a Novita AI key can start paid machines; Subtank only reads with them.

Cursor’s key. Cursor keeps its sign-in encrypted, with a key in your Keychain named “Cursor Safe Storage”. Subtank reads that item only after you click Allow access on the Cursor row and macOS asks you; with Always Allow, macOS lets later reads through without asking. Subtank uses the key to decrypt one value, Cursor’s access token, and nothing else Cursor keeps. The key stays in memory while Subtank runs: it is never written to a file, logged or sent anywhere, and the token goes only to api2.cursor.sh, as Cursor’s own does. Subtank never renews the token, never changes Cursor’s database or its Keychain item, and never edits who may read it; Help says how to take the permission back.

OpenCode Go’s address. OpenCode’s documentation doesn’t list the address its own client reads Go’s limits from, so Subtank marks that row experimental. It sends the key you pasted there and nowhere else.

The update check

Copies downloaded from this site or installed with Homebrew check for updates 30 seconds after they start and then about every 6 hours. They also check whenever you choose “Check for updates”, right away when you switch the update channel in Settings, and when your Mac wakes if the last check was 6 hours ago or more. Each check is one HTTPS request to dl.subtank.dev for a small file, latest-mac.yml (or beta-mac.yml on the Beta channel), with a number from the clock added to the address so no cache answers instead. When there is an update, that same file carries its release notes, so showing them under “What’s new” takes no other request.

The request carries no account, and neither your version of Subtank nor your version of macOS: its user agent is the generic electron-builder. Like every connection, it comes from your IP address.

Subtank 0.0.1 and 0.0.2 also send a random installation number with every check. Their update library makes it once for each copy and adds it by default. Since 24 September 2026 the server deletes it from each request before anything is written. Versions after 0.0.2 send the same all-zero value from every copy instead.

When there is an update, the download names what it fetches: the new version for your Mac’s chip (subtank-0.2.0-arm64.zip, for example). The first update after installing fetches that whole file. Later ones first fetch small index files (.blockmap) of the new version and, when Subtank has not kept one, of the version you have, and then only the parts of the file that changed.

Server logs

Caddy, the web server behind subtank.dev and dl.subtank.dev, writes every request to an access log: the time, the IP address, the address requested and the request headers, such as the user agent. Caddy leaves cookies and authorization headers out, and deletes the installation number described above. The public pages set no cookies. The only cookie on subtank.dev belongs to the owner’s admin page: it is set when the owner signs in, and for no one else.

The log is closed and a new one started every day at 00:00 UTC, and whenever it reaches 10 MiB. A closed log is deleted the next time a log is closed after it has been closed for 167 hours, which for one closed at midnight is the midnight seven days later. So a line is on disk for at most about 8 days.

A program on the same server reads the log as it is written and turns it into counts: visits, downloads and update checks per hour and per day, by page, referring site or link tag (the ?ref= in a link to this site, such as ?ref=lonelyduck on lonelyduck.io’s links), country, language, version and chip. A disk image fetched from a phone is counted as a tap, not a download. It looks each address up in a country database stored on the server; it keeps the country, not the address. Counts are kept for 13 months, and download and install totals for as long as Subtank exists. Beside the counts it keeps two things, on that server only: the last 48 hours of requests, in memory, with each address cut to its first two numbers (203.0.x.x); and, for requests that probe for weaknesses, the block of 256 addresses they came from, for 30 days. Nothing is shared, sold or sent anywhere else.

Country data: IPinfo Lite (CC BY-SA 4.0).

What there is none of

  • No Subtank account, and no sign-in to Subtank itself.
  • No analytics script or service, telemetry, crash reporter or advertising identifier, in the app or on this site. The counts under Server logs are made on this site’s own server, from its own log.
  • No remote content in the app: its windows may not load anything from the network, and Chromium’s spell-check download and Translate are switched off.
  • No scripts, cookies or third-party requests on this site’s public pages. Their fonts are served from subtank.dev itself. The home page carries one block of data for search engines (JSON-LD: the app’s name, version and requirements, and LonelyDuck as its publisher); browsers never run it. The owner’s admin page is not public, and its one cookie is set only for the owner.

What stays on your Mac

What Subtank keeps is in ~/Library/Application Support/subtank:

  • settings.json and accounts.json — your settings, the accounts you added and what you typed about them;
  • accounts.json.bak — the accounts as they were before their last change, so they come back if accounts.json cannot be read;
  • subtank.db, with its subtank.db-wal and subtank.db-shm working files — the latest numbers for each account and 90 days of samples;
  • settings.bad-…json, accounts.json.bad-… and subtank.db.bad-…, named with the time — only if one of those files was damaged and could not be used: it is moved aside, never overwritten, and a new one is started;
  • statusline.txt and status.json — the one-line status the subtank command prints, and every account’s numbers for your own scripts (subtank json): the label you see, what is left and used, balances and spend, and when each was read; no email and no token;
  • accounts.tsv — the Claude and Codex accounts subtank claude and subtank codex can start: nickname, the folder the tool is pointed at, what is left, when it resets and the hour-ahead pace warning when there is one, and, for a Claude account, a short hash of its account id, so the banner can check that ~/.claude is still signed in to it; no email;
  • tools.tsv — where the claude and codex that Subtank found are, so the subtank command starts the same ones;
  • feed/ — while subtank is Claude Code’s status line, the session details Claude Code passes to it after each turn, its limits among them; each file is read once and deleted;
  • events/ — with the limit hook, Claude Code’s note that a session hit its limit; read once and deleted;
  • switch/ — the short scripts Terminal runs for “Start Claude Code on it” and “Start Codex on it”, named after the account: a folder path, no secret;
  • cursor-settings.backup.json and cursor-settings.original.json — if you let Subtank switch Cursor’s Claude panel, Cursor’s settings.json as it was before Subtank’s last edit, and before its first;
  • renewals-reminded.json and resets-reminded.json — which renewal reminders and saved-Codex-reset reminders were already shown, so a relaunch does not repeat them;
  • .updaterId — the random installation number the update library made; versions after 0.0.2 never send it;
  • update-install.json — for a moment during an update restart, the version it is installing, so the next start can say whether it did;
  • update-failed.json — a version that did not install, so it is not tried again until you ask;
  • claude/.cwd and codex/.cwd — the folders Claude Code and Codex run in when Subtank asks them for numbers, so what they touch stays inside Subtank’s folder;
  • for accounts added with +, the profile folders Claude Code and Codex signed in to. If you share your Claude Code setup with them, what you chose goes into those folders only: MCP servers (with any keys they carry, kept in that account’s own Claude Code file on this Mac), a line that reads your CLAUDE.md, links to single skills, agents and commands, and settings one by one. Each folder keeps a .subtank record of exactly what was written and copies of what was there before, so Restore can put it back;
  • claude-hooks.json and claude-settings.backup.json — if you let Subtank add its status line to Claude Code, what it added and Claude Code’s settings.json as it was before;
  • keys-reminded.json — which key-expiry reminders were already shown.

A log of what Subtank did is in ~/Library/Logs/subtank: three files of about 1 MB at most, with anything shaped like a key or a token removed and your home folder written as ~. It never leaves your Mac.

Downloaded updates wait in ~/Library/Caches/subtank-updater: the last update’s zip, kept so the next update can fetch only what changed.

Secrets Subtank holds itself — Kilo device-code sign-ins and the API keys you paste — are in your Keychain under the service subtank, never in a file. Cursor’s key, if you allowed Subtank to use it, stays in Cursor’s own Keychain item and in Subtank’s memory while it runs: never in a file, and never copied into Subtank’s items.

Removing an account deletes only what Subtank created for it. Nothing in ~/.claude, ~/.codex, Cursor or the GitHub CLI is ever deleted. Outside its own folders Subtank changes three files, each only after you allow it: Cursor’s settings.json, when you switch Cursor’s Claude panel (one entry, with a copy kept first); your shell profile, for zsh or bash, when you choose “Start on the account with the most room” in Settings (one line that makes claude run subtank claude, shown to you first and removed again when you switch that off); and Claude Code’s ~/.claude/settings.json, when you choose “Add to Claude Code” in Settings (Subtank’s status line and its limit hook, shown to you first, with a copy kept and a status line you already had kept running; Remove and Reset take them out again). “Hide personal info” in Settings replaces emails and nicknames with “Claude 1”, “Claude 2” on screen. Uninstalling explains how to remove everything.

Questions

Subtank is made by Deokwon Song, as a LonelyDuck app. Ask about this page, or report something it gets wrong, at github.com/subtank-dev/subtank/issues, which is public. For anything that should not be public, write to support@lonelyduck.io, LonelyDuck’s mailbox, where one person reads it; mail never reaches Subtank’s server.