Repository navigation
Description
What problem are you trying to solve?
In the v2 sidebar, every project's main workspace row reads exactly local. With more than one project in the sidebar the rows are indistinguishable, and the one thing that actually differs between them — the branch each checkout is sitting on — is invisible.
Right now I have two projects open: one checkout is on main, the other on feat/app-platform. Both rows say local, and nothing on either row says which is which. Coming back to a checkout I left on a feature branch the day before, the sidebar gives me no signal at all.
v1 showed it: WorkspaceListItem computed showBranchSubtitle = isBranchWorkspace || … and rendered the branch in muted mono under the name. The v2 row dropped that line.
The data is already one property away from the JSX — decorateSidebarWorkspace() puts branch: workspace.branch on the decorated model, but the row renders {name || branch} and, for a main workspace, getV2WorkspaceDisplayName() always returns "local", so branch is never reached:
apps/desktop/src/renderer/utils/getV2WorkspaceDisplayName/getV2WorkspaceDisplayName.tsapps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/components/DashboardSidebarWorkspaceItem/components/DashboardSidebarExpandedWorkspaceRow/DashboardSidebarExpandedWorkspaceRow.tsx#L297apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/hooks/useDashboardSidebarData/buildDashboardSidebarProjects.ts
Proposed solution
Render the branch as a secondary line under local, the way v1 did.
Not as the name: the docstring on getV2WorkspaceDisplayName is right that a main workspace's stored name tracks the checked-out branch rather than a user-chosen label, so it shouldn't pose as one — keeping local as the title and the branch as a subtitle preserves that distinction. The row already has a second line for the agents / ports chips, so the branch could sit there in the same muted mono the v1 subtitle used.
Two lighter variants if a permanent line is too much:
- show it only when the checkout is not on the repository's default branch — that's the case where not knowing actually costs something;
- ship it behind an Experimental toggle, next to Workspace agents and Inline workspace ports.
Either way it needs no new query — branch is already on the decorated workspace object.
Workarounds you've tried
- Hover card — it does show
BRANCH, and it's good, but one row at a time and only on hover. It answers "what is this workspace?", not "which of my checkouts is on a feature branch?". - ⌘K lists workspaces with their branch, the header chip on the right shows the active one, and right-click → Copy Branch Name works.
- Renaming the row: not possible by design (
onRename: isMainWorkspace ? void 0 : startRename, and the storednameis ignored for main workspaces). - Moving the row into a section I could name myself: the Create section / Move to section submenu is gated on
!isLocalMainWorkspace.
Superset 1.22.0, macOS 26 (arm64).
Activity
github-actions commentedon Aug 16, 2026
This is a feature request rather than a bug, and the code confirms every claim in it. Here's what I found.
Summary
The v2 sidebar renders every local main workspace row with the literal text
local, so with two or more projects open the rows carry no information about which branch each checkout is sitting on. The branch data is present on the decorated model the row already receives — it's just never rendered, because the row prints{name || branch}andnameis always the non-empty string"local"for main workspaces. v1'sWorkspaceListItemrendered the branch as a muted mono subtitle; the v2 row has no equivalent.Affected code
The row title, which short-circuits on a non-empty
name:apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/components/DashboardSidebarWorkspaceItem/components/DashboardSidebarExpandedWorkspaceRow/DashboardSidebarExpandedWorkspaceRow.tsx:297—{name || branch}inside the title<span>;branchis destructured at line 98 and otherwise unused in the expanded row.The name source:
apps/desktop/src/renderer/utils/getV2WorkspaceDisplayName/getV2WorkspaceDisplayName.ts:15—if (workspace.type === "main") return "local";. Locked in bygetV2WorkspaceDisplayName.test.ts:5-13("always displays main workspaces as 'local'").The data plumbing, which already carries the branch through:
.../hooks/useDashboardSidebarData/buildDashboardSidebarProjects.ts:91-92—decorateSidebarWorkspacesetsname: getV2WorkspaceDisplayName(workspace)andbranch: workspace.branchside by side. Same decorator feeds project groups, the Pinned section (buildDashboardSidebarPinnedWorkspaces), and Sessions, so anything added to the expanded row shows up in all three.v1, for reference:
apps/desktop/src/renderer/screens/main/components/WorkspaceSidebar/WorkspaceListItem/WorkspaceListItem.tsx:259—const showBranchSubtitle = isBranchWorkspace || (!!name && name !== branch);and:436-442, rendering<span className="text-muted-foreground/60 truncate font-mono leading-tight">{branch}</span>. Note lines 309 and 319: enabling the subtitle also switched the row's vertical padding and icon alignment.The workarounds are gated exactly as described:
onRename={isMainWorkspace ? undefined : startRename}(DashboardSidebarWorkspaceItem.tsx:252and:344), the section submenu behind{!isPinned && !isLocalMainWorkspace && projectId !== null && (…)}(DashboardSidebarWorkspaceContextMenu.tsx:193), and the hover card'sBranchblock atDashboardSidebarWorkspaceHoverCardContent.tsx:64-80.Two things worth confirming before implementing
The branch value is live, not stale. I checked this because a subtitle sourced from a stale column would be worse than nothing.
packages/host-service/src/runtime/pull-requests/pull-requests.ts:529-582(syncWorkspaceRow) reads the real HEAD from the worktree on GitWatcher events and writesworkspaces.branchback; it skips only session (projectId === null) and archived rows, so local main workspaces are covered. A branch subtitle should track checkouts made in a terminal.The "only when off the default branch" variant does need new plumbing, contrary to the "needs no new query" note — that applies to the always-on variant only. The sidebar's project identity comes from the host fan-out
project.list, and neitherHostProjectRow(apps/desktop/src/renderer/hooks/host-projects/useHostProjects/useHostProjects.utils.ts:6-20) nor the procedure that fills it (packages/host-service/src/trpc/router/project/project.ts:65-83) returns a default branch, even thoughprojects.defaultBranchexists inpackages/local-db/src/schema/schema.ts:46.SidebarProjectInputwould need the field too (buildDashboardSidebarProjects.ts:14-25). Resolving it live per project viaresolveDefaultBranchName(packages/host-service/src/runtime/git/refs.ts:207) is the other option. The always-on and Experimental-toggle variants need no new data.Fix direction
The narrowest change that matches existing precedent:
getV2WorkspaceDisplayName— e.g.getV2WorkspaceBranchSubtitle({ type, name, branch })returningbranchwhentype === "main",nullwhentype === "session", and for worktreesbranchonly when it differs from the display name. That last guard matters:getV2WorkspaceDisplayNamealready falls back tobranchfor unnamed worktrees, so an unguarded subtitle would print the same string twice. Both other v2 surfaces already guard exactly this way —V2WorkspaceTitle.tsx:17(rawBranch === name ? null : rawBranch) andV2WorkspaceRow.tsx:219-221(case-insensitive compare, plus atype !== "session"check).DashboardSidebarExpandedWorkspaceRow.tsx, styled like v1's (truncate font-mono text-[11px] leading-tight text-muted-foreground/60).Two layout details to watch in step 2. The title cell is a
grid-cols-[minmax(0,1fr)_auto] items-centergrid (line 277) whose right-hand cell is pinnedcol-start-2 row-start-1(line 302) — a second line in column 1 will want that cell to span both rows or self-center, or the diff stats and hover buttons will ride up against the title. And the chips strip below (DashboardSidebarWorkspaceChips) early-returnsnullwhen there are no agents/ports (line 37-39) and sits outside the clickable row div (line 390-396), so reusing it as the branch line means both relaxing that early return and accepting its fixedh-7; putting the subtitle inside the title column keeps the two independent. Itspl-[42px]/pl-[50px]values (line 50) are the alignment reference if you want the branch to line up with the title.Reproduction
git checkout -b feat/app-platformin one of the two checkouts; leave the other onmain.local, with the branch visible only on hover, in ⌘K, or in the top-bar chip for the active workspace.For a regression test, the renderer has essentially no component-test infrastructure (one
@testing-library/reactfile,Redirect.test.tsx), so the idiomatic coverage is a pure-function test — extendgetV2WorkspaceDisplayName.test.tsfor the new helper:buildDashboardSidebarProjects.test.tsis the place for a companion assertion if the subtitle ends up precomputed on the decorated model instead of derived in the row.svenpeeters commentedon Oct 27, 2026
Most of the original problem ("every main row reads
local") went away with #7485: local workspaces now have names that users pick. But a named local workspace still does not show which branch the shared checkout is on.I'd like to pick this up. My approach: show the branch as a muted mono suffix after the name on
type: "local"rows. The suffix is hidden when the branch is the same as the name, and the row stays on one line. Worktree and session rows do not change. I have a working version with before/after screenshots and can open a PR. Does this approach work for you?