---
title: "Checkouts — Robion user manual"
description: "Git worktrees as checkouts: main vs own worktree, the TASKS section, update, merge, remove, tidy, conflicts, what the agent can and cannot touch."
url: "https://robion.app/docs/checkouts/"
lang: en
---

# 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 branch `worktree-<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](https://robion.app/docs/tasks/)), **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 <project>"). A detached
  worktree outside the worktrees folder with no task in it (a release build under the temp
  folder, `git worktree add --detach` to 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 = <root>/.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-<name> 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 with `claude --worktree`; the tab
  tooltip reads "own worktree · <branch>", 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-<branch>.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 --worktree` Claude 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 · <strategy>**, **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 <path>". Since 0.20.4 this
  needs no `cd` by the agent (0.20.1–0.20.3 moved the task only on its first `cd`, 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 (<branch>)" 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 <default branch>** 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 <files> — 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 `npm` works 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 <branch>? 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 <branch>? 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 "<title>"? 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`, a `cd`) 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 update` on 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 · <sha>" or "pull request opened" ([phone.md](https://robion.app/docs/phone/)).
