Skip to content

feat(worktrees): pick up worktrees a repository already has - #919

Merged
badcuban merged 1 commit into
mainfrom
feat/existing-worktree-pickup
Nov 14, 2026
Merged

badcuban merged 1 commit into
mainfrom
feat/existing-worktree-pickup

Conversation

@badcuban

Copy link
Copy Markdown
Collaborator

The problem

A repository often already has worktrees Threadlines did not make: git worktree add by hand, or another app that keeps one per task. They only showed in the branch picker, each with a small "worktree" label. There was no way to carry on in them as threads, and nothing stopped Threadlines from treating those folders as its own.

What this adds

  • Right after adding the repository, the new-thread screen lists its worktrees under the message box with a checkbox each. Ones with nothing left to ship start unticked. "Add N threads" makes a thread per ticked worktree, named from its branch ("fix/checkout-retry" reads "Checkout retry"). Nothing runs until a message is sent.
  • Later visits show a count beside the recent threads ("4 worktrees"). Opening it lists them with "Work here" (points the thread about to start at that worktree), "Add as threads…" and "Hide for this project".
  • The Workspace picker under the message box lists them under "Existing worktree", on desktop and phone.
  • The command palette has "Add existing worktrees as threads…", which also brings a hidden count back.
  • An added thread opened before its first message says where it works.

Only worktrees outside Threadlines' own worktrees folder count, and only ones no thread works in yet.

A guest, not an owner

A thread in one of these worktrees carries ThreadWorktreeOrigin { kind: "existing" }, the marker a thread lent another thread's worktree already has. So the first turn never renames the branch, no setup script runs, deleting the thread never offers to remove the folder, the cleanup dialog never pre-ticks it, and undo only reverts the thread's own edits. A thread continuing in a guest's worktree is a guest too. The branch picker and the Source panel send the marker when they point a thread at one.

How it is built

  • vcs.listWorktrees takes scope: "elsewhere" (leaves out the main checkout and Threadlines' own worktrees before any per-worktree work) and statuses: false (names only). Reading a worktree costs a git status there, about seven seconds on a repository with 34 worktrees, so the count, the menus and the palette ask for names and only a list that is shown asks for statuses.
  • thread.create accepts worktreeOrigin: { kind: "existing" } from a client (never without a worktree path; kind: "thread" stays server-only). thread.checkout.select takes existingWorktree.
  • The server reports a worktreePickup capability. Without it the client asks for nothing and sends no marker.
  • Design note: docs/design/worktree-pickup.md. The app guide's "Threads and worktrees" topic covers it.

Known limits

Checked

vp fmt, vp lint, vp run typecheck, the full unit suite, the full browser suite, and the startup size check (891,290 B against 915,000). Walked every screen in the real app against a scratch repository with four worktrees, in light, dark and phone layouts. Not run: a real agent turn inside a picked-up thread.

A repository often has worktrees Threadlines did not make (git worktree
add, or another app). They only showed in the branch picker, with no way to
carry on in them as threads.

Right after such a repository is added, the new-thread screen lists them
under the message box with a checkbox each; "Add N threads" makes a thread
per ticked worktree, named from its branch, and nothing runs. Later visits
show a count beside the recent threads that opens into rows with "Work
here". The Workspace picker lists them under "Existing worktree", and the
command palette can lay the list out again.

A thread in one is a guest (ThreadWorktreeOrigin `existing`): no branch
rename, no setup script, deleting it never offers to remove the folder,
cleanup never pre-ticks it, and undo only reverts the thread's own edits.
The branch picker and the Source panel mark a thread they send into one.

vcs.listWorktrees can leave out Threadlines' own worktrees and can name
worktrees without reading them: reading costs a git status each, about
seven seconds on a repository with 34, so only a list that is shown asks.

Design note: docs/design/worktree-pickup.md.
@vercel

vercel Bot commented Nov 14, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
threadlines Ready Ready Preview Nov 14, 2026 7:11pm UTC

Request Review

@badcuban
badcuban added this pull request to the merge queue Nov 14, 2026
Merged via the queue into main with commit 4f6a114 Nov 14, 2026
33 of 35 checks passed
@badcuban
badcuban deleted the feat/existing-worktree-pickup branch November 14, 2026 19:29

This branch was successfully deployed

1 active deployment
Preview — de24fb7e Deployed Nov 14, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant