Worktrees and tasks
New Task makes a worktree, a branch and an agent in one step — and Overterm notices when the branch is merged.
A task in Overterm is a git worktree on its own branch with a tab in it, usually with an agent started. Making one by hand is four commands; here it is one sheet. The other half of the feature is the end: knowing which of your nine worktrees are finished with, and removing them without losing work.
New Task
⇧⌘N, or File ▸ New Task…, or the palette’s New Task….
The sheet asks three things:
- Branch — the branch to work on. An existing branch is checked out as
it is; a new one is created at the base below. The name is validated with
git check-ref-format --branch, so an invalid name is refused before anything is created. - From — the base the new branch starts at. Prefilled from Settings
(see below); empty means
HEAD. - Start — Claude, Codex or Shell only, prefilled from Settings ▸ Agents.
Under the fields the sheet shows the exact path the worktree will take, so you see where it is going before you press Create.
Then:
⇧⌘N → branch, base, agent
↳ git worktree add (-b <branch> … <base>)
↳ a tab in the new worktree, named after the branch
↳ the agent typed into its shell
The tab’s name is the branch. The checkout it shows in the sidebar, the changes pane and the ± badge is the new worktree, because that is where its agent works.
Where the worktree goes
Settings ▸ Agents ▸ Worktrees go (agents.worktreeLocation):
| Value | Path | Example |
|---|---|---|
sibling (default) |
<repo>-wt-<branch> |
~/code/app-wt-feat-auth |
inside |
<repo>/.worktrees/<branch> |
~/code/app/.worktrees/feat-auth |
The branch name is slugged for the path: everything outside letters,
digits, ., _ and - becomes a dash, runs of dashes collapse, and the
result is lowercased. feat/Cosign signing becomes feat-cosign-signing.
With inside, Overterm adds .worktrees/ to the repository’s local
exclude file (.git/info/exclude) the first time, under a comment naming
itself. No tracked file is changed, and nothing is added to .gitignore.
Settings ▸ Agents ▸ New branches start from (agents.newTaskBase)
prefills the From field. Left empty, the base is the main worktree’s
branch.
Worktrees in the sidebar
⌘B opens the sidebar; the Worktrees section lives in Overgit. Each row shows the worktree’s name, a house glyph for the main checkout, and on a line beneath it what its tabs are doing — named and coloured when an agent in it is blocked (“Agent waiting · …”). On the right of the row:
- a pin when the worktree is attached to the selected tab, or the agent’s own glyph when an agent is working there;
- its branch’s pull request — the number in its state’s colour with a CI
glyph — through your own
gh; - a purple merge mark when the worktree is finished with, a folder-question glyph when its directory is gone, a lock when it is locked.
Clicking a row opens it. Right-clicking gives:
Attach to This Tab / Detach from This Tab · New Tab Here · New Claude Tab Here · New Codex Tab Here · Show Pull Request #N · Open #N on GitHub · Reveal in Finder · Copy Path · Remove Worktree… · Clean Up Merged Worktrees…
Attaching pins a checkout to a tab: the sidebar, the changes pane and the ± badge then follow that checkout rather than guessing from the tab’s agent or shell directory.
Merged-worktree detection
Overterm marks a worktree as finished with when any one of these is true of its branch:
- Its upstream is
[gone]and every commit is pushed. This is GitHub’s delete-on-merge: the branch was pushed, then deleted on the remote. Overterm checks the tip really is on some remote ref — a gone branch carrying commits no remote has (work done after the merge) is never treated as merged on that alone. - It has an upstream and its tip is reachable from the default branch
—
origin/HEAD, else the main worktree’s branch. ghreports a merged pull request whose head is exactly the branch’s tip. This is how a squash merge is recognised, where the branch’s commits never appear inmainat all. A reused branch name with new work on it does not match, because the tip has moved.
A branch that was never pushed never counts, however reachable it looks: a
brand-new task branch with no commits is reachable from main too.
A worktree whose folder was deleted by hand (git calls it prunable) is cleanable as well.
Clean Up Merged Worktrees
The Worktrees header shows a count — “Clean up 3 merged” — which runs Clean Up Merged Worktrees…. It is also in the File menu, the palette and a worktree row’s menu.
It runs git fetch --prune first (ssh in batch mode, so it never hangs on a
passphrase prompt), then shows one sheet listing what goes and what stays.
A worktree is kept, and the sheet says so, when:
- a tab is working in it — a shell’s directory, or where its agent works;
- it has uncommitted changes;
- it is locked.
Removal is git worktree remove without --force, so git itself still
refuses anything surprising. Deleting the branch is a tick box and uses
git branch -D, because -d refuses a squash-merged branch — which is
exactly the case this feature exists for.
The Worktrees reload button fetches too, so the marks are current without running the clean-up.
Pull requests
Everything GitHub goes through your own gh,
already logged in. There is no token in Overterm and no GitHub app.
One gh pr list --state all per repository, cached for a minute and
refreshed each minute while the app is active, feeds the worktree rows, the
title-bar chip for the current branch, and Overgit’s Pull Requests section.
View ▸ Pull Request opens the right-hand pane on the current branch’s
PR: its checks, description, comments and review threads, with inline
comments grouped into threads. A thread’s file:line opens in the
editor, and you can comment and reply from the pane.
Without gh, or without a login, the pull request pane stays empty and
nothing else changes. See Requirements.
Claude sessions
The sidebar’s Sessions panel lists every Claude conversation ever run in
the repository’s worktrees — read from ~/.claude/projects — newest first,
with the session’s own title. Clicking one selects the tab it is running in,
or opens a new tab with claude --resume <id> in the directory it ran in.
Only well-formed session ids are used, because the command is typed into a
shell.