# Worktrees

URL: https://tuios.dev/docs/worktrees

> One session per git worktree, and one prompt fanned out to several agents at once.

A git worktree is a second checkout of a repository on its own branch. It is a good place to put one agent: it has its own files and its own branch, and it shares nothing with your working copy. TUIOS makes the worktree and a session inside it with one command, and the rail groups every such session under its repository, labelled by branch.

## Creating one

Run this inside a repository:

```bash
tuios worktree new feat/retry
```

```
Created branch feat/retry in /home/u/.local/share/tuios/worktrees/api/feat-retry.
Created session 'api-feat-retry'.
```

- A branch that does not exist is created from `--base`, or from `HEAD`.
- The worktree goes under `$XDG_DATA_HOME/tuios/worktrees/<repo>/<branch>`.
- The session is named `<repo>-<branch>`, with every `/` turned into `-`. `--name` picks another name.
- The session attaches at once. `--detach` (`-d`) creates it without attaching.
- `--repo` points at another repository instead of the current directory.

`--agent` starts an agent CLI in the session instead of a shell. Name it the way you type it:

```bash
tuios worktree new feat/retry --base main --agent claude --detach
```

A session you start by hand inside a worktree is recognised too. The daemon reads the directory, so it never runs git to find out.

## Listing and comparing

```bash
tuios worktree ls
tuios worktree ls --repo api
```

