Added
-
A tab is named after where the work is, not only after what is running there. The label reads
[N] <directory> › <branch> › <activity>, so fiveclaudetabs across three checkouts stop reading alike. Each part drops out when it says nothing worth the width: the directory when it is your home directory, the filesystem root, or the name of the workspace the tab is already in, since herdr shows that above the tabs.TAB_CONTEXT=0turns the whole half off, and every part keeps a budget of its own rather than sharing one total.A directory too long for
MAX_CONTEXT_LENis reduced rather than cut through the middle. Worktrees and branches are named the same way by the same people, sobugfix-proj-482-fix-rev-discrepancyreads asPROJ-482where a plain cut leavesbugfix-proj-, which identifies nothing. -
The branch the pane's repository has checked out, read from the files under
.gitand never by running git.git rev-parseis a process whereHEADis one open, and this runs per named tab on every herdr event and again on every shell prompt. The repository's own default branch is left out, read fromrefs/remotes/origin/HEADrather than from a list of names, so a team whose trunk isdevelopgets the same silence amainone does. A repository that records no default falls back toTRUNK_BRANCHES, because otherwise every tab of a local-only repo carriesmainalike.Worktrees and submodules are followed through their
gitdir:pointer to their own HEAD and throughcommondirto the shared refs. A rebase keeps the branch it set aside, so a tab does not take a new hash on every step; any other detached HEAD shows the short hash, which is where commits get lost. A branch that repeats the directory or the workspace is dropped, since a worktree named after its branch would otherwise say one thing three times.SHOW_BRANCH=0andMAX_BRANCH_LEN=0both leave branches out. -
A pane running
sshis named after the machine it reached,prod-01 › ssh. The directory it was launched from is local and the branch checked out there would read as the remote machine's, so both are dropped. The destination is parsed rather than taken as the first word afterssh, which is as often an option's value as a host: clustered short options, attached values, the url form, and bracketed IPv6 addresses all resolve, the user and the port are dropped, and a-osetting whose value is a command is refused outright rather than guessed at, because aProxyCommandparses as its own bastion. -
A coding agent that has not titled its terminal is named from its own session. Claude Code derives that title from what the user typed, so a session opened with a slash command and answered by the agent alone is never given one, and its tab read
claudefor as long as it ran. The transcript is read for the title the agent generated, or failing that the first prompt the user actually typed, which is what Claude Code's own session list shows for an untitled session.Only Claude Code is read, and only where herdr reports that pane's session, which
herdr integration install claudeis what sets up. Reads are bounded to the end of the file each answer needs.AGENT_TRANSCRIPT=0leaves the file unread, and a transcript that stops carrying these fields yields nothing, so the tab is named as it was before this existed.
Fixed
-
A numbered workspace goes on following its directory (#13). herdr names a workspace after
identity_cwd, its own tracked directory, and the firstworkspace renamefreezes that name for good: herdr keeps the directory current and never labels from it again. Numbering a workspace pinned it to whatever it was called when it opened, and no smaller rename would have helped, because there is no rename that leaves the derivation alive.The base now comes from
identity_cwd, read out of thesession.jsonthe collapse rules already read, and resolves to the repository the directory belongs to, or to the directory itself outside a repo. A pane moving around inside a project is not a rename; a pane that leaves takes the new name. Two caveats come with the file. The value is in no API response, and herdr saves it on a 5-second debounce, so acdlands on the label an event or two later rather than instantly. An older herdr without the field keeps the previous behavior.A workspace herdr has not written to
session.jsonyet, which is every new one for up to five seconds, reads its directory off its panes instead. Without that, the numbering rename lands before the file exists, the stale label reads as a name somebody typed, and the workspace opts out of tracking for good.A
cdstill emits no event the plugin subscribes to, so the new name lands on whatever event arrives next, the same way a sidebar collapse does.A workspace named by hand, or by another plugin, keeps its name and is only ever numbered, which is the promise a tab already gets. The plugin tracks a label that is herdr's own derivation or its own last write, and nothing else. Renaming a workspace back to the directory name hands tracking back, since
resettakes a tab and a workspace has no equivalent.