Using it

Worktrees

Every agent starts in a git worktree of its own, on a branch of its own, so two agents never edit the same files.

Two agents in one checkout edit each other’s files. So an agent started in a project is started in a git worktree cut for it, on a branch of its own, lu/agent-1, lu/agent-2, and its row in the list says which. Its work can be reviewed and merged like anyone’s.

A shell is your own terminal, and opens in the project’s own checkout. A project that isn’t a git checkout with a commit gets no worktrees: its agents run in the folder itself.

A pool, not a pile

A worktree is reused and not deleted, which keeps its dependencies and its build output warm. A project holds a capped number of them, eight unless the config says otherwise. One that has sat ready and unused for a week is removed, and the pool grows back on demand. When every one of a project’s worktrees is in use or holds work that hasn’t landed, voodoo says so and starts nothing, rather than touch any of them.

The rule everything else bends to: a worktree holding work that hasn’t landed is never reset and never removed, unless you ask for that one by name. Landed means clean, with every commit already in the checkout’s HEAD or its default branch, whether it got there as an ancestor or by a squash.

See them

voodoo worktrees
voodoo worktrees (an example)

  Worktrees

  › my-app · ~/code/my-app
     1  lu/agent-1     in use      claude 1
     2  lu/agent-2     unfinished  3 changed files, 1 commit · used 2h ago
     3  lu/agent-3     ready       used 1d ago

  ! 1 holds work that hasn't landed. It is kept until it lands.
    `voodoo worktrees remove <number> --discard` loses it for good.
StateWhat it means
in useA session is in it.
readyFree, with nothing in it that hasn’t landed: the next agent’s.
unfinishedFree, and holding work that hasn’t landed. Kept until it lands, or you discard it.

Remove one

By its number in the listing, or by its branch. It deletes the folder and the lu/agent-N branch.

voodoo worktrees remove 3

voodoo refuses if the worktree holds work that hasn’t landed. --discard removes it anyway, and that work is lost for good.

A shell beside an agent

To look at what an agent did, or run what it wrote, open a shell in its worktree: t on its row in the list, or ^a t from inside its terminal. The shell shares the worktree, and the row says which branch that is.

Push it, and open a pull request

From inside the worktree, voodoo push pushes its branch and voodoo pr pushes it and then opens a pull request through gh, or finds the one already open. Neither is ever forced, and an agent’s worktree never pushes main, master or whatever origin calls its default: that is the one promise that lets an agent run voodoo push unattended. Pushes borrow gh’s login for the one command, so a machine with no SSH key for GitHub can still push.

voodoo pr

Files git ignores

A fresh worktree has none of the files your .gitignore keeps out of git, and an agent usually needs some of them. Commit a .worktreeinclude to the repository, in the same pattern syntax as .gitignore, and the files it names are copied into every worktree.

.worktreeinclude
.env
.env.local

Where they live

Under ~/.local/share/localuniverse/worktrees. Outside lu’s config folder on purpose, so that deleting the config never deletes work that hasn’t landed. LU_WORKTREE_DIR moves them.

Turn them off

Set "worktrees": false in the config, and every session runs in the project’s own checkout.