Checkouts
Git worktrees as first-class checkouts (since 0.20): a task in the main checkout or in its own worktree, the TASKS section and the GIT caption, update, merge, remove, tidy, the hooks, the phone.
What a checkout is
- A checkout is a working tree of the project’s repository: the main checkout (the project
root) or a worktree under
<root>/.claude/worktrees/<name>on branchworktree-<name>. Git is the truth: worktrees Robion made for a task, ones Claude Code made itself (claude --worktree, a subagent) and ones added by hand all appear, tagged Steward, agent (a task another agent started, tasks.md), Claude or by hand where it matters; one still being made reads “being created…”. A worktree added by hand anywhere opens in TREE and GIT like the others (since 0.20.19; before, one outside the worktrees folder answered ”… is not a checkout of”). A detached worktree outside the worktrees folder with no task in it (a release build under the temp folder, git worktree add --detachto look at an old commit) is not listed at all: no branch to merge, nothing running there — it appears once a task runs in it. - ⚙ → project → Worktrees directory: “empty =
/.claude/worktrees (in .git/info/exclude) — the only place Claude Code adopts a worktree in (claude —worktree, enforced isolation); a custom directory gives a plain git worktree without isolation”.
Main checkout or own worktree when starting a task
- The segment next to + new task (git projects only) picks the place a task runs in, not a
branch: main checkout — “a quick task in the main checkout, on whatever branch is checked
out there (one click, as always) — click switches to an own worktree”; own worktree —
“own worktree: claude —worktree, branch worktree-
from the local HEAD; the main checkout is out of the agent’s reach — click switches back to the main checkout”. The click flips the project’s default for tasks by hand (remembered per project; the phone follows it). The ⋯ popover repeats “the task starts in the main checkout / its own worktree (claude —worktree)”. Until 0.20.8 the segment read main / branch, which suggested a choice of git branch inside the same checkout; a main-checkout task runs on the branch currently checked out there, whatever the default branch is called. - An own-worktree task: Robion creates the worktree (branch
worktree-<name>from the task title: lower-case, dashes) and starts Claude Code in it withclaude --worktree; the tab tooltip reads “own worktree ·”, the rail’s second line counts “n checkouts”. - ⚙ → project → Worktree setup script: “runs in the new worktree right after it is created,
before the agent starts (e.g. .env, pnpm install); ROBION_PROJECT_ROOT, ROBION_WORKTREE,
ROBION_WORKTREE_SLUG and PORT are set; without a script the files matched by .worktreeinclude
are copied; output in logs/setup-
.log”.
Per-project defaults (⚙ → project)
- New task by hand: own worktree — “the “new task” button starts a worktree (claude —worktree); the segment next to the button switches it any time”.
- Tasks of the Steward and automations: own worktree — “unattended work never touches the checkout you are editing; the agent cannot reach main from a worktree” (on by default).
- Base of a new worktree: local HEAD (“carries unpushed commits too”) or origin default branch (“Claude Code’s own “fresh"").
- Task teardown script: runs in the task folder when the task closes.
What isolation means for you
- With
claude --worktreeClaude Code enforces the isolation: the agent’s edits and git commands cannot reach the main checkout — “main is out of the agent’s reach” — so you keep editing main while it works. A custom worktrees directory loses this (a plain worktree). - No agent tool merges, updates or removes a checkout; those are your clicks in the side panel or on the phone. The agent asks for a review; you integrate.
The TASKS section (side panel)
- Caption tasks · count. Rows: main first (named by the default branch), then each worktree: branch, ”· n changes”, ↑n ahead / ↓n behind, the origin tag; under it the tasks (“CC · title”, “SHELL · title”, the state dot, ”· parked”; × ends the task).
- Row actions (shown on hover): main has + task (“a new Claude Code task in this checkout”)
and new checkout; a worktree has merge (“fold the branch into main: fast-forward,
squash, merge or PR”), update (“rebase onto the default branch (merge when the branch was
pushed)”), + task, remove (“remove the worktree and its branch”; disabled with “a task
is still running here”). Right button: show in tree and git, + task, new checkout,
merge ·
, update, remove. - A task follows its session: when the agent enters a worktree mid-session (“do it in a new
worktree” → EnterWorktree), leaves it (ExitWorktree) or starts with
claude --worktree, its row moves under that checkout with the next hook Claude Code sends (a tool call, a prompt, the end of a turn) and the timeline notes “the session moved to”. Since 0.20.4 this needs no cdby the agent (0.20.1–0.20.3 moved the task only on its firstcd, because Claude Code fires no CwdChanged hook for EnterWorktree). - to tidy · n: “worktrees with no task that are merged or older than 14 days” — each with “merged” or “↑n unmerged”, its age “n d”, and remove or discard….
- history: the recently closed tasks, resumable in place (the full list is on home).
- “server not connected” while the server is offline.
The GIT caption switcher and ⌘K
- The GIT caption holds a chip with the branch of the checkout the tree and git look at; its menu checkout lists every checkout (house = main, branch icon = worktree, ↑n, “n tasks” or “Claude”, ✓ current), new checkout…, and follow the active task when pinned.
- By default the panel follows the active task (a worktree task swaps the tree to its checkout). Picking one pins it: the pin icon reads “pinned · click to follow the active task again”. A pinned checkout that git no longer lists falls back to following. A pinned worktree with no task in it refreshes with the project (since 0.20.1; before, only the 15 s poll of the GIT section caught up with it).
- ⌘K group checkouts: “show in the side panel” pins the same way.
New checkout dialog
- new checkout (GIT caption menu, main row): name (“letters, digits, dots, dashes and
underscores”; the hint shows
.claude/worktrees/<name> · branch worktree-<name>), base: main · local HEAD, origin/main, or from the current checkout (offered when opened from a worktree); “the local HEAD carries unpushed commits too (worktree.baseRef = head)”. Buttons just create / create and start a task — “a worktree without a task”.
Update (rebase onto main)
- update rebases the branch onto the default branch; a branch that was pushed gets the default branch merged in instead (“merge when the branch was pushed”). Refused while the worktree has uncommitted changes, an agent is mid-turn there, or a rebase is in progress.
- On a conflict the row shows conflict · n and “the rebase onto main stopped on these
files:” with the list and four ways out: abort rebase; open a shell (a shell task in
that checkout); let an agent resolve it — a task “Resolve rebase conflicts (
)” with the prompt “A rebase is in progress in this worktree. Resolve every conflict keeping both intents, run the tests, do not push, then report.”; continue once the files are resolved (it may stop again). Robion never resolves a conflict itself.
Merge
- merge opens merge into
with four strategies: fast-forward (“main moves to the tip of the branch, no new commit”; blocked with “main moved by n commit(s) — “update” first”), squash (“n commit(s) → 1”, “one commit on main; the branch history is dropped”), merge commit (“keeps all n commit(s) and adds a merge commit”), pull request (“push the branch and open a PR / MR on the host; the review notes as its body”). Squash and PR take a commit message, prefilled from the task. - before merging — three checks that must all tick: the worktree is clean, no agent is running in this checkout, no overlap with uncommitted changes in main. A refusal shows inside the dialog: the first line says what happened and where main stands, the block under it what git or the hook printed (since 0.20.1). remove the worktree after merging (a tick; greyed with “a task still runs in this worktree”, and for a pull request) removes the worktree and branch right after a successful merge; merge / “merging…”. The checks and the counts follow the live checkout while the dialog is open (since 0.20.1): a commit in the worktree ticks “clean” without reopening.
- The merge runs in the main checkout; main’s own uncommitted edits are untouched (that is what the overlap check guards). The phone offers the same merge (below).
- A branch behind main (the row shows “behind n”) is brought up to date first when you choose
squash or merge commit (since 0.20.14): the dialog says so under the strategies (“main moved
by n commit(s): the branch is updated (rebased) first …”). A conflict then stops in the
worktree, never in main: the dialog reports “the default branch moved and the branch
conflicts with it in
— the update stopped in the worktree …”, the row switches to conflict · n with continue, abort rebase, open a shell, let an agent resolve it (see Update above), and after that the merge goes through as chosen. - The project’s git hooks (husky, pre-commit …) run with the PATH of your login shell plus
Homebrew, /usr/local/bin, ~/.local/bin and volta, so a hook that calls
npmworks from the dialog (since 0.20.1). A hook that refuses the squash commit, or a merge that fails half-way in main (“the merge failed in the main checkout”), shows git’s output in the dialog; a main that was clean is put back as it was (“the merge was undone, main is as it was”), a main with changes of its own keeps the merged changes staged (“the merged changes stay staged in main …”) — commit or reset them there, then merge again.
Remove, discard, tidy
- remove: “Remove worktree
? It is merged and clean.” Only a worktree without a task; its worktree-…branch (or any branch of a Robion-made worktree) is deleted with it, the branch of a Claude or by-hand worktree stays. - Unmerged or dirty: discard… — “Discard worktree
? n unmerged commit(s) and n changed file(s) will be lost.” - Removing a project (⚙ → project → Remove project) needs its tasks closed first and leaves every worktree on disk.
Ending a task in a worktree
- end task dialog: “Close task "
"? This ends its terminal session.” plus the tick remove the worktree and branch <branch> — pre-ticked when “merged into main · clean · the Claude Code lock is released”; otherwise “n unmerged commit(s) · n changed file(s) — kept unless you discard them” and a red second tick discard the unmerged work too (required before unmerged work can go); “the checkout list is not loaded; the worktree stays unless you tick this” when offline. end task / cancel. - resume from home continues “in the worktree if it still exists”.
The CwdChanged hook and “outdated hooks”
- Since 0.20 Robion installs Claude Code’s CwdChanged hook with the others, so a session that
moves into a worktree (
claude --worktree, acd) keeps its task and the side panel follows its checkout. Existing installs read “Claude Code hooks are outdated” once: click update hooks in the banner (or ⚙ → agents → Claude Code hooks → reinstall); a remote server’s hooks update from ⚙ → Servers. A remote server on an older release shows “update the server (vX)” there until it is updated (robion-server updateon the box).
On the phone
- A task row shows its branch; a new task offers own worktree (“the task gets its own
worktree; main stays yours”); the Changes tab has Merge into main (“squash · n commits → 1 ·
worktree clean · agent idle”) opening a sheet with squash (default), fast-forward (“main has
moved — update the worktree first” when blocked), merge commit and pull request; blockers “n
uncommitted changes in the worktree”, “the agent is still working”, “n files also changed in
main”; result “merged into main ·
” or “pull request opened” (phone.md).