Skip to content

Worktrees

Git worktrees let one repository have several branches checked out in separate folders. luvus makes them first-class workspaces. Creation uses the built-in Git provider by default, so existing installations keep their current behavior. A third-party module can provide creation and, optionally, explicit removal through any worktree manager. Internal rollback and task merge continue to use Git directly.

Install or link an enabled module whose manifest declares a fixed provider command, then select its canonical module id in ~/.luvus/config.json (debug builds: ~/.luvus-dev/config.json):

# The module's luvus-module.toml
id = "example.worktree-manager"
name = "Worktree Manager"
version = "0.1.0"
min_luvus_version = "0.14.1"
[worktree_provider]
command = ["./create-worktree"]
remove_command = ["./remove-worktree"] # optional
identity_bound_remove = true # if removal binds expected_identity
{
"worktree": {
"provider": "example.worktree-manager"
}
}

The configuration selects only a registered module; it cannot supply an executable, argv, or shell command. Luvus runs the fixed manifest argv directly in the module directory with the module’s normal settings and identity environment. It writes one request to the provider’s stdin.

Creation request:

{"version":1,"operation":"create","repository":"/absolute/repo","branch":"feature/example","branch_exists":false}

Creation must emit only {"path":"/absolute/worktree/path"} on stdout.

When remove_command is present, explicit worktree.remove and confirmed TUI deletes send:

{"version":1,"operation":"remove","repository":"/absolute/repo","path":"/absolute/worktree","branch":"feature/example","force":false}

force is true for a confirmed sidebar deletion and false for the CLI/API command unless --force or force: true is explicitly requested. Normal CLI/API removal fails with worktree_in_use before deletion when the worktree has a working or blocked agent pane, an unfinished bound task, or a related lease. Finish or release the named work first. Forced removal bypasses that guard and stops panes in the removed workspace. Confirmed sidebar deletion also supplies expected_identity (volume and file). A removal provider must reject a target whose directory identity has changed and bind deletion to the checked directory, not just its path. Providers without identity_bound_remove = true use built-in Git removal for the confirmed sidebar action.

Removal must write nothing to stdout, exit successfully, and both unregister the worktree and remove its directory. If a provider violates the exit or stdout contract after the irreversible deletion already completed, Luvus reconciles the proven Git and filesystem state rather than leaving a stale workspace; stdout is still not a supported result channel. If remove_command is omitted, explicit removal falls back to built-in Git. Human diagnostics belong on stderr. A non-zero exit preserves stderr in the user-facing error when the target still exists, so approval or non-interactive failures from the underlying tool remain actionable. The provider handles one request at a time and must not call back into the Luvus CLI/API while that request is running; module settings and config/state directories remain available.

Before opening the returned path, Luvus verifies that it exists, is registered as a Git worktree, shares the source repository’s Git common directory, and has the requested branch checked out. This provider applies uniformly to worktree.create, TUI creation, and ORCH task worktrees.

  • Ctrl+Space G: type a branch name. With the default provider, luvus runs git worktree add under ~/.luvus/worktrees/<repo>/<branch> and opens it as a workspace. A module provider chooses its own path and creation tool. esc or a click outside the prompt cancels it.
  • The folder picker (Ctrl+Space N): when browsing a git repo, an Open with new worktree row (or the w key) does the same for that repo.
  • CLI: luvus worktree create <branch> · open <path> · list · remove <path> (the branch is kept).

Right-click a repo’s sidebar row and choose Open Worktree. The list is fed by git worktree list, so it shows every existing, non-bare checkout git knows about, wherever it lives on disk and whichever tool created it: a sibling folder from git worktree add ../feature, one made by another editor, or one under ~/.luvus/worktrees/. Each row shows the branch (or the short commit when detached), the path, and an open badge when that checkout is already a workspace.

  • ⏎ opens the highlighted checkout as a new workspace. If it is already open, luvus focuses that workspace instead of opening a duplicate, since a worktree is one place.
  • ↑/↓ (or j/k) move, esc closes. Rows are clickable.
  • The listing runs off the app loop, so a slow filesystem shows a brief Loading worktrees… row rather than stalling the terminal.

Bare entries and worktrees whose folder is already gone (git worktree prune would remove them) are left out, since there is nothing to open.

Right-click a linked worktree in the sidebar, choose Delete Worktree, then confirm. Luvus validates that the target is a linked checkout (never the main checkout), closes its workspace, and removes it in bounded background work. The dialog closes immediately; the Luvus Bar shows deletion in progress and leaves a success or failure notification when it finishes. The Git branch is kept. If the background queue is full or validation fails, the workspace remains open. If removal fails after it starts, the directory may still exist and can be reopened from the main checkout.

Unrelated workspaces and agent sessions remain usable during validation and removal. Before removal starts, Luvus checks again for other workspaces or panes using the checkout. If one opened while validation was running, deletion is cancelled and the checkout is preserved.

Each agent works in its own worktree, with its own files on disk, so two agents can work the same repo without any chance of stepping on each other’s edits. The sidebar nests worktrees under their repo, so the grouping is always visible. This is also the foundation the orchestration board builds on.