Repository navigation
release: 0.5.0 - #51
Merged
Merged
Conversation
The runner sent SIGKILL half a second after SIGTERM. On its way out Claude Code waits up to two seconds for a token refresh in flight to be saved, and the refresh token changes with every refresh, so a kill in that wait could leave the account without a refresh token that works. The keeper now gives both commands five seconds; every other command keeps the half second. The cycle watchdog grows from 270 s to 280 s to cover the longer grace.
…n help Claude Code renews a token only inside its last five minutes: every refresh it makes, short of answering a 401, first checks now + 5 min >= expiresAt (read out of the 2.1.290 to 2.1.302 binaries). The keeper ran claude doctor from 30 minutes before the expiry, so the first doctor of every token did nothing, counted as a failure, and the claude -p after it spent limit and started the account's 5-hour window for nothing. The keeper now acts 4 min 30 s before the expiry, inside the CLI's window with half a minute to spare.
Claude Code's native binary runs itself as other tools: as rg, its bundled ripgrep, and as ugrep and bfs for the grep and find of its Bash tool's shell, under that name (ARGV0= in zsh, exec -a in bash). Such a process inherits its session's CLAUDE_CONFIG_DIR, and one left behind in an old tail -F | grep pipeline ran for days after the session had gone. Brow took it for a session holding the account and never refreshed that account's token. A process whose argv[0] is rg, ugrep, bfs or apply-seccomp is no longer counted.
…g its token Since 0.3.1 an account with a live claude process for its folder was left to that session, however long it had sat idle, with nothing to fall back on as the token ran out, and the refresh button could not override it. A session renews its token only when it sends a request in the token's last five minutes, so with sessions left open for days nothing renewed any token: eight hours after its last refresh each account read "Token in use by Claude Code", then "Rate limited", and signing in again only restarted the clock. The 0.3.1 worry, a refresh by Brow racing the session's own, no longer holds: Claude Code takes a lock in the config dir around every refresh and re-reads the token under it. A session now holds the keeper off only while the token has more than two minutes left. After that, after a 401, and when a refresh is asked for (the refresh button, a wake, a sign-in), the keeper runs whoever holds the account. Each stretch of either is logged once, at the default level, so it is kept.
The usage client sent a token whatever its expiry. The endpoint can only refuse a dead token, the client retried every 401 once, and with Brow polling every 30 s the account's row went from "Token in use by Claude Code" to "Rate limited". A token past its expiry now stays home. The panel says "Token expired 12 min ago", and adds "— Claude Code hasn't refreshed it" while a session holds the account. When the keeper's attempt floor is what holds the refresh back, the dead token gets the one forced attempt a 401 would have bought it.
The key lit for any 401, and the token line read "sign-in revoked", so a token a refresh would have fixed sent you to sign in again; with an idle session holding the account that only restarted its eight-hour clock. A 401 now reads "Anthropic rejected the token" and buys the keeper's forced attempt. The key lights when the keeper says the login is dead, because claude doctor or claude -p printed "Please run /login" or three attempts in a row did not renew the token, and, as before, when an account has no token at all. The keeper keeps that verdict with the token it was reached on, through its attempt floor and a relaunch, until a new sign-in replaces the token or a refresh lands, and spends no claude -p on a login the CLI says is dead.
Brow's 30 s poll keeps firing in the dark wakes of a sleeping Mac (Power Nap, maintenance), and the keeper ran claude doctor and claude -p in them. A doctor frozen mid-refresh when the Mac goes back to sleep can lose the refresh token that still works, and -p spends limit with nobody there. From macOS saying it is going to sleep until the wake that follows, while the main display is asleep, the keeper now runs nothing; the usage reading still goes out. The display check keeps a sleep that never ended in a wake notification from holding the keeper off for someone at the screen.
The changelog's Unreleased section says what changed and why the 0.3.1 reasoning no longer holds: Claude Code locks around every refresh, and an idle session renews nothing. docs/brow.md and the three READMEs said Brow never refreshes a token a session is using and that the fallback runs from 30 minutes out; they now say a session gets the first go while the token has more than two minutes left, and that claude doctor runs in the token's last 4½ minutes.
Two moods at the ends of the meter, judged like the others on H plus the food still on the plate, with 5 points of hysteresis: Stuffed from -35 coming down until above -30, and Famished from 90 until below 85. Stuffed takes about six points from 0 or a feast from 13 or below and wears off within an hour of hunger time from the floor; Famished comes 4 h 30 min after 0 at an even pace and is left only by food. A meal carries the mood it was planned in. A full meal that leaves the pet stuffed is followed by `brim`, a full meal or a feast eaten famished by `grateful`; a nibble is a lick as before. The words are Stuffed and Famished. pet.json is unchanged: a restored pet takes the mood its H gives. Until they get their own look, the two ends wear their neighbours' faces.
…f the panel The outline's bottom corners are Apple's continuous corners: the quadratic ones turned at once, with the control point on the corner, which read as a plain radius. The open panel's radius goes from 18 to 24 pt, where a continuous corner reads as one soft curve; the strip keeps 14. The flares are drawn beside the body, so the two never overlap and no seam can show. NotchGeometry.frames takes the open panel's width, so a screen of the one window can ask for its own.
maxDayCards shows that many accounts beside the month and then "+N more on this day", so a day on which every account resets cannot make the column taller than the panel was sized for. nil keeps every account, as before.
The keeper's "sign in again" came only from the -p leg, and a token past its expiry reached the keeper flagged as rejected (the store flags it so the attempt floor lets one attempt through), which skips -p. So once a dead login's token had expired, every attempt stopped at claude doctor, the breaker was never reached, and the key stayed grey for good: doctor prints a report, not "Please run /login". A token past its expiry is now renewed like a due one: -p and the breaker apply to it. Only a token Anthropic refused while it still had life left stays at doctor, as before. The breaker's verdict no longer needs the -p leg either, so it also reaches people who turned the fallback off.
claude -p is not interactive, and there the CLI words a dead login "Failed to authenticate: OAuth session expired and could not be refreshed", "Failed to authenticate: OAuth token revoked. …" or "Failed to authenticate. API Error: …"; "Please run /login" is what an interactive session says (2.1.290 to 2.1.303). The keeper looked only for the latter, so a dead refresh token, the commonest dead login, went unheard. It now takes either, and the key lights on the first attempt after the token expired instead of three attempts later. The changelog and docs/brow.md say which words count.
With the network down nothing can renew a token, and the usage request that used to say "Offline" is no longer sent for one past its expiry. So on a long flight every account read "Token expired 2 h ago — Claude Code hasn't refreshed it", which points at the session and at signing in again, while the account comes back on its own with the network. The row and the footer say "Offline" again, and the token is still not sent.
The changelog and docs/brow.md say a token past its expiry is not sent to Anthropic, but only the usage request held to that: the daily api/oauth/profile request still went out with a dead token, about once an hour per account while the token stayed dead. It now throws the same "expired" error the usage client does, without a request.
…session Two of the rules that let the keeper run past a session holding the account were pinned only by the table test of holderRule: with the 401 rule or the dead-login rule taken out, every cycle test still passed. The 401 test used a token with five hours left, which no session holds the keeper off for anyway, and no test had a dead login with a session open on it. Now a 401 with three and a half minutes left still gets its forced doctor, and a dead login with a session open on it keeps the sign-in key lit and the keeper's word in the token line.
docs/brow.md said the fallback is never used after a 401/403. Since a token past its expiry is no longer sent, nothing refuses it, and the keeper gives it claude doctor and then claude -p like a token that is due; only a token Anthropic refused while it had time left stays at doctor.
ScreenMetrics carries the screen's visible frame, and NotchGeometry gains the height the open panel may have: from the screen's top edge down to 12 pt above the visible frame's bottom (the Dock, or the screen's edge), and a 480 pt floor for a panel with sections. panelHeight takes the content's own height between the two.
… at the month The grid always reserves six week rows, so walking from a five-week month to a six-week one never changes the panel's height. The day's cards are drawn over the space beside the grid and are cut at its height: as many as fit, at most the number the panel asks for, then "+N more on this day" with the other accounts' dots. A day on which every account resets can no longer grow the panel and push its bottom row out of the outline. The tests run on made-up accounts (MadeUpLimits: the README's three and five more), for a four-, five- and six-week month and every hovered day.
claude -p ends any 401/403 that its own one forced refresh did not clear with "Failed to authenticate. API Error: …", and that refresh also fails when the token endpoint errors or does not answer, or when another process is in the middle of a refresh (read out of 2.1.303). The keeper took the line for a dead login, so an outage at the token endpoint would light the sign-in key on every account whose token ran out during it, and send people to sign in again for nothing. A dead refresh token reads "Failed to authenticate: OAuth session expired and could not be refreshed", and the CLI clears it from the Keychain, which the next scan sees as no token. That line and "OAuth token revoked" still count.
…I's own deadline On SIGTERM Claude Code cleans up first (up to 2 s), runs the SessionEnd hooks (1.5 s unless configured otherwise), and only then waits up to 2 s for a token refresh in flight to be saved. Its own deadline for all of that is 6.5 s, and 8.5 s while a refresh is in flight (2.1.290 to 2.1.303). The five seconds Brow gave it could end in the last of that wait, which is the kill the grace exists to avoid. Nine seconds outlast the CLI's deadline. The cycle's worst case becomes 267 s, still inside the 280 s watchdog, and the test that recomputes it from the constants passes unchanged.
Stuffed sits round and low, leaning back from the number belly out, the nubs on its belly, eyes shut in bliss over a wide smile and rosy cheeks, its light over the brim. The belly is the meter's: it bulges the lower sides and sets the feet wider from -26 down, so the bite that makes the pet stuffed rounds it as the light lands and it goes down by itself as hunger returns; curled up asleep there is none. The eyes open out of their bliss every 6 to 18 s for a couple of seconds. Its beats take the place of the habits that do not suit it, one gesture at a time: a pat-pat on the belly, a contented sigh with a puff of breath, a peek at the number and a lick, a hiccup, and about every three minutes a thumbs-up with a wink and a sparkle, the arm away from the readout coming up with a little thumb. The thumbs-up's rise and the hiccup's hop are drawn in the fast class. It still eats, leaning for the food rather than leaping, its belly bouncing as the bite lands, and the swallowed light carries no tint at a stuffed mouth. A full meal that leaves it stuffed ends in pats, a thumbs-up and a sigh; a feast that does the same in the stuffed face. Out of stuffed it settles into Full over 2 s. Eyes open and shut on a quick clock of their own wherever a posture blend takes them across the drawings' cross-fade. The old heavy-lidded face is now `heavy`, the start of the yawn at the 5-hour limit. The body's box, which the zone clamp keeps inside the zone, is now measured on the points the outline is drawn through and counts the arms' and the thumb's stroked edge: the round belly bulged between the coarser points it was measured on, and under the notch at 100 % a stuffed meal's belly and cheeks came within the readout's 4 pt.
launchCommand takes the environment a session starts with from the app that hosts the engine, already quoted, in place of the CLAUDE_CONFIG_DIR and BROWSER it would build. Brow passes env -u CLAUDE_CONFIG_DIR for the default account, so a shell that exports another account cannot make the session run as that one. A blank one is none.
…vironment Workspaces' screens learn where they are drawn: a window of their own, or a section of a host's panel (groveHost), and in which accent (groveAccent: Grove's blue by default). Stats, Graph, the stats settings and the notices draw their controls, links and glyphs in it; the repositories keep their own chart colours. Cards in a host's panel are its own: white at 5.5 % with a 7 % edge. FadingScrollView is the screens' scroll: a fade at the top once scrolled and at the bottom while there is more. Offscreen, where ImageRenderer draws no ScrollView, it clips the content to the room it is given at a render offset that never runs past the end, and draws the indicator; given no height it is as tall as its content. isSnapshotRender is public, with a snapshotRender() modifier, so a host renders the screens too. Graph's repositories sit in one row that scrolls sideways and never wraps a name. ScopeHeader takes the screen's own actions and a subtitle under the title.
Famished stands up on its toes, leaning in at the number and a step closer to it, the near nub reaching for it, with shining eyes (bigger catchlights and a third pin of light, never at the lower rim), brows high and level, an eager open smile and rosy cheeks. Its light is the meter's; the face carries the hope: never a raised inner brow, a frown, a lower body, a tear or a tongue resting out. Its tummy grumbles every 25 to 43 s on a schedule of its own: it looks down at it, surprised, pats it with both nubs and goes back to the number with a hopeful smile and a lick. Coming up from hungry, the first grumble comes at once, or 8 s after a rumble it has just had, and the schedule's own start 20 s after it. It reaches on tiptoe with grabby little circles, and about every three minutes asks please: the shining eyes on the viewer, both nubs at its cheeks, two quick happy squints. Blinks keep out of the grumble and the please. Settled, it only rumbles, at half strength. Its meal starts with a hop of joy and sways through the chews; a full meal or a feast eaten famished ends in the grateful beat, a self-hug with sparkles and a bounce, then shining eyes back on the number for more. A nibble gets a quick happy squint. Leaning in, it turns its whole face to the number: the head takes part of the eyes' travel, so the big eyes stay over the smile instead of sliding across the face onto it, and its look down at a grumble is a little slower, so that face never sweeps across the body faster than the idle's half a point a frame. The readout guard now renders both ends of the meter and every gesture of theirs.
Opening the panel is a new event for the brain, `panel(open:)`, sent at the instant the outline starts to spring. When the pet rests at an end of the meter, Reduce Motion is off and no greeting came in the last three minutes, the brain cues `greet` once the hop into the header has landed, 0.6 s later. The rig plays it as the mood's own gesture, a thumbs-up stuffed and please famished, waiting up to 1.5 s for a gesture already playing to end or letting it go, and nothing if the mood has changed by then. The pointer coming close greets nobody: near the notch it is often on its way to the menu bar. The greeting's leap is drawn in the fast class like the others, and the controller wakes at both ends of it. A beat under way when the mood changes plays on into the next idle, and one an action cuts short fades with it rather than vanish.
…e-eyes Between the bean eye and the happy arc the drawing cross-fades, and an eye held in the cross-fade for more than a couple of frames shows both: the idle lick peaked there for about nine frames at its half pace. The lick's and the squish's squints now go all the way to the arc in the same time, and the scratch's squint and the celebrations' joy open and shut on the eyes' quick clock. A blink took the lids down with their slant, so the half-shut frames of a hungry blink read as a side-eye; the slant now goes down with the lid and the middle of a blink is level. A new scan walks the eyes frame by frame at 30 fps through every idle mood, settled, eager and the ten-minute script, which now visits both ends of the meter. Stuffed, eyes opened out of their bliss that would shut just as a gesture opens them on its own (the thumbs-up, room for more, the hiccup, a mote) stay open for it: shut and opened again at once, they stopped half way for three frames. The ten-minute script also greets at both ends.
Asleep at the limit the brows pressed down onto the shut eyes over a dark open dash, which drew "=_=", the face of someone bored or put out. The brows now rest easy above the shut eyes, the mouth is a small closed smile and the cheeks are warm: full, cozy and content. The loaf, the light, the Zzz, the yawn into it, drowsy and hibernation are unchanged.
…footer The panel is a shell installed once, which a publish of the limits never rebuilds: the band at the top, a switch between sections while there is more than one (Limits, and the sections a host registers), the section's content, and one footer that is never part of a scroll. One width and one height for every section — the Limits section's own laid-out height, measured offscreen rather than read back from the window's frame, at least 480 pt while there are sections and at most 12 pt above the Dock — so switching sections never moves the outline, and the bottom row is always inside it. On Limits, Glim's row and the Overall line are a fixed header and the accounts and the month scroll under them; the month's day column shows three accounts at most. The footer is the same on every section: the section's status line, its own button (Limits' share), the pin, ⟳ and ⚙ with the version, Settings… and Quit Brow. Hovered, the panel opens and closes with the pointer, on the section it last closed on for 15 minutes. Any click inside pins it: only then may the non-activating panel become key, so its fields take the keyboard without activating Brow, and the pointer leaving no longer closes it. It closes on Esc at a section's root, a click outside, the pin or a hand-off, and every close latches the hover until the pointer has left. While pinned, ⌘1–⌘3 and ⌃Tab switch sections, holding ⌘ shows the keys, ⌘R refreshes the section in front, ⌘, opens Settings and ⌘Q quits. It can open pinned with the notch off, at the top centre, for as long as it is open. Off Limits the band keeps the strip's readouts and Glim stays on its ledge; switching to and from Limits hops it with today's hop. The shell stays in the tree while the panel is closed, so what a section holds is there when it opens again. Cream is the one accent. The Workspaces button leaves the footer: Workspaces becomes a section of this panel. The README's panel renders draw the controller's own outline at the height it measures.
PetMoodsPreviewTests renders the two ends of the meter through Brow's real window on the cream desktop of Brow's pictures, every number made up: the six moods side by side at 4x and at real size, stuffed and famished pose by pose, both under the notch and on the pill, the panel's header, films of the strip at 60 fps (a 4x zoom over the real strip) of each end at rest, eating, coming in and going out, the panel's greeting played by the real controller, the sleep at the 5-hour limit, and one day through the brain that passes through both ends. Skipped unless PET_MOODS_DIR names an output folder; each test is best run in a process of its own.
…gents Every opening of the panel, a pass of the pointer on its way to the menu bar included, started the agents' watch, and after half a minute closed its cold start: a look through every account's projects folder and the end of each transcript written in the last half hour. The watch now starts once the panel has been open for a quarter of a second, the rule Projects already scans by, and not at all if it closed before.
…ever under a running session Confirmed in the row, Delete did nothing, without a word, when no account was the canonical one (every account outside ~/.claude): the guard came from the safety net, which the delete only cleans as well. And the row asks before it deletes, so a session could start running between the two: its process would go on writing a file no longer there. The delete now looks at what runs first, as Share and Resume as do, and says why it will not.
The item opens the panel pinned on Projects, and a second click should close it. But the pinned panel took the item's mouse-down for a click outside and closed, so the item's action, on the mouse-up, found it closed and opened it again. A click on Brow's own status-bar window is now left to the item.
…anscript the agents reader takes
With "Show Brow in the notch" off the panel opens pinned from the menu-bar item, the menu or a reopen. Pressing the pin then unpinned it, which took away Esc and the click outside, and with no strip there was no pointer to leave it either: nothing closed the panel short of pinning it again. Now the pointer leaving closes it, as it does with the notch on; nothing hovers it open.
…d state The session index reads what runs, then lists transcripts for a while; a session record written meanwhile (a turn ending) is read again and shown at once. When the index finished after that, its older read went back up: a session gone idle showed "Working" again until the next read, up to the next 15 s refresh. Every read is now numbered as it starts and only the newest started is shown; the index's rows take their states from it.
The shell stayed in the tree while the panel was closed, invisible, so every publish of what its sections read and every frame of the strip evaluated it again: a third of a core and more with a large project open. It now leaves the tree once the closing spring has settled. Where Projects is lives in AppState's route, so the panel opens where it was; a section holding something a rebuild would lose (a form, a creation's log) keeps it in.
A project can hold a hundred loose worktrees that agents and scripts left behind, and each was a row with its own "New session" menu, which read every account and its limits again on every publish, and git ran for each on every refresh. Worktrees with no session, process or cmux workspace now count on one line, listed when it is opened or a search finds them, with no git run for them. The menu's accounts are read once for all rows.
Each project listed every session under its folder or its workspaces folder, so two projects whose folders overlap, one inside the other or two of one name sharing a workspaces folder, both showed it: one session counted as two at work. A session now belongs to the project whose folder holds it most closely. A folder that is a project's, lies in one, holds one, or shares a project's name is not added as a second project.
A session run in ~/Projects offered all of ~/Projects as a project, every repository in it included. A folder right in the home folder, or one holding more than twelve repositories, is where projects are kept, not one.
Transcripts written by claude -p and the Agent SDK (entrypoint sdk-*) were listed and counted with the sessions someone typed in. The entrypoint is read from the same first record as the folder and kept with it.
Projects opens from the notch, the Brow menu and opening Brow again. Settings keeps the old switch's value for older builds, as it keeps 0.4's panel material.
DemoScreenshotTests renders the panel's Projects and Agents sides and the screens Workspaces pushes in it from the made-up world of the review renders, and renders the notch, the panel and Settings › Workspaces again. Each changed picture has a new name, since GitHub and browsers cache an image by its name. Workspaces' renders as a window of its own go: the window is gone.
The workspace pictures are the panel's: a project with a workspace open and Resume with options with each account's limits, and a new section shows Projects and Agents side by side. The menu-bar item is gone from Coming from Grove and the FAQ, which says how to open Projects instead. Glim's new moods, tokens renewed while sessions sit open, and the test count are brought up to date.
Both show Projects and Agents in the notch panel with the new pictures, name the session menu's Resume as, Copy to account and Share with all accounts, say how to open Projects now that there is no menu-bar item, and quit from the ⚙ menu. Glim's new moods, tokens renewed while sessions sit open, the test count and the screenshot command match the English README.
docs/workspaces.md says how to open Projects and Agents now that Brow has no item in the menu bar, and shows the panel's own screens in place of the Workspaces window: a project, New Workspace, a project's settings, Projects, Agents, Resume with options, Graph and Stats, and Projects while Grove.app runs. It adds that a session shows under one project, which folders are not suggested, that sessions a program started are not listed, and the one line for loose worktrees nobody works in. Troubleshooting says where Projects opens, architecture.md drops the menu-bar item, docs/brow.md shows the collapsed notch and the open panel, and the pictures nothing shows any more are deleted.
The English, Russian and Chinese pages say version 0.5.0 and link its release notes. Workspaces is the Projects and Agents sides of the notch panel rather than an item in the menu bar: the section shows the panel's own screens, a project with a workspace open and Resume with options with each account's limits, and gains two rows, what each session said last and who talks to whom. The session menu's actions take their new names, Resume as, Copy to account and Share with all accounts. The questions say how to open Projects, that Brow has no menu-bar item, and when the claude -p fallback runs. Tokens renewed while sessions sit open, Glim's new moods, and what Projects and Agents read are brought up to date, as are the structured data's screenshots and features.
Continue a Claude Code session on another account opens Projects from the notch and moves a session from its menu, with Resume as, Copy to account and Share with all accounts; Resume with options takes Terminal.app, a copy is resumed as its account from a terminal, and Settings › Accounts shows which accounts are linked. Run Claude Code across multiple repositories adds a project and a workspace from the panel and starts a session with New session. The accounts guide names the new actions. Pictures nothing shows any more go, and the sitemap dates every page 21 October.
Brow has no menu-bar item; the development build's own identifier keeps rebuilds away from what macOS keeps for the installed app, its permissions included.
Copy to account in place of Migrate to…, the New session form in place of the launch sheet, Projects and Agents among the parts of Brow, and no menu-bar item.
The panel on the right is 0.5.0's, rendered from the app's own views: its footer has share, the pin, refresh and the gear, and its bottom corners are continuous. The text and the cream icon with its shadow are as they were.
The hero, the calendar and the sign-in are rendered again from the app's own views, with the same story, timing and made-up accounts: the panel now has 0.5.0's footer (share, the pin, refresh, the gear) and its continuous bottom corners. As in 0.5.0, the click on a button pins the panel, so the pointer closes it with a click on the desktop, and Team's row reads "Anthropic rejected the token" with its key lit. Glim's film is drawn by 0.5.0's pet, which smiles in its sleep. New file names, so no cached copy of the old ones is shown.
The hero, calendar, sign-in and Glim loops on every page, their stills for reduced motion and the stills the structured data names, at the site's 1280 x 800, from the same renders as the README's. New file names, so no cached copy of the 0.4.0 ones is shown.
The collapsed strip with its 5-HOUR, GLIM and WEEKLY labels is rendered again from 0.5.0's views, with the same composition and numbers (54 % and 72 %): the strip's bottom corners are now continuous. A new file name, so no cached copy of the 0.4.0 one is shown.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Workspaces moves into the notch panel, next to the limits: Projects with each session's last exchange and what needs you, Agents with who talks to whom, and no menu-bar item. Glim gets two new moods, and Brow refreshes tokens again while Claude Code sessions sit open. The changelog has the details. Merged with a merge commit, like 0.4.0, so the history of each change stays readable.