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:
tuios worktree new feat/retryCreated 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 fromHEAD. - The worktree goes under
$XDG_DATA_HOME/tuios/worktrees/<repo>/<branch>. - The session is named
<repo>-<branch>, with every/turned into-.--namepicks another name. - The session attaches at once.
--detach(-d) creates it without attaching. --repopoints 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:
tuios worktree new feat/retry --base main --agent claude --detachA session you start by hand inside a worktree is recognised too. The daemon reads the directory, so it never runs git to find out.
From the rail Added in v0.9.3
- On the session rail, right-click the header of a repository, or the row of a worktree session.
- Select New worktree....
- Type the branch.
- Optionally, type a session name. With no name, TUIOS makes one from the repository and the branch.
TUIOS makes the worktree and its session, and attaches to it. The dialog does not ask for a folder. The worktree goes under the worktree folder of the daemon: TUIOS_WORKTREE_DIR in the environment of the daemon, or $XDG_DATA_HOME/tuios/worktrees. A notification shows where the worktree is.
From a pane Added in v0.11.1
Ctrl+B U opens the same dialog on the repository of the focused pane's folder. Type the branch, and press Enter. TUIOS makes the worktree and its session, and switches to it. If the pane is not in a git repository, a message says so. The action is new_worktree. See New worktree.
Where a worktree goes Added in v0.12.0
[worktree] path sets where tuios worktree new, New worktree... on the rail and tuios fan put a worktree. The value is a path template.
[worktree]
path = "{{ repo_path }}/.worktrees/{{ branch | slug }}"| Variable | What it holds |
|---|---|
repo_path | The main checkout's directory |
repo | Its base name |
branch | The branch, as given |
slugturns a value into one folder name:feat/retrybecomesfeat-retry.sanitizeis another name forslug. Use it onbranch. Without it, the slash makes a folder per part, so the worktree offeat/xlands inside the worktree offeat.- A relative path starts at
repo_path. A leading~/is your home folder. - The template must use
branch. - A worktree can be inside the repository, where git does not ignore it. tuios then warns and names the folder to add to
.gitignoreor.git/info/exclude. tuios never edits those files. - The daemon reads the setting when it starts and when the file changes. While the setting is empty,
TUIOS_WORKTREE_DIRin the daemon's environment still moves the default folder.
Run a command in a new worktree Added in v0.12.0
An after-new-worktree hook runs in the new worktree before its first pane starts. Use it to copy the ignored files a checkout needs. See Hooks.
[hooks]
after-new-worktree = 'cp "$TUIOS_WORKTREE_REPO_ROOT/.env" .'Setup before the agent Unreleased
[worktree] setup is a shell command that runs in every new worktree before its agent or shell starts. Use it to install dependencies:
[worktree]
setup = "pnpm i"
setup_async = false| Key | Default | What it does |
|---|---|---|
setup | "" | The command. It runs with sh -c in the worktree, in a window named setup, with no grants. Empty runs nothing |
setup_async | false | Start the agent at once, while the setup runs |
The new session shows a card at the top right with three stages: the checkout, the setup with its last four lines, and the agent. The rail row says setup while it runs and setup failed after a failure.
- Without
setup_async, the agent starts when the setup passes. When the setup fails, TUIOS removes the new worktree and the branch it made, and the agent does not start. It keeps a worktree with an uncommitted change or a nested repository, and a branch with a commit or one that was there before, and the card's note says what it kept. The setup window stays open on its output until you press Enter. - With
setup_async = true, a failed setup keeps the worktree and the branch, because the agent may already have work in them.
tuios worktree new --setup CMD and tuios fan --setup CMD set the command for one call, and --setup-async the mode. --setup '' runs no setup.
A new command waits for you
A process in a pane can write the config file, and the daemon runs this command. So a new or changed command waits for tuios config apply from a terminal outside TUIOS, or a daemon restart. Clearing the command applies at once.
Hooks and repository config
TUIOS runs git with no hooks when it makes a worktree, so your post-checkout hook does not run. Run it yourself in the new worktree if you need it. The same holds for every git command TUIOS runs on its own: checkpoints, reviews, diffs and counts. A filter, textconv or diff program that only the repository's own .git/config names does not run. A filter from your global git config, such as Git LFS, still runs.
Listing and comparing
tuios worktree ls
tuios worktree ls --repo apiEach 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 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.
Merged branches Added in v0.10.0
The MERGED column shows into <ref> when the branch of a worktree is merged, so you can see which worktrees are safe to remove. A branch is merged when it has commits of its own, and a merge into its base changes nothing.
- TUIOS checks the base of the worktree, then the upstream of the base, such as
origin/main, as git last fetched it. TUIOS does not fetch. - A merge commit, a fast-forward, a rebase and a squash merge all count.
- A new branch with no commits is not merged. A branch that only fast-forwarded to its base is not merged. A commit and its revert are not merged.
tuios worktree ls --jsongivesmergedandmerged_into.
TUIOS does not remove a merged worktree. Use tuios worktree rm.
tuios worktree diff api-feat-retry
tuios worktree diff api-feat-retry --statworktree diff prints the commits the session made on top of its base, then its uncommitted changes, then its untracked files.
Removing one
tuios worktree rm api-feat-retryThis 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 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.
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-3and so on. The stem isfan/plus the first words of the prompt, or--name. --agentis 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,geminiwith 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 NAMEpasses your value of a variable to every agent, and--env NAME=VALUEsets one.PATHis always sent.--basesets the ref every branch starts from.--grantssays what every agent may do through TUIOS. See 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 asking you to look at its pane. Its prompt is typed as soon as it is ready.
--waitmakes the command return only when every prompt has been sent or given up on.--hostruns the fan-out on another machine. See Remote Hosts.
Follow the run:
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 3600000The --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.
tuios fan compare api-fan-demofan/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.
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. The review overlay's compare view (Ctrl+B v, then w) does all of this from the keyboard.
tuios fan diff api-fan-demo api-fan-demo-2 --stat
tuios review api-fan-demo-2Keep one and remove the others:
tuios fan keep api-fan-add-retry-backoff-http-2 --stashThe 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:
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 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, 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:
tuios worktree pull build:api-fan-add-retry-2
tuios worktree pull build:api-fan-add-retry-2 --branch try/retry-build --detachThe 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.
{"id":1,"verb":"fan","params":{"count":3,"agent":"claude","prompt":"Add a retry.","repo":"/src/api"}}See Control Protocol and tuios list-verbs fan.
Related
Ship
Commit, merge, push and open a pull request from a worktree
Checkpoints
Read and undo what one turn changed
Agents
The agent state each worktree session reports
Agent Messaging
Let the agents talk to each other
Session Rail
Worktree sessions grouped under their repository
Sessions
What a session is and how it persists
Program Status
Let any program in a pane report what it does with one escape sequence, OSC 7501, and see it in the rail and the Inbox.
Checkpoints
TUIOS saves an agent's work tree at the end of each turn, so you can read what one turn changed and undo it.
tuios lives only at tuios.dev and github.com/Gaurav-Gosain/tuios. tuios has no X or Twitter account. An account that offers a tuios token or presale is not this project.