Concepts
Six nouns explain Rove: Task, Worktree, Terminal Tab, Engine, Daemon, and PTY host. Learn those and the rest reads itself.
Task
A Task is one workspace record you're tracking. Rove has three Task kinds:
| Kind | Directory | Git isolation |
|---|---|---|
| Project main | A saved repository's existing checkout | Uses the checkout as-is; no Rove-created branch or worktree |
| Managed task | A Rove-created worktree | Own branch and worktree |
| Directory task | An existing directory opened with rove . | Uses the directory as-is; it need not be a git repository |
For a managed task, the product unit is:
Managed task = git worktree + branch + terminal tabsA Task is a workspace, not a conversation. Its Terminal Tabs all run in the same directory. Only managed tasks get Rove-created branch/worktree isolation; project-main and directory tasks deliberately reuse directories you already own.
Scratch shells are directory Tasks with an unsettled home: press tab in
the ctrl+e new-conversation dialog until the destination reads "new scratch
task", pick an engine (or shell for a bare shell), and enter opens one in
$HOME with that engine already running. It
lives in the sidebar's Scratch section above every project, and follows a
zero-ceremony lifecycle: its last tab exiting removes the row (no archive, no
confirm; nothing on disk is touched). A scratch row earns a permanent place
two ways: rename it (naming is the keep gesture), or start a coding harness
inside a git repository. Rove detects the live harness plus the shell's
settled directory and quietly migrates the row into that repository's project
group. If the settled directory already belongs to a Task (the project's
main checkout, a directory Task's directory, or inside a managed Task's
worktree), the shell folds into that Task as a new terminal tab, running
session and all, instead of becoming a duplicate row.
Each Task has a status you set yourself (backlog, in_progress,
in_review, done, canceled, error) — from the sidebar row's right-click
menu (Set status) or with rove api update --status. It is a label and nothing
more: canceled does not stop a session or remove a worktree, and done does
not close anything. Rove moves a Task from backlog to in_progress by itself
when its engine starts a turn, and the system prompt asks the agent to set
in_review when it finishes; everything past that is yours. The sidebar row
does not draw it: the one mark in that cell is the PR's, and the status is
something you already know because you set it
(see TUI).
Delete is explicit and kind-aware. A project-main Task cannot go through
Task deletion; pressing d on its row instead forgets the saved project and
synthetic main row while keeping the repository, branches, worktrees, and
managed Tasks. Deleting a directory Task removes only its Rove record, never
the directory.
Deleting a managed Task removes its worktree after the dirty-worktree safety
check. The task branch stays. Git is the durable record of the work;
pass --delete-branch on rove api delete to drop it too. That runs
git branch -d, which refuses a branch whose commits neither the repo's HEAD
nor the branch's own upstream already contains — so work that was never pushed
and never landed survives the flag, and --force is what upgrades the delete
to git branch -D. The remote branch is only touched when you ask for it,
with the separate --delete-remote — a local branch is recoverable from any
clone that still has it, a remote one is recoverable by nobody, and deleting
it closes an open PR, so one flag never implies the other.
The separate
Worktrees page is an audit/cleanup tool: removing a directory
there keeps its Task record and branch so the worktree can be materialized
again later. rove api remove-worktree --task-id ID is the same operation
from a shell — the inverse of ensure-worktree, and what a script reclaiming
idle checkouts wants instead of delete.
What the delete did to the branch is in the reply. With either branch flag
the result carries branch — { branch, deleted, keptReason?, remote? } — so
"the branch went with it" is a fact you read rather than one you infer from
status: "removed", which is the worktree's outcome. When git kept the branch,
keptReason is its own sentence about why.
Worktree and branch
Every managed Task gets its own git worktree at
~/.rove/worktrees/<repo-key>/<task-slug>/, checked out to the task's
branch. The slug is drawn from a pool of animal names, so parallel Tasks in
one repo get distinguishable directories without anyone choosing them;
rove api add --worktree-name NAME overrides that when a script needs to
predict the path instead of reading it back, and refuses a name already in
use rather than suffixing it. That's what makes running many tasks at once safe: N tasks means N
working trees that can't overwrite each other or your main checkout. Edits
cross over only when you merge.
Project-main and directory Tasks are the exceptions: they point at an existing checkout or directory. Use a managed Task when you want isolation.
The worktree outlives everything else. Killing a session, quitting the TUI, dropping SSH, restarting the daemon: none of them touch it.
One thing to watch: Terminal Tabs inside the same managed Task share one worktree, and Rove does not coordinate their writes. Two tabs editing the same file at once will conflict. If you need real isolation, open a new task.
Terminal Tabs and engine sessions
A Task owns N Terminal Tabs. An engine tab runs an engine inside an interactive shell and can resume an engine-owned conversation. Other tabs can be shells, fixed commands/editors, or read-only file/diff content; those are not engine conversations. Splits add more shell leaves inside a tab.
Tabs let you ask a side question or open a shell without changing directories. Close a tab when you're done; the Task's directory stays. Exiting the engine CLI itself returns an engine tab to its shell prompt. The hosted session ends only when that wrapping shell exits or Rove explicitly closes it.
Closing the last tab is "done for now", not "forget". Close every tab of a
managed Task and its row stays in the sidebar; entering it again opens a fresh
tab in the same worktree. Close every tab of a project whose only row is its
main checkout (or of a directory Task) and the whole project leaves the
sidebar, header and row together. Nothing is deleted: the main Task record and
the saved repository both stay on disk. To bring it back, open New task
(n), pick the same repository, and choose "the project itself" instead of a
new task worktree (see TUI). Forgetting a project
(d on its row) is the separate, un-saving gesture.
Each engine tab may pin its own engine; otherwise it inherits the Task's engine, so tabs in one Task can use different vendors. A Task-level reasoning-effort choice is forwarded when that engine supports it. The embedded engine CLI owns its own model and permission controls.
Conversation history belongs to the engine, not to Rove (Claude Code, for
example, keeps JSONL transcripts under ~/.claude/projects/**). Hosted
terminal output has separate persistence rules; see Sessions.
Engines
An engine is the execution backend a task runs on. Rove embeds the real
interactive CLI (claude, codex, copilot, kimi, pi, omp, or one
yourself) inside a hosted terminal session. No API wrappers, no re-rendered
output: what you see is the actual engine running next to your dependencies
and credentials.
Details: Engines.
Daemon and PTY host
Rove splits into three processes, and that split is why your sessions survive you:
- Daemon. Owns your task list, worktrees, and the issue store. Starts on its own, then stops after the last attached GUI disconnects unless an enabled routine, or any live tab session in the PTY host, holds it alive (it must stay up to collect engine activity, or the status dots go stale).
- PTY host. Owns the running engine and shell processes. Survives both the TUI and a daemon restart.
- The TUI. Just a viewport. Quitting it kills nothing.
Full lifetime rules, and exactly what survives a reboot: Sessions.
The issue store
Rove has no external issue tracker. Your backlog lives in a daemon-owned
store at ~/.rove/issues.json, shared between a repo and all its worktrees.
It's deliberately simple. No type taxonomy, just a status
(open → doing → done, plus hold for things parked on purpose):
- You. The Kanban in the TUI. Open a card with
enterand tab to its STATUS field to move it between columns;don the board deletes the story outright. - Agents and scripts.
rove api issue-list,issue-create,issue-update(--statusmoves a card),issue-delete.
Issues track what to do; the changelog records what shipped.
Where things live on disk
| What | Where |
|---|---|
| Task index | ~/.rove/tasks.json |
| Worktrees | ~/.rove/worktrees/<repo-key>/<task-slug>/ |
| Issue store | ~/.rove/issues.json |
| Daemon socket / log | ~/.rove/daemon.sock, ~/.rove/daemon.log |
| Settings | ~/.config/rove/state.json (open with rove config) |
| Conversation history | engine-owned, e.g. ~/.claude/projects/** |
Setting ROVE_HOME_DIR moves Rove's home-rooted product data and compatibility
runtime; ROVE_HOME_DIR remains a fallback. It does not relocate platform
settings or engine-owned conversation stores. That's how the dev sandbox
avoids touching your real ~/.rove task data or runtime.
Three ways people use it
Many attempts at one prompt. Press n in the TUI, or script it:
rove api add --repo "$PWD" \
--agents claude:2,codex:2 \
--prompt "Try independent approaches to simplify the auth flow."Each attempt is its own Task with its own worktree. Workers message their
outcome back to the spawning agent's engine tab (rove api send); compare
with rove api collect, merge with rove api land.
Over SSH, on the machine your code lives on. The daemon and PTY host run
on that machine, so dropping SSH does not end hosted sessions. SSH back in and
run rove to reattach. Clipboard and terminal notifications depend on the
attached terminal connection; attention that happens while disconnected stays
available in Rove's Inbox when you return.
Glossary
- Task. A tracked workspace record: project main, managed worktree, or existing directory.
- Worktree. A git working tree on disk. Rove creates one for each managed Task; project-main and directory Tasks reuse existing directories.
- Terminal Tab. An engine, shell, command/editor, or read-only content surface inside a Task. N per Task.
- Engine. The coding-agent CLI a task runs on.
- Daemon. The background process holding your task list and issues.
- PTY host. The standalone process holding TUI/API live sessions; survives daemon restarts.
rove api. The headless surface for scripts and agents.- Fan out / fan in. Run N attempts of one prompt, then merge the winner.