Rove

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:

KindDirectoryGit isolation
Project mainA saved repository's existing checkoutUses the checkout as-is; no Rove-created branch or worktree
Managed taskA Rove-created worktreeOwn branch and worktree
Directory taskAn 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 tabs

A 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 enter and tab to its STATUS field to move it between columns; d on the board deletes the story outright.
  • Agents and scripts. rove api issue-list, issue-create, issue-update (--status moves a card), issue-delete.

Issues track what to do; the changelog records what shipped.

Where things live on disk

WhatWhere
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 historyengine-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.

On this page