Releases: crafts69guy/herdr-switchboard
Release list
v3.0.0
Added
- A line-coverage gate.
bash bin/coverage.shreports per-file coverage and fails under 90%,
and CI enforces it on every pull request. It is a separate job frombin/check.sh, which stays
fast. Coverage went from 78.5% to 90.1%, and closing that gap found and pinned several behaviours
that were previously untested.
Fixed
- Concurrent panes no longer lose recency or archive state. Recording an open and archiving a
saved review each read their file, changed it, and wrote the whole thing back as separate steps,
so two panes acting at the same moment silently erased each other's change. Both are now a single
locked transaction, as starring already was. Every durable file also gets a unique temporary
sibling instead of one fixed name shared by every writer, which could leave a truncated file
behind. Settings and zen chrome gain the same atomic replace while keeping their existing
permissions.
Changed
-
One prefix concept, everywhere. Which prefix a key wore used to depend on where it grew up:
ctrl-sstarred a command but sent a repo to an agent,alt-ssorted in Projects but opened
Settings in the Central Menu,alt-uupdated the plugin in Projects and used a Node version in
the fnm manager, opening a workspace wasalt-where /ctrl-wthere / barewin Normal, and
the changelog answered to three different letters. Now the prefix names the kind of work, and
never the mode you are in:ctrl-<key>acts on the selected row — open it, update it, remove it, copy it, send it,
star it.alt-<key>changes the view or the app — preview, sort, clone, changelog, settings, plugin
update. It is also the heavier form of actrlverb on the same letter, such as Ports'
ctrl-xTERM andalt-xKILL.enterruns the row's primary action, withctrl-enter/alt-enteras its variants.
Every one of those chords now means the same thing in both Projects modes and on every
picker. Normal mode adds bare aliases —tvowp— always on the same letter as the
chord they shorten, and motion keeps the idiom of its mode (readline while typing, Vim while
navigating).The
spaceleader is gone. Space can only be a leader in Normal — while typing it is a
character you meant — so every verb living there was forced to change prefix with the mode, which
was the inconsistency itself.space u/space x/space c/space l/space ,/
space Uare now simplyctrl-r/ctrl-x/alt-l/alt-h/alt-,/alt-u, in both
modes.What moved, in full: open in a tab
ctrl-t→ctrl-e(Projects and AI Agents), because
herdr consumes its prefix before a pane sees the key: a binding that is somebody's prefix never
arrives at all, andctrl-tis the usual prefix for anyone carrying tmux muscle memory while
ctrl-bis herdr's own default. The open group avoids both, and nothing here may bindctrl-b
any more. Normal's bare alias follows the letter, so it ise. Then: starctrl-b→ctrl-s; send to an agentctrl-s→ctrl-a
(Projects and the Git saved-review lists); open in a workspacealt-w→ctrl-w(Projects
and AI Agents; Ports already used it); clonealt-enter→alt-l; changelogalt-c→
alt-h; delete wordctrl-w→alt-backspace, which also revives it in the Ports picker
wherectrl-whad silently killed it; and in Node Versions,alt-uuse →ctrl-enter,
alt-iinstall →alt-enter,alt-ddefault →ctrl-d,alt-xuninstall →ctrl-x.
Commands, Zen, the Git menu and the Central Menu are unchanged.Old habits are a config block away — see Remapping in
docs/keybindings.md. A Projects
override now binds into both modes at once, so it cannot reintroduce the split, and the footer
and?cheatsheet render whatever you bind. -
The Central Menu and Node Versions can be rebound. They were the only two pickers with no
[keys.*]table, so their keys were the ones nobody could move.[keys.menu]and[keys.fnm]
now work like every other picker's. -
The empty Starred tab in Commands names the key you actually have. It printed a fixed
ctrl-seven after[keys.commands] starwas remapped, sending you to a key that no longer
starred anything. -
A shift bit your terminal adds no longer loses the action. Projects weighed only ctrl and alt
when resolving a key; every other picker compared the modifier bits exactly. So one press had two
answers depending on which surface read it —shift-enterran the selected row in Projects and
did nothing in Commands, Ports, Agents, Zen, the Menu or Node Versions, and a chord arriving with
a stray shift bit missed itsctrl-action outright. Both halves now decide the same way. -
A picker action that collides with a reserved chord is now caught at build time. The shared
picker answersalt-,,alt-j,alt-k,tabandshift-tabbefore consulting a picker's own
actions, so an action declared on one of those was silently swallowed — the way Ports'ctrl-w
had quietly killed delete-word for that picker alone. Those chords are one table now, and a test
every picker runs refuses an action that claims one, takesctrl-c/ctrl-u, uses a bare letter
(which would make that character untypeable), prints a cap that is not the key it listens for, or
binds a shared action to a chord it does not carry elsewhere. -
A modified chord can no longer trigger a Git menu mnemonic. The menu matched
awhether or
not ctrl was held, soctrl-apressed one view too early would have started an all-files review
— a minutes-long read — rather than doing nothing. -
Projects and the Commands, Ports, Agents and Menu pickers scroll and filter faster. Every
visible and off-screen row was rebuilt from scratch on each frame; rows now reuse the text they
already have. Star lookups, tab counts, the name ordering, and field filters no longer redo work
per keystroke. A burst of wheel or held-key input is drawn once instead of once per event. -
Projects opens faster on machines with many repositories. Repositories with no linked
worktrees are recognised from disk instead of costing agitprocess each, the two Herdr
catalogue queries run at the same time, and a repository Inspector gathers its branch, status,
last commit, and file tree concurrently. -
Pickers with nothing loading no longer wake twenty times a second. Commands, Agents, the
Menu, and the Zen picker now idle until you press something, matching Projects and Git. -
Released binaries are built for speed rather than build time. Published archives now use a
fully optimised profile; building from a linked checkout stays as quick as it was.
v2.1.0
Changed
-
Projects opens without a blank flash while its catalogue loads. The final dashboard appears
immediately withStanding by…; Settings Apply keeps the old rows visible underRefreshing….
Repository discovery now shares one ghq snapshot with up to four concurrent worktree probes. -
Cancelling repository removal now preserves its local state. An aborted confirmation leaves
recency and stars untouched, and a failed delete is reported instead of being treated as success. -
The central menu is roomier and standalone Settings has one frame. The menu now opens at
a fitted112x28, with its complete action bar balanced across two rows separated by a gap.
Standalone Settings relies on the
frame Herdr already draws, while the in-Projects Settings overlay keeps its floating card.
Added
-
Projects can keep starred repos and worktrees. Press
ctrl-bin Insert mode orspace bin
Normal mode to star the selection, then open the persistent★ Starredgroup by keyboard or
mouse. Compact group labels keep that tab clickable in medium panes; concurrent panes serialize
changes so completed stars are not lost. Stars stay private on disk, retain every normal project
action, and can be selected asprojects.default_tab. -
Commands can keep a local starred list. Press
ctrl-sto star or unstar a command, then use
the History and Starred tabs from the keyboard or mouse. Starred rows carry a peach★that
remains visible on the selected row, keep every existing command action, persist privately on
disk, and stay available beyond the ordinary history limit. -
Node Versions is a full fnm manager. Open it from the Switchboard menu to search installed
and remote Node.js versions, use one in the originating pane, install it, make it the default,
refresh the catalogue, or uninstall it after typing the exact version to confirm. -
Projects can activate repository Node versions through fnm. Enable
[fnm].enabledto show
.nvmrc,.node-version, orpackage.jsonNode requirements in the Inspector and carry an
already-installed match into new workspaces, tabs, and splits. Missing versions never install
themselves or block the open; Switchboard warns and keeps the inherited Node environment. -
Navigator paths can be copied or handed to a running agent. Select an Agent, Repo, or
Worktree in Projects, then pressctrl-yto copy its absolute path orctrl-sto share that
path as context. Agent delivery uses the origin agent when it shares the worktree, otherwise
offers matching promptable agents and falls back to all running agents; Workspace rows remain
disabled because they do not have one unambiguous path. -
Saved tuicr reviews can be archived without deleting review data. Press
ctrl-din the Git
menu's saved-review list to hide a session, openRarchived reviews to find it, and press
ctrl-dagain to restore it. Reading comments and sending them to an agent remain available in
both lists. -
Saved tuicr reviews can be handed directly to a running agent. Press
ctrl-sin the Git
menu's saved-review list: Switchboard uses the origin agent when it still shares the worktree,
otherwise offers matching agents and then all available agents. The handoff preserves tuicr's
structured comment IDs and locations, closes back to the agent on success, and stays retryable
when delivery fails.
Fixed
- New workspaces, tabs, and splits no longer print Switchboard's fnm activation command around the
shell greeting. Matching Node versions are supplied only through the target's launch environment.
v2.0.0
Changed
-
Switchboard backgrounds now follow one explicit policy. Set
common.transparency = "transparent"(the default) to show the terminal through Projects,
mode pickers, Git, Usage, Settings, Changelog, the review splash, and their nested cards; set it
to"opaque"to fill every surface and gutter withpanel_bg. The old
auto/enabled/disabledvalues are removed so parent panes and floating cards cannot silently
choose different behavior. -
Switchboard is now Vim-first and adapts as a persistent dashboard. Projects opens in Normal
mode by default;ior/enters filtering, andcommon.keymode = "insert"restores the old
type-first start. Wide panes show a context rail beside the navigator and inspector, medium panes
keep the navigator/inspector split, and compact panes reserve the available space for navigation. -
Every terminal surface now runs through one lifecycle host. Projects, mode pickers, Git,
Usage, Changelog, and Settings share terminal claiming, mouse capture, polling, redraw, and
guaranteed teardown. Keybinding overrides also use the same chord parser everywhere, so accepted
syntax and displayed key caps cannot drift between pickers. -
Usage donuts now separate spent quota from what remains. The used arc and its percentage use
the theme's semantic red, while the available arc uses semantic green. Loading and unavailable
cards remain muted, and the per-window bars keep their existing provider severity and configured
warning thresholds.
Fixed
- The local-build cat is centred in the real plugin pane. Bootstrap now reads the Herdr PTY
size directly instead of falling back to terminfo's 80x24 dimensions, and its vertical padding
uses terminal rows rather than spaces on the first line.
v1.3.0
Added
-
A
renewsrow on every Usage card. A window reset says when you may work again; a renewal
says when the plan is charged and its allowance starts over — the question that decides whether
pacing is worth it at all. Codex states it, so the row readsrenews 13 Sep · in 25d, taken
from the same~/.codex/auth.jsonID token the account line already decodes: no extra request,
no extra file, one read for both labels.Anthropic states it nowhere readable — not in the usage endpoint, not in
~/.claude.json— so
the Claude card saysunknowninstead of counting a month from the day the subscription was
created. A date already in the past reads asunknowntoo: the Codex claim only refreshes while
Codex runs, and a stale date under a heading that says renews reads as one that is coming. -
The mouse reaches every surface, not just the switcher. The pointer worked in the projects
picker and nowhere else:--usageand--changelognever turned mouse reporting on at all,
--settingsread only keys, the Git pane took the wheel and ignored every click, and the mode
pickers moved the selection without ever running it. Now the wheel scrolls the changelog, moves
the selection in the Git menu and its sub-lists, walks the settings form, and scrolls a mode
picker's preview card when the pointer is over it — and a click reaches rows, tabs and
command-bar pills on all of them.One rule everywhere, because terminals report no double-click: a click selects, a click on the
row already selected does what Enter would, and a click on a pill does what the key printed on
its cap does. So no stray click ever launches a review or writes a setting, and a pill's label
cannot drift from its behaviour — the label is the behaviour. Each zone is still measured by
the loop that draws the thing it points at; what is shared is the lookup, not the measurement.
Clicking outside the settings card now discards the draft asescdoes, instead of closing over
a staged edit and leaving it alive.
Changed
-
A reset that is not today now names the day it falls on. The status line reads
resets 08:53 Wed 19 Augand the window's own bar row reads1d 12h · 19 Aug. A weekday is
unambiguous inside a seven-day window but it is not legible: mappingThuonto a calendar six
days out is arithmetic you had to do in your head, and the weekly bucket is exactly the one that
lands far enough away to need it.A window rolling over later today stays as short as it was —
resets 15:59 Thu,2h 40m— so
the presence of a date is itself the signal that the rollover is not today. The countdown keeps
its place beside it: it is the only "how long do I wait" figure a window that missed the donut
gets. -
More air between the Usage cards. The pane paints no background and draws no divider
between providers, so whitespace is the only thing separating them — and with the columns
butted together the two cards read as one wide table of rows rather than two independent
answers. They now get a gutter, which yields back to one column on a pane too narrow to seat
the cards' own rows. The columns also fill the pane exactly, instead of100 / nleaving the
remainder dark on the right. -
The Git menu asks before an all-files review of a large repo.
arunstuicr -A, which
reads every tracked file — and because the pane deliberately keeps the screen, draws one static
splash andexecs the review over itself, a checkout big enough to keep tuicr busy for minutes
is indistinguishable from a hang: no frame, no spinner, nothing to cancel. On a 7,600-file tree
it was two solid minutes of a cat that never moved.The row now counts the tree first — one
git ls-files, taken on activation rather than on open,
so the menu's first frame still costs nothing — and overgit.all_files_warn(1,500 by default)
it spends a screen saying what it found:6,699 files tracked in this repo,tuicr reads every one of them before its first frame. Enter opens it anyway, esc goes back to the menu. Under the
threshold nothing changed, andall_files_warn = 0never asks. A count git refuses to give
opens the review rather than standing in front of it: a broken number must not become a locked
door. -
The Git pane stopped painting itself opaque. Its menu card, its sub-list card and that
list's search box each filled themselves withpanel_bgand drew their borders in the accent.
All three were hand-rolledBlocks — exactly the drifttui::boxedexists to prevent — and the
result was one pane that looked like a solid dialog sitting next to five that the terminal shows
through. They go through the helper now: borders recede inoverlay0, captions keep
title_color, and nothing paints a fill, so a translucent terminal stays translucent under the
Git pane too.panel_bgkeeps the places it belongs: as ink on key caps and pills, and as the fill of the
changelog, settings and cheatsheet popups, which float over the live picker and genuinely have
to occlude it. The switcher's own list panel was hand-rolling aBlockas well — its caption
slot holds the tab strip rather than a word — sotuigrewframed, the captionless half of
boxed, and both panels build from it. Three render tests now assert the absence of a fill,
because the one that existed only covered the mode pickers.
v1.2.0
Added
-
A conflicts row in the Git menu.
xlists every pathgit statusreports as unmerged,
each with what actually happened to it —both modified,deleted by them,both added—
and opens the one you pick in tuicr. It is always offered: with no merge in progress the list
says so, rather than the row appearing and disappearing under the mnemonic.The pick opens with
tuicr --file, which shows the file itself with its conflict markers
intact, not a diff. That is on purpose:git diffon an unmerged path emits a combined
diff (diff --cc), which is not the two-sided shape a review tool reads. This is the row
retired in 0.10.0 for exactly that reason, back now that the sub-list picker the pull-request
and saved-review rows already use gives it a way to name one file at a time.
v1.1.0
Added
-
A Usage popup. Bind
switchboard.usageor open it from the central menu to see how much of
each AI subscription is spent and when it resets. Each agent gets a donut for the window closest
to running out, a bar for every other window, and the numbers that give the percentage its
context: what the session spent, how much of the context window the last turn used, whether
credits are on. Every card dates itself —as of 12m ago— because Codex reports whatever its
last session wrote, and a two-day-old percentage read as current is the mistake this popup exists
to prevent. Resets are given both ways,in 1d 12handresets 08:53 Wed.Codex reads the exact numbers OpenAI returns, straight out of its own session log, with no
network at all. Claude Code publishes nothing to disk, so its card asks the same endpoint the
in-session/usagecommand asks, using the OAuth token Claude Code already stores; that request
runs on a worker with a timeout, so the popup opens instantly with Codex on screen and fills
Claude in when it lands. Claude also grades its own limits, and the card colours them the way the
provider grades them rather than by a threshold of ours; anything ungraded falls back to
usage.warn_percentandusage.alert_percent.Each card names the account it is reporting on — the two agents are routinely signed in as two
different people, and a quota means little without knowing whose it is. Codex's address comes
from the ID token it stores, Claude's from the profile Claude Code caches, and that profile is
also where the Claude card gets its plan, since the usage endpoint names none.Press
rto read both again. Any agent that cannot be read says why on its own card and leaves
the other one alone. Choose the providers and thresholds under[usage], or from the settings
overlay. -
Zen can hide Herdr's own chrome. The new
zen.chromesetting (offby default, or
panes/full) suppresses the pane borders and gaps, the scrollbar column, the tab row and
the sidebar for the length of a zen session. None of those have a per-pane switch, so anything
butoffrewrites the matching[ui]keys in Herdr's ownconfig.tomland reloads Herdr,
then restores them exactly on the way out: comments and unmanaged keys survive, keys already at
the wanted value are left alone, and your untouched config is copied to
$XDG_STATE_HOME/herdr-switchboard/herdr-config.backup.tomlbefore the first write. If a
restore fails or Herdr is killed mid-session,herdr-switchboard zen chrome-restoreputs it
back. Herdr only appliessidebar_start_collapsedon its next launch, sofullmay leave the
sidebar in place — zen measures that and says so rather than failing silently. -
Zen mode.
switchboard.zen-togglegives the current pane the screen: it moves to a tab of
its own, centred atzen.width(default 70%) between two dimmed gutters, and toggling again
puts it back where it was.switchboard.zenopens a picker to zen any pane instead of the
current one. The gutters are dimmed by painting over them through Herdr's graphics API, which
needs[experimental] kitty_graphics = true; without it the gutters are simply blank. Tune it
withzen.width,zen.scrim, andzen.scrim_color, or from the settings overlay. Neighbouring
panes are never touched — only the zen'd pane moves, and its running process survives the move.
Leaving zen restores a two-pane tab exactly; a more deeply nested tab gets every pane back beside
its former neighbour, with a notification when the split nesting could not be reproduced. -
An AI Agents picker. Bind
switchboard.agentsor open it from the central menu to list the
AI integrations installed in Herdr.enterstarts the selected AI in the origin pane,ctrl-t
starts it in a new tab, andalt-wstarts it in a new workspace; failed starts clean up any
tab or workspace Switchboard created. The focused picker opens as a compact centered popup rather
than a mostly empty full-screen overlay. This requires Herdr 0.8.0 or newer.
Changed
- The README is now a concise entry point instead of a monolithic reference. Quick start,
feature discovery, core actions, and namespaced configuration stay on the front page; detailed
keybindings, safety behaviour, Zen, Git, configuration, and architecture now live in focused
guides underdocs/. Stale pre-1.0 wording, flat configuration names, dependency scope, popup
placement, update-version examples, and contributor checks were corrected at the same time.
Fixed
- Opening AI Agents or another popup from the Central Menu now waits for the menu popup to close,
so Herdr no longer rejects the replacement aspopup already open. - The AI Agents picker now closes immediately after a selection while startup readiness is checked
in the background; failed starts still clean up new tabs or workspaces and report the error with
a notification. - Linked development checkouts now rebuild their release binary when Rust sources or Cargo metadata
are newer, instead of silently running an old same-version binary after source changes.
v1.0.0
Breaking
- Removed the old
ghqconfiguration/state migration and flat-config compatibility path;
Switchboard now reads only namespaced configuration from its own plugin directory.
Changed
- The Menu, Commands, and Ports pickers now render in the Projects picker's visual
language: borders recede inoverlay0instead of shouting in the mode accent, every
panel caption usestitle_color, and the selected row is a subtlesurface1bar
rather than a full-width inverted accent block. - Those three panes no longer repeat their name: herdr already draws the pane frame and
its title, so the pane title is now a single icon (as Projects and Git already were)
and the mode name moved onto the list panel. - All three panels are transparent, so the terminal shows through consistently. The
Search and Preview panels previously painted an opaquepanel_bgwhile the list did
not, which read as two different themes inside one pane. - The Preview panel gained the Projects picker's
⌥jk n/totalscroll indicator, shown
only when the card runs past the fold, and its scroll now clamps to the content. - Picker rows are laid out against the panel's real width. A row longer than the panel
now ends in an ellipsis instead of being cut mid-word wherever the border fell, and a
row's trailing tag sits in its own right-hand gutter instead of a column that went
ragged as soon as one entry ran long. - Commands stopped printing
shellon every row — it was the source of all but a handful
of entries. The badge now appears only for a preset or a Switchboard command, and the
right-hand gutter carries how long ago the command was last used (2h,3d), which is
what the list is sorted by. - Commands draws each row's leading word — the program — in the entry's colour, bold, so
a wall of history has something to scan down, and gives the list 58% of the body rather
than 42, since its rows are long and its preview card is short. - The Commands preview reports
last usedas a relative age plus a readable UTC date
instead of a raw unix timestamp, and labels the selection count asn ×.
v0.11.0
Breaking
- Renamed the package, binary, plugin id, release assets, runtime environment variables, and state
directory from herdr-ghq /ghqto herdr-switchboard /switchboard. Existing flat
configuration and state are migrated once, validated, and then removed; no legacy alias or backup
is retained. Changeghq.menubindings toswitchboard.projects.
Added
- Added the searchable
switchboard.menucentral menu and direct actions
switchboard.projects,switchboard.commands,switchboard.ports, and
switchboard.settings, so every picker can have its own Herdr key binding. - Added a Commands picker that merges shell history, presets, and Switchboard selection history;
supports quoted/negated field filters; excludes likely secrets; and can fill, run, copy, or forget
an exact command. Multiline execution requires typed confirmation. - Added a native Ports picker for live TCP listeners with process metadata, automatic refresh,
URL/copy/workspace actions, and identity-checked TERM/KILL confirmations. - Added four package Settings tabs (
Common / Projects / Commands / Ports) and semantic Herdr
notifications for command-delivery and listener-signal outcomes.
Changed
- Configuration is typed, namespaced TOML. Commands and Ports share a colorful picker engine with
stable selection, mode-specific remaps, inline filter diagnostics, mouse support, preview, and a
live command bar.
v0.10.0
This release replaces hunk with tuicr and moves the git
menu out of the switcher into a pane of its own. It is a breaking change: keys move, two menu rows
are gone, and tuicr is now a hard requirement (brew install tuicr, ≥ 0.20.0). Themes for it come
from hue-theme — install that first, or reviews open in
tuicr's own colours.
Removed
⌥gno longer opens a git menu in the switcher. The menu is a herdr pane now, reached only by
theghq.gitaction (bind it toprefix+g). What you lose with it: reviewing an arbitrary repo
you fuzzy-jumped to.cdthere (^o) and pressprefix+g. Two entry points would have drifted
apart, and only one of them could be the fast one.sreview staged — tuicr has no staged-only flag,d(tuicr -w) already covers staged and
unstaged together, and lazygit is the better pre-commit surface.xresolve conflicts — tuicr's-ptakes a single path prefix, sohunk diff -- <files>
has no translation.- The commit history browser — the scrolling, fuzzy-filterable
git loglist behindh. tuicr
has a commit panel of its own, sohnow opens that directly. - The startup animation. The switcher no longer animates a cat while it loads.
hunkis no longer used or configured, and the plugin writes nothing into tuicr's config.
Added
- A dedicated git menu pane.
prefix+gopens it straight onto the repo the pane is sitting in;
it loads no agents, no workspaces, no repository index, and no preview on the way. Picking a row
takes over that pane, and quitting the review returns you to where you started. a— review all files (tuicr -A).p— review a pull request:gh pr listin a fuzzy-filterable list, thentuicr pr <n>. The
row is hidden whenghis not installed.r— saved reviews: the sessions fromtuicr review list, with their comment counts. Note
this reads comments only — tuicr's TUI cannot reopen a session, so there is no way back into a
half-finished review yet.GHQ_TRACE=1writes tab-separated timings to$XDG_STATE_HOME/herdr-ghq/trace.log(or
$GHQ_TRACE_FILE) — first list, keystroke-to-frame, and preview render, each measured
separately. Never to stdout or stderr. See the README.
Changed
- The switcher opens about 10× sooner — roughly 35 ms to the first list where it used to be
430 ms. Almost all of that was the animation's own 420 ms minimum-visible floor, not the work: the
sources are now read synchronously before the terminal is claimed, so the first thing painted is
the list. A machine with thousands of repositories will see a blank pane for slightly longer
before it appears. - Reviews open in
tuicr, nothunk:d→tuicr -w,b→tuicr -r <base>.. -w,
h→tuicr. Every launch passes--no-update-check. - The preview card is about twice as fast — roughly 50 ms on average where it used to take
90 ms, and 65 ms at the tail where it used to reach 214 ms. The branch now comes from reading
.git/HEADrather than spawninggit symbolic-ref, and the dirty check no longer walks untracked
files. Behaviour change: a repository whose only changes are untracked files now reads as
clean. - The git menu is sized to fit its command bar, so a short menu no longer clips
esc closeto
esc clo, and every row carries an icon.
Fixed
- Enter on an agent now actually switches to it, and the agent preview loads again. herdr keys
agent focus/agent geton the pane id, but the switcher was passing the terminal id, so every
agent focus failed silently (agent_not_found) — the picker closed and left you on the current
agent — and the preview card came up empty. Agents now carry their pane id as the target. - Opening the git menu no longer prints a stray commit SHA onto the screen beneath the card.
Base-branch detection rangit rev-parse --verifythrough the terminal-inheritingstatuspath,
andrev-parseechoes the resolved SHA on success; it now captures the output instead. - The Kitty/herdr graphics startup splash (the animated GIF cat) is gone, along with the
[experimental].kitty_graphicsdependency. herdr 0.7.5 changed its socket API to serve one
request per connection and close it on reply, which stranded the image on screen.
v0.9.0
Added
- An animated typing cat now appears as soon as the switcher opens: compatible
Kitty/Ghostty/WezTerm panes use the embeddedcat-typing.gifframes when Herdr's experimental
Kitty graphics proxy is enabled, while small or unsupported panes automatically keep the
theme-coloured pixel-art fallback. Both paths preserve the terminal's transparent background;
the image is cleaned up before picker content appears and
its first frame is always shown for a 420 ms minimum, making 2–3 animation steps visible even
when loading finishes immediately. Agents, workspaces, repositories, and linked worktrees
load in the background. Inside Herdr, frames use its acknowledged pane-graphics API so a
rejected image immediately reveals the pixel-art fallback instead of leaving an empty splash;
direct terminal launches retain standard Kitty commands. Managed
installs fetch a checksummed native binary for macOS/Linux on arm64/x86_64, so first open no
longer waits on Cargo; offline and linked checkouts still fall back to a local build, with
the same cat keeping the pane responsive.escorctrl-ccancels either loading stage. - Launching a
⌥greview now shows the same typing cat while it opens. A hunk review used to
hand the pane a frozen screen whilehunk diffwalked a large repository; the review launcher
now plays a short branded pre-roll that animates the cat (Kitty frames or the pixel-art fallback)
while it warms the exact diff hunk is about to read, so the review opens onto the splash instead
of a stall and hunk itself starts faster off the warmed cache. The cat stays up until the warm-up
finishes (a 420 ms floor keeps it visible on an already-warm repo, a 5 s cap keeps a pathological
one from stalling);esc,enter, orctrl-cskips straight to the tool. The pre-roll hands off
without a blank flash: it freezes a static “Opening review…” frame and leaves the screen in place
for hunk to paint straight over, rather than tearing the terminal down between the two. Only hunk
reviews get it —lazygitand custommenu.confcommands bring their own startup. - A Worktrees tab now lists linked Git worktrees across every ghq repository without
duplicating the main checkout already shown under Repos. Worktrees open in a workspace,
tab, split, or pane and use the built-in Git menu at their own path; repo-only update and
remove actions stay hidden.include_worktreescontrols the source and defaults totrue. default_tabchooses the active startup group (all,agents,workspaces,repos, or
worktrees). Applying it in the settings overlay switches immediately; an empty, disabled,
or unrecognised group safely falls back to All.
Changed
- The Workspaces preview is now a dashboard. Instead of a bare tab list, it shows a
pane/agent summary with a colour-coded status breakdown, the running agents with their
status and current task, and the distinct repositories their panes sit in with each one's
branch and a dirty marker — read frompane listso it reflects what the workspace is
actually running.