Session sidebar: ⌘K search with wildcard/regex, and per-repo subtabs - #24
Merged
Conversation
The sidebar listed every repository as one flat TreeView. With more than
a handful of repos that became unreadable, and the global filter shortcut
(⌘F) collided with the conventional in-terminal find binding.
Search. The global "focus the sidebar filter" shortcut moves from ⌘F to
⌘K (ShortcutsOverlay relabelled "Session search"), freeing ⌘F for a
future terminal-find binding. The filter's text matcher is extracted into
SidebarQuery, which adds two shapes on top of the historical
case-insensitive substring: glob (`*`/`?`, other regex metacharacters
escaped) and regex (`/body/` or `re:body`, compiled
CASE_INSENSITIVE|DOTALL with find()). An unparseable regex body falls back
to a literal substring match of the body, never throwing -- a typo in the
filter must not blank the sidebar. RepositorySidebar compiles the matcher
once at the top of rebuildTree; matchesRepo/matchesNode/matchesPullRequest
and the PR-group narrower all consult it instead of a lowercased substring.
Subtabs. The flat all-repos TreeView is replaced by a wrapping FlowPane
strip of per-repository ToggleButtons above the TreeView, which now shows
only the selected repo's subtree. One repo is visible at a time; the
subtab titles wrap inside a bounded width (long repo names take as many
rows as they need) and the strip itself wraps across rows as the sidebar
narrows. A subtab is shown iff the repo name matches the text filter OR
any of its session/worktree rows do -- the same filter the old flat
treeview used, now deciding subtab visibility instead of expand-and-keep.
Within a shown repo, rows filter exactly as before (chips AND text, facets
OR within an axis).
The repo pane keeps everything the expandable row carried (sessions,
unopened worktrees, stale/locked buckets, the PULL REQUESTS group, the ⟳
rescan and the + new-session button); the repo row is now an
always-expanded pane header (caret and click-to-collapse removed, a
force-re-expand guard defeats keyboard ←). Per-repo collapse state
(collapsed/collapsedBeforeFilter/filterChangedSinceLastRebuild) is gone --
there is nothing to collapse. Selecting a subtab replaces the old
"repo-row expand" as the lazy PR-scan trigger, and refreshWorktrees's
collapsed-skip became a not-selected-skip (isSelectedRepo), so a repo
whose worktree list changes while nobody is looking at it is marked stale
and self-heals the moment its subtab is reselected. Switching the active
session to another repo auto-selects that repo's subtab so its subtree is
the one showing when the row is revealed.
The dedup FX test's "collapsed self-heals on expand" case is rewritten to
the subtab model ("deselected self-heals on reselect"), driving the
worktree rescan through the workspace seam (refreshWorktreesFor) since the
⟳ button lives on the repo row a deselected repo does not show.
Co-Authored-By: Claude <noreply@anthropic.com>
jbachorik
marked this pull request as ready for review
August 26, 2026 14:02
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.
The sidebar listed every repository as one flat TreeView. With more than a handful of repos that became unreadable, and the global filter shortcut (⌘F) collided with the conventional in-terminal find binding. This change restructures the sidebar around per-repository subtabs and upgrades the search shortcut and matcher.
Session search: ⌘K + wildcard/regex
The global "focus the sidebar filter" shortcut moves from ⌘F to ⌘K (ShortcutsOverlay relabelled "Session search"), freeing ⌘F for a future terminal-find binding.
The filter's text matcher is extracted into
SidebarQuery, which adds two shapes on top of the historical case-insensitive substring:*/?, other regex metacharacters escaped./body/orre:body, compiledCASE_INSENSITIVE|DOTALLwithfind().An unparseable regex body falls back to a literal substring match of the body, never throwing — a typo in the filter must not blank the sidebar.
RepositorySidebarcompiles the matcher once at the top ofrebuildTree;matchesRepo/matchesNode/matchesPullRequestand the PR-group narrower all consult it instead of a lowercased substring.Per-repo subtabs instead of a flat tree
The flat all-repos
TreeViewis replaced by a wrappingFlowPanestrip of per-repositoryToggleButtons above theTreeView, which now shows only the selected repo's subtree. One repo is visible at a time; the subtab titles wrap inside a bounded width (long repo names take as many rows as they need) and the strip itself wraps across rows as the sidebar narrows.A subtab is shown iff the repo name matches the text filter OR any of its session/worktree rows do — the same filter the old flat treeview used, now deciding subtab visibility instead of expand-and-keep. Within a shown repo, rows filter exactly as before (chips AND text, facets OR within an axis).
The repo pane keeps everything the expandable row carried (sessions, unopened worktrees, stale/locked buckets, the PULL REQUESTS group, the ⟳ rescan and the + new-session button); the repo row is now an always-expanded pane header (caret and click-to-collapse removed, a force-re-expand guard defeats keyboard ←). Per-repo collapse state (
collapsed/collapsedBeforeFilter/filterChangedSinceLastRebuild) is gone — there is nothing to collapse.Selecting a subtab replaces the old "repo-row expand" as the lazy PR-scan trigger, and
refreshWorktrees's collapsed-skip became a not-selected-skip (isSelectedRepo): a repo whose worktree list changes while nobody is looking at it is marked stale and self-heals the moment its subtab is reselected. Switching the active session to another repo auto-selects that repo's subtab so its subtree is the one showing when the row is revealed.Verification
./gradlew :app:test --tests "app.drydock.ui.*"— all green, including the rewritten dedup FX test.refreshWorktreesFor) since the ⟳ button lives on the repo row a deselected repo does not show.Out of scope
5 unrelated
git worktree addtimeouts inGitStatusServiceTest/WorkspaceMcpSessionContextTestreproduce on cleanmain(verified by stashing this branch); they are caused by the globalcore.hooksPathsecrets-scanner hook under parallel load, not by these changes.