You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The sidebar lists git worktrees that no longer exist on disk, and labels any detached-HEAD worktree with the literal string detached. Both come from the same screenshot but are two small gaps: the server does not drop stale registrations, and the app has no better label than a hardcoded word.
What was observed
A subagent had created a throwaway worktree in $TMPDIR at a detached HEAD. Its directory was deleted, but the .git/worktrees/<id> admin entry survived:
The sidebar showed it as a group named detached sitting next to feat/github-budget, both reporting the identical diff (+6927 -225) because they point at the same commit. The directory was already gone — ls on that path returned "No such file or directory".
Cause
1. Stale registrations are not filtered.listWorktrees in server/src/git.ts parses git worktree list --porcelain and handles the worktree, HEAD, branch and detached lines. It does not handle prunable, which git emits for exactly this case (a registration whose working tree is missing). Those entries are forwarded to the app as ordinary worktrees.
2. detached is a hardcoded fallback, and there is nothing better to fall back to. Four call sites do worktree.branch ?? 'detached':
The server's WorktreeEntry already carries head (the commit sha), but the app's Worktree model (app/lib/store/models.dart:501) drops it — so the UI has no sha available even though the server read one.
Suggested fix
Skip prunable entries in listWorktrees, or surface the flag so the app can filter/mark them. A worktree whose directory is gone is not a place you can start an agent.
Carry head through to the app's Worktree model and label a detached worktree with a short sha (51a86ed) instead of the word detached. That also disambiguates two detached worktrees, which currently render identically.
Consider whether temp/throwaway worktrees should appear as groups at all.
Notes
Worth deciding what a live detached worktree should show, not just a stale one — the sha label covers both.
git worktree prune clears the stale entry as a workaround, but the app should not depend on the user running it.
Summary
The sidebar lists git worktrees that no longer exist on disk, and labels any detached-HEAD worktree with the literal string
detached. Both come from the same screenshot but are two small gaps: the server does not drop stale registrations, and the app has no better label than a hardcoded word.What was observed
A subagent had created a throwaway worktree in
$TMPDIRat a detached HEAD. Its directory was deleted, but the.git/worktrees/<id>admin entry survived:The sidebar showed it as a group named
detachedsitting next tofeat/github-budget, both reporting the identical diff (+6927 -225) because they point at the same commit. The directory was already gone —lson that path returned "No such file or directory".Cause
1. Stale registrations are not filtered.
listWorktreesinserver/src/git.tsparsesgit worktree list --porcelainand handles theworktree,HEAD,branchanddetachedlines. It does not handleprunable, which git emits for exactly this case (a registration whose working tree is missing). Those entries are forwarded to the app as ordinary worktrees.2.
detachedis a hardcoded fallback, and there is nothing better to fall back to. Four call sites doworktree.branch ?? 'detached':app/lib/desktop/chat/desktop_sidebar.dart:487app/lib/ui/home/worktree_row.dart:26app/lib/desktop/chat/new_worktree_dialog.dart:473app/lib/desktop/chat/archived_sidebar_view.dart:231The server's
WorktreeEntryalready carrieshead(the commit sha), but the app'sWorktreemodel (app/lib/store/models.dart:501) drops it — so the UI has no sha available even though the server read one.Suggested fix
listWorktrees, or surface the flag so the app can filter/mark them. A worktree whose directory is gone is not a place you can start an agent.headthrough to the app'sWorktreemodel and label a detached worktree with a short sha (51a86ed) instead of the worddetached. That also disambiguates two detached worktrees, which currently render identically.Notes
git worktree pruneclears the stale entry as a workaround, but the app should not depend on the user running it.