Releases: Nanako0129/syrtis
Release list
Syrtis 2.2.0
Features
-
Releases are signed with a Developer ID and notarized by Apple. #445
macOS now opens a downloaded Syrtis without a Gatekeeper warning, so the Homebrew cask no longer removes the quarantine flag on install. Installed copies update through the in-app updater as before: in testing, an installed v2.1.0 updated itself to a Developer-ID build, and launch at login and quota reads were unaffected.
-
Each release has an installer DMG. #454
Syrtis-2.2.0.dmgon the release page opens a window with the app and an Applications folder to drag it onto. It is signed and notarized like the app. In-app updates and the Homebrew cask keep usingSyrtis.app.tar.gz. -
A new animated menu bar icon: Sand shoal. #441
Sand falls onto a dune while a current carries grains off its far side. It plays at a fixed 24 fps in four levels: as the live token rate passes 50K, 300K and 1.5M tokens per minute at the default pace, more sand falls and the dune grows and erodes further. Suggested on Discord by charliie.
-
Animated icons follow a new speed curve, set by an animation pace. #441
The cat and parrot run at 2 fps up to 50K tokens per minute, then speed up on a log curve to 40 fps at 3M. The previous curve was linear and reached full speed at 1M. A pace choice under Settings → Menubar icon scales this for how busy your agents are: Light reaches full speed at 600K tokens per minute, Moderate (the default) at 3M, and Heavy at about 10M. The same pace moves the Sand shoal's level thresholds.
-
First-run setup cards on the Overview. #442 — relates to #435
Cards at the top of the Overview cover which agents get a tab, the menu bar icon and text, the animation pace, usage attribution, starting at login, and the Discord profile. They show at once and each is answered on its own; "Skip setup" answers the rest. Existing users see them once too, with their current choices already selected. The Discord card replaces the Discord alert that appeared at launch, and neither of its buttons turns the Discord profile on.
Fixes
-
With no quota reading, the menu bar gauge looked like a full allowance. #439 — fixes #419
When no reading is available, for example when every provider fails at once under Auto, the gauge is now drawn faded with a diagonal slash, in every gauge style and in the Settings preview.
-
An old reading's title kept its warning color. #440 — fixes #420
v2.1.0 turned the gauge grey once its reading was more than 30 minutes old, but the "Quota left" title beside it stayed red or amber, and with the cat or parrot nothing showed the reading was old. The title now turns the same grey, over both automatic and custom colors, and takes its color back with the next fresh reading.
-
Switching pages kept the previous scroll position. #444
A new Settings page, or a new tab or view in the dashboard, now starts at the top.
-
Two Settings hints described behavior the app does not have. #443
Data refresh said the live tokens-per-minute figure updates every few seconds whatever the setting, which is not how the app reads it; the hint now says the setting sets how often all logs are reread in full. Overview cards said the list sets their order; the order is fixed. The Settings hints, the usage attribution page, the Claude setup-token note and the Grok Bot Keychain notice were also rewritten in shorter, plainer language in English, Traditional Chinese and Simplified Chinese.
Syrtis 2.1.0
Features
-
A card offers to attribute your usage to subscriptions. #437
Until usage is attributed, a subscription's window history lists 0 tokens and $0.00 for every window, which reads like an idle window rather than a missing setting. When nothing is attributed yet, a card at the top of Overview and of the Quota view on every client tab lists the suggested assignments, each as the source, its provider and the subscription it would count toward, and applies them in one click. Settings → Usage attribution suggests the same assignments. "Set up manually…" opens that page, and "Not now" hides the card for good. The window history also says why its figures are 0 and links to the page, and the "Nothing is classified yet" hints in Stats now open it too.
-
Grok Build models are listed under one name. #417
Grok Build reports usage as
grok-4.6-buildwhile its session namesgrok-4.6, so one model showed up as two rows. Models, Monthly, Daily and the Grok quota card's per-model breakdown now listgrok-4.6andgrok-4.7once each, in one color. Totals are unchanged. -
The menu bar gauge turns grey when its reading is old. #418
The gauge used to draw the last reading in its warning colors however old it was. It now turns grey once the reading it shows is more than 30 minutes old, and takes its color back with the next fresh reading.
Fixes
-
Setting the clock back could erase quota history. #415
When the history file held readings stamped later than the current time, loading it dropped each such series whole. A poll that recorded anything then saved the loss. On a copy of a real history file with the clock set back 10 minutes, the previous version dropped 3 of 18 series in memory, 10,163 readings down to 3,780. That the next recording poll would have saved the loss was derived from the code, not run on the copy. This version drops only the 4 readings stamped in the future and keeps every series. Repairs made while loading are also written back to the file once, instead of being redone in memory on every load.
-
The window history said "Quota history could not be read. It will be retried." for good. #433 #434
Some sources record no quota history: Antigravity read through the
agyCLI, which carries no account identity, and a Grok Bot token that names no account. Reading their history failed on every update, and the failure was reported as one that would be retried. Their window history now shows "No earlier windows recorded yet." The retry message stays for history that exists and could not be read. -
Model prices stopped updating while you were idle. #413 — fixes #191
The model report, and the "Prices updated …" time on the Models card, only refreshed when an agent wrote new usage. While the dashboard is open, the report is now fetched again once it is an hour old.
-
A signed-in
agythat Syrtis could not find started a login shell on every refresh. #402 — relates to #353When Antigravity's other routes fail and
agyis signed in but not on the app'sPATH, Syrtis starts a login shell to look for it. If that search found nothing, it ran again on the next refresh. It now runs at most once every 15 minutes. -
Claude credential errors said only "could not be loaded". #411 — relates to #225 and #226
Each failure now names its cause in a fixed message, and no message includes credential content. A Keychain credential with a character outside printable ASCII came back from macOS as hex and was treated as unusable. It is now decoded and read.
-
A malformed Codex token could skip the refresh check. #397 — fixes #385, thanks @snowman12320
A token with a missing, extra or empty segment could supply an expiry that kept Codex from refreshing. Such a token's expiry is no longer trusted, and the refresh falls back to the time of the last refresh.
-
Quota history that failed to load was described as never recorded. #405
Past windows and the heatmap now say "Quota history could not be read. It will be retried." when a window's history failed to load and nothing is left to show.
-
The separators in the light glass panel were harsh. #436
On macOS 27 in light mode, the lines under the row of views (Overview, Quota, Models…) and above the footer are now lighter. Dark mode is unchanged.
Full Changelog: v2.0.1...v2.1.0
Syrtis 2.0.1
Fixes
-
Hover tooltips in the glass panel were hard to read over a list. #399 — relates to #398
On macOS 27 the tooltips used clear glass, which barely blurs what is behind it, so over the window history the rows beneath showed through the tooltip's own figures. The tooltips now use the same frosted glass as the panel.
Full Changelog: v2.0.0...v2.0.1
Syrtis 2.0.0
Before you update
TokenBar is now Syrtis, and the first launch renames the app on disk. #392 #395 #390
The update installs over TokenBar.app. On its first launch the app renames itself to Syrtis.app in the same folder and starts again from there. The bundle identifier has not changed, so settings, usage history and the login item carry over.
If TokenBar.app is pinned in the Dock, the tile is repointed at Syrtis.app and the Dock restarts once. Two things follow from that restart. Windows you had minimized to the Dock leave it; clicking their app brings them back. The pinned tile may keep the old icon until you click it once.
The rename is skipped when a Syrtis.app already sits beside it, or when the account cannot write to the Applications folder. The app then keeps the file name TokenBar.app and works the same.
Homebrew has a new tap. New installs use brew install --cask nanako0129/tap/syrtis. An existing install from nanako0129/tokenbar keeps updating through the app itself; that cask stays on the last TokenBar release. To move an existing install to the new tap, quit the app, run brew uninstall --cask tokenbar, move Syrtis.app (or TokenBar.app) from Applications to the Trash, then run brew install --cask nanako0129/tap/syrtis. The uninstall alone can leave the renamed Syrtis.app behind. Settings and usage history are kept.
Some clients re-scan once, and several count differently. #386 #389
The engine moves forward, and Copilot, Grok, OpenClaw, RooCode, KiloCode, Cline, Cursor, OpenCode, Pi and Droid each rebuild their cache once on the first launch. Every other client, Claude and Codex included, is read from its existing cache.
- Pi counts fall if you fork sessions. A forked session copies the parent's replies into the new file with the same response id, and each copy was counted again. Each reply now counts once.
- OpenClaw counts can move either way. Archived sessions (
.jsonl.zst) are now read, which adds usage that was missing, and compaction checkpoints are no longer counted as usage. - OpenCode 2.x usage appears. It read as zero because the old session lookup failed on 2.x.
- Grok usage after an invalid UTF-8 line is recovered. A session file used to be dropped from its first invalid line onwards.
Droid totals are unchanged: a session's usage is now split across its replies instead of landing as one record. Cursor's Input (w/ Cache Write) is now counted as cache write, and a $0.00 cost Cursor reports is kept as $0.00.
Costs for claude-fable-5-1 and claude-opus-5-5 fall by 16.7%. #389
The previous engine could not match OpenRouter's dotted names for these two models (claude-fable-5.1, claude-opus-5.5) and fell back to an AWS GovCloud Bedrock price entry that is 1.2 times the list price on every rate. They now resolve to Anthropic's own entry. Token counts are unchanged, and past usage is repriced the same way. claude-opus-4-8, and claude-haiku-4-5 used through OpenCode, rise slightly where some of their cache writes had been priced at $0.
Features
-
On macOS 27, the dashboard opens in a Liquid Glass panel. #380 #391
The popover blurred the desktop before the dashboard could see it, so its glass could only show a flat tone. The panel's glass refracts the actual wallpaper. It closes on Esc or a click anywhere else, and right-clicking the menu bar item still opens the menu. Tab selections slide, bar charts regrow and heatmaps crossfade between views. Below macOS 27 the popover is unchanged.
-
A new icon and name in the app. #392
The panel header shows the Syrtis mark and the Greek wordmark Σύρτις, the Settings sidebar uses the same mark, and Discord presence shows the new icon. The site is now syrtis.nyanako.com, with a page on where the name comes from. Old links to the TokenBar site and repository redirect.
Fixes
-
A quota window's readings were deleted when they could not be modelled. #373 — relates to #370
History kept only the windows a pace curve could be fitted to. When a provider moved a reset later, the window's recorded reset no longer qualified, and its readings were erased: on the store behind #370, two weekly windows of 51 readings each. They are now kept, within the usual history limits. They still do not feed the pace model.
-
Codex asked you to sign in again while a refresh token was available. #344 — thanks @snowman12320
Codex access tokens can expire before the eight-day interval TokenBar used to decide when to refresh them. The token's own expiry is now checked, and it is refreshed within five minutes of it.
-
Switching windows on the quota window card paused the app. #383
Each switch re-read the whole quota history once per part of the card that wanted it: 131–144 ms on the main thread in a release build. Each series is now read once per update, and a switch takes 12–15 ms.
-
Opening the dashboard right after launch computed the usage graph up to three times. #384
Requests that arrive while the graph is being computed now wait for that result. In three paired runs on real data, the graph was ready after 2.4, 2.2 and 2.1 s, down from 5.6, 3.7 and 4.6 s.
-
The Local Network prompt did not say why it appeared. #374 — thanks @mvanhorn
macOS can ask for local network access when a VPN routes provider traffic through a local network. The prompt now explains that Syrtis connects to your providers to read quota information.
New Contributors
- @snowman12320 made their first contribution in #344
- @mvanhorn made their first contribution in #374
Full Changelog: v1.20.2...v2.0.0
TokenBar 1.20.2
Fixes
-
With the Antigravity CLI signed out, TokenBar could open a Google sign-in page on every refresh. #378
When the Antigravity IDE is closed and no Gemini CLI login is available, TokenBar asks the
agyCLI for quota instead. Signed out, that command opens a browser tab for Google sign-in and waits, and TokenBar ran it on every refresh: once a minute with the popover open.TokenBar now checks that
agy's login item exists in the Keychain before running it, and skips the CLI when it does not. Only the item's presence and modification date are read, never the token. Ifagyruns and still fails, it is not run again until you sign in toagyagain or restart TokenBar; until then the Antigravity card shows the error from the other routes.
Full Changelog: v1.20.1...v1.20.2
TokenBar 1.20.1
Fixes
-
A model with no price read
$0.00, the same as free usage. #375A row that shows a token count beside an amount now shows
—when those tokens could not be priced. That happens when a model is not in the pricing data yet: Claude Opus 5.5 read$0.00until LiteLLM and OpenRouter listed it on 2026-09-22. The Models tab, the model breakdown, Agents, the Daily and Monthly rows, the usage chart, the heatmap and the usage attribution rows all follow this.In the same places, a positive amount under half a cent now reads
<$0.01instead of$0.00. Totals shown without a token count beside them are unchanged, and they still count unpriced usage as nothing.
Full Changelog: v1.20.0...v1.20.1
TokenBar 1.20.0
Before you update
Repairing an unwritable history file drops a few stored samples, once. #371
A history file the engine could no longer write is now repaired on the first poll rather than refused, and the repair drops the samples that were making it fail validation. Measured on one real store: 39 samples of 5815 in one series, 0.67%. The polls after it needed no repair.
Features
-
Hovering a row in a window's history shows what its tokens were. #368
Input, output, cache read and cache write, each with its share as a percentage, under a heading naming the window's date and time span. The whole row is the hover target rather than the token count alone, and each model line carries its own breakdown.
Fixes
-
Pace and history read "unavailable" for every provider, and stayed that way. #371 — relates to #370
A write the engine refused wrote nothing and quarantined nothing, so the next poll met the same file and refused it identically. The refusal was permanent rather than transient, and it takes every window in the batch with it: one series stopped the whole lens reporting pace. The write is now repaired inside a bounded allowance instead of refused.
The cost was worse than a blank field. While writes were refused the window in progress stopped gaining readings, and a window that ends with no readings near its end was deleted outright — so a refused write destroyed the window it had been unable to extend.
#370 is not closed. A separate defect still deletes a window whose reset the provider later revises.
-
One provider's unreadable credential erased every other provider's history. #360 — relates to #359
A read that fails now costs only its own window. A card whose read failed keeps what it already had, instead of the failure emptying the lens.
-
A few seconds of drift in a provider's reset time split one window into two. #369 — relates to #367
The second of the pair read 0% against the full span's tokens. Readings a few seconds apart are grouped as one window again, and the group reports the reset time most of its readings agree on.
-
The quota cards were recomputed from scratch every time the popover opened. #361 #364
The history strip, the heatmap and the equivalences are drawn from the reopen cache, so they are present when the popover appears rather than arriving a moment after it.
-
The daily chart flashed empty for a frame when the popover opened. #362
A series' rows are folded when the view is constructed, not on its first task tick.
Full Changelog: v1.19.1...v1.20.0
TokenBar 1.19.1
Fixes
-
The Quota lens could report that no history had ever been recorded, about history that was still on disk. #356 — reported in #355
Past windows and When the allowance goes fill on launch and could go empty after the app had been running a while, saying
No completed windows recorded yet. Nothing was lost — relaunching brought the cards back.A refresh that cannot read any history no longer replaces what is already on screen. Quota history accumulates, so a refresh returning nothing after those cards have been filled is that pass failing to answer rather than the history ceasing to exist, and the cards now keep what they have.
Why those reads come back empty is still open in #355. This does not claim to have fixed that; it stops it from erasing what was already recorded.
Full Changelog: v1.19.0...v1.19.1
TokenBar 1.19.0
Before you update
Tabs for providers you never set up disappear, and Antigravity's two tabs become one. #348 #349
Both are visible the first time you open the popover.
v1.18.0 began including configured quota sources in the tab bar alongside local usage, which is right for a provider you use and wrong for one you don't. Codex, Claude and Antigravity are built as cards that always exist, so the presence of a card said nothing about whether anything had been set up, and Codex and Antigravity took a tab on every install. Reported in #345. A provider with no credential at all now has no tab. One whose credential exists and cannot be read — a permission problem, a corrupt file — keeps its tab and shows what went wrong.
Antigravity's IDE and CLI clients draw on one subscription and had a tab each. They now share one, labelled Antigravity, the arrangement Grok Build and Grok Bot already use: the CLI's usage and the IDE's quota card sit under it together. Your own settings survive the merge — a hidden Antigravity CLI tab stays hidden, and its place in your saved tab order becomes the merged tab's.
Fixes
-
An
agyinstalled after TokenBar started was never found. #330 — thanks @iF2007Antigravity's CLI discovery cached its answer for the life of the process, including the answer that there was nothing to find. Installing
agywhile TokenBar was running therefore changed nothing until the next launch, and the card went on reporting the error it had been given before. An empty result is now retried on a later refresh.
Full Changelog: v1.18.0...v1.19.0
TokenBar 1.18.0
Before you update
Codex turn counts jump from zero to thousands, and the first launch rescans Codex transcripts once. #315
Codex used to announce a human turn as an event_msg of type user_message. Around version 0.145 it stopped, and now reports the same input as an item_completed carrying a UserMessage item. TokenBar recognised only the old shape, so is_turn_start never fired on a recent transcript and the Daily and Monthly cards read 0 turns for Codex on essentially every day.
Nothing was recounted. On every day with Codex activity, every other figure is byte-identical before and after — tokens, cost, messages, models. Only the turn column moves, which is what makes this checkable: the number that was wrong is the only one that changed.
Reading turns out of the old cache is not possible, so parser_version for Codex moves 5 to 6 and every Codex shard is rebuilt once on first launch. No other client's cache is touched — Claude, Copilot, Gemini and the rest are read from their existing shards as usual. The launch after it is normal speed.
Features
-
The paid OpenCode Go plan now has a quota card. #301 — thanks @binhonglee
OpenCode stores the Go plan under a separate api key, and TokenBar read only the Copilot quota that lives in the same
auth.json. Its rolling, weekly and monthly windows now appear under the existingopencodeclient rather than as a new tab, the same arrangement the Copilot quota already uses. -
Kiro's monthly allowance now appears as a quota card. #305 — thanks @binhonglee
Kiro was already recognised as a subscription for attribution, but no quota was ever fetched for it, so the plan had no usage bar. The token is discovered from either the kiro-cli store or the Kiro IDE token file.
-
Grok Bot's weekly allowance now appears alongside Grok Build's. #316 — thanks @savourylie
The two are separate allowances and only Grok Build's was read. Both now appear together under a Grok Build & Bot tab in Overview and Quota, including on machines with no local Grok usage records at all.
Reading that allowance needs your permission once. #338
Grok Bot keeps its login in your Keychain, and the weekly limit cannot be read without decrypting it. Rather than letting macOS ask out of nowhere, the card says what it needs and waits. Allow proceeds, and the system dialog follows a second or two later; Not now leaves the card as a single grey line, with Allow still there whenever you change your mind. If macOS itself refuses, or never answers, the card says so and TokenBar stops asking rather than raising the dialog again every cycle — Allow tries once more when you want it to.
The login is used for one thing: asking Grok Bot's usage endpoint (
api2.cursor.sh) what your weekly limit is. TokenBar does not store it, does not log it, and sends it nowhere else. Declining affects that card and nothing else — there is no setting to find and nothing to undo later, because once macOS holds the grant only macOS can withdraw it.Having Grok Bot signed in already does not change this: the card still asks, and macOS may still want to confirm. Reading the item is what this integration does for the first time in this release, so there is no prior grant to rely on, and TokenBar cannot check for one without performing the read it is asking about — asking macOS whether it would allow the read is the read.
-
Window history grows past twelve rows. #334
The card drew twelve cycles with no way to reach the thirteenth. It still opens at twelve, and a
Show N morelink under the list adds twelve per press until every cycle is on screen. Pressing to exhaustion reaches 32, which is where the engine's fold stops.
Fixes
-
A quota poll could open a browser tab you never asked for. #332 — reported by @banahaker in #329
agy --printis documented as non-interactive and is not: with an expired token and no DNS, it treats the network failure as an authentication failure and starts an interactive sign-in, which opens a tab. The defect is the CLI's, but TokenBar is the only thing invoking it unattended, and its timer fires exactly when that path is most likely. TokenBar now resolves the endpoint first and gives up without invoking the CLI when that fails. -
A window-history card said usage was never recorded, about usage sitting in the same scan. #322
Two different statements were collapsed into one flag: this machine recorded nothing, and this machine recorded it and you have not said which subscription it belongs to. Three places computed that flag, each the same wrong way, so a client you had not classified was reported as having no records at all. The flag is now decided per subscription.
-
One long model name stretched a whole usage card past the edge of the popover. #336 — reported in #335
The layout measured every legend item at its ideal width and took the widest row as the card's own width, so a single entry wider than the popover stretched everything around it. Locally-served model names reach that length easily — the report had one running to
hauhaucs/qwen3.8-27b-uncensored-…. Items are now measured against the row they sit on, which lets the label's single-line truncation do the job it was already there to do. -
An OpenCode Go window could be dated to a cycle that had already reset. #327
The clock was read on the first line of the fetch and held across the credential load and the HTTP round trip, so a reset that expired while the request was in flight still compared as being in the future. The clock is now read after the response arrives.
-
A cancelled quota poller kept running for the rest of its minute. #331
Closing the popover cancels the poller, but the sleep it was parked in observed only its own timeout, so the task stayed alive for up to a minute after the window it served had gone. Nothing observable went wrong, which is why it lasted: the work was not incorrect, only late to stop.
New Contributors
- @binhonglee made their first contribution in #301
Full Changelog: v1.17.0...v1.18.0