Each row shows the session, repository, branch, the agent state inside it, how many uncommitted changes it holds, and its pull request and checks once [`tuios ship pr`](https://tuios.dev/docs/ship) opened one. A row marked `gone` is a session whose worktree directory was removed. The session is kept, so what the agent printed can still be read.

```bash
tuios worktree diff api-feat-retry
tuios worktree diff api-feat-retry --stat
```

`worktree diff` prints the commits the session made on top of its base, then its uncommitted changes, then its untracked files.

## Removing one

```bash
tuios worktree rm api-feat-retry
```

This runs `git worktree remove` and kills the session. A worktree with uncommitted changes is refused and nothing is removed. Choose what happens to the changes:

| Flag             | Effect                                                                         |
| ---------------- | ------------------------------------------------------------------------------ |
| `--stash`        | Move the changes into the repository's stash as `tuios: <branch>`, then remove |
| `--force`        | Discard the changes. The only option that throws work away                     |
| `--keep-session` | Remove the worktree and leave the session running                              |

Removing a worktree also deletes the [checkpoints](https://tuios.dev/docs/checkpoints) taken in it.

> **Branches are never deleted**
>
> Every commit made in a worktree stays in the repository. TUIOS never deletes a branch and never runs `git worktree prune`.

## Fan-out: one prompt, several agents

`tuios fan` starts the same prompt in several agents at once, each in its own worktree. When they finish, compare the results and keep the best one.

```bash
tuios fan 3 --agent claude 'Add a retry with backoff to the HTTP client.'
```

```
Started 3 agents on fan/add-retry-backoff-http. Each prompt is sent when its agent is ready.
  api-fan-add-retry-backoff-http    fan/add-retry-backoff-http    ...
  api-fan-add-retry-backoff-http-2  fan/add-retry-backoff-http-2  ...
  api-fan-add-retry-backoff-http-3  fan/add-retry-backoff-http-3  ...
```

- The count is 1 to 16.
- The branches are a stem, then `stem-2`, `stem-3` and so on. The stem is `fan/` plus the first words of the prompt, or `--name`.
- `--agent` is required. Name the agent the way you type it, arguments included: `claude`, `"codex --model o5"`, or any program. Several, separated by commas, are cycled across the sessions, so `--agent claude,codex,gemini` with a count of 3 starts one of each.
- `--prompt`, given once per session, gives each session its own prompt. The count is then how many there are.
- `--env NAME` passes your value of a variable to every agent, and `--env NAME=VALUE` sets one. `PATH` is always sent.
- `--base` sets the ref every branch starts from.
- `--grants` says what every agent may do through TUIOS. See [What a pane may do](https://tuios.dev/docs/agents#what-a-pane-may-do).
- The prompt is not typed the moment the agent starts. TUIOS waits until the agent is at its prompt, then types it, so it never lands in a start-up screen. An agent that has not shown its prompt after 30 seconds, most often because it asks a first-run question such as whether to trust the folder, puts a question in the [Inbox](https://tuios.dev/docs/agent-inbox) asking you to look at its pane. Its prompt is typed as soon as it is ready.
- `--wait` makes the command return only when every prompt has been sent or given up on.
- `--host` runs the fan-out on another machine. See [Remote Hosts](https://tuios.dev/docs/remote-hosts).

Follow the run:

```bash
tuios worktree ls --group fan/add-retry-backoff-http
tuios wait-for agent-state --select 'group:fan/add-retry-backoff-http' --until idle,done --every --timeout 3600000
```

The `--group` listing shows whether each prompt is `pending`, `sent` or `not_sent`.

### Comparing and keeping one

`fan compare` shows every attempt on one line: its agent and state, the files and lines it changed against the fan's base (committed or not, untracked files included), and its last check.

```bash
tuios fan compare api-fan-demo
```

```
fan/demo in api, 2 attempts against main
  api-fan-demo    bash  none  0 files  +0 -0  no check yet
  api-fan-demo-2  bash  none  2 files  +2 -0  no check yet
Keep one with 'tuios fan keep <session>'. Compare two with 'tuios fan diff A B'.
```

`fan verify` runs one check in every attempt, in a window named `verify` in each session, and says which passed. It always runs the command you give, never one read from the repository, and the window holds no grants. A window whose check passed closes. One whose check failed stays open so you can read the output. The command exits `1` when any check failed.

```bash
tuios fan verify api-fan-demo -- 'test -f b.txt'
```

```
Running "test -f b.txt" in 2 attempts of fan/demo.
  api-fan-demo: failed, exit 1 in 0s. Its verify window is open with the output
  api-fan-demo-2: passed in 0s
1 of 2 passed.
```

`fan compare` then shows each check's result in its last column. `fan diff` shows what one attempt did differently from another, and `tuios review` shows one attempt's changes with notes you can send back to its agent. See [Reviewing an agent's changes](https://tuios.dev/docs/agent-inbox#reviewing-an-agents-changes). The review overlay's compare view (Ctrl+B v, then w) does all of this from the keyboard.

```bash
tuios fan diff api-fan-demo api-fan-demo-2 --stat
tuios review api-fan-demo-2
```

Keep one and remove the others:

```bash
tuios fan keep api-fan-add-retry-backoff-http-2 --stash
```

The session you name is untouched. Each sibling is removed the way `worktree rm` removes it. A sibling with uncommitted changes is left in place unless you pass `--stash` or `--force`.

To land the kept attempt too, add `--merge`:

```bash
tuios fan keep api-fan-add-retry-backoff-http-2 --merge --squash
```

`--merge` first merges the kept attempt's branch into its base in the main checkout, as [`tuios ship merge`](https://tuios.dev/docs/ship#merge) does. `--squash`, `--ff-only` and `--into` choose how. When the merge conflicts or is refused, it is undone and no sibling is removed. Uncommitted changes in the kept worktree are not merged, so commit them first with `tuios ship commit`.

## Work from another machine

`worktree new --host` and `fan --host` run on a machine from the [`[hosts]` table](https://tuios.dev/docs/remote-hosts), and so does `start-agent -s HOST:SESSION`. The repository is the one the current directory is in, found on the host by its origin URL under the host's `repos_root`, and `--clone` clones it there when the host has none. The agent must be installed on that machine.

`worktree pull` brings the work back:

```bash
tuios worktree pull build:api-fan-add-retry-2
tuios worktree pull build:api-fan-add-retry-2 --branch try/retry-build --detach
```

The session's commits come across as a git bundle into a new branch here, and its uncommitted work, untracked files included, as a patch applied in a new worktree on that branch. Nothing on the other machine changes. A branch that already exists here is refused, so nothing is overwritten.

## From a script

The commands are wrappers over the `new-worktree`, `list-worktrees`, `remove-worktree`, `fan`, `compare-fan`, `verify-fan` and `keep-fan` verbs. `--json` on each command gives the result as JSON.

```json
{"id":1,"verb":"fan","params":{"count":3,"agent":"claude","prompt":"Add a retry.","repo":"/src/api"}}
```

See [Control Protocol](https://tuios.dev/docs/control-protocol) and `tuios list-verbs fan`.

## Related

*[An interactive figure goes here. Open the page to use it.](https://tuios.dev/docs/worktrees)*
