Rove

Engines

An engine is the AI coding CLI a task runs on — claude, codex, copilot, kimi, or one you register yourself. Rove runs the real interactive CLI inside the task's terminal session.

Managed task = one git worktree + one branch + one or more terminal tabs

A Task can own several terminal tabs. Each engine tab has its own PTY process and conversation, but opening another engine or shell tab does not create another worktree: ordinary sibling tabs use the same Task directory. Two agents in sibling tabs can therefore edit each other's work; create another task when you need git-level isolation and a separate branch.

Which engines are supported

EngineIdAccount detectActivity badgeHistoryModel picker
Claude Codeclaude
Codexcodex✓ (after you trust hooks)✓ + effort levels
GitHub Copilotcopilotpartial
Kimi Codekimihandoff only
Anything you registercustom

Claude Code is the default and the most complete: its quota probe drives rate-limit auto-resume and the Settings usage dashboard.

Kimi is partial. Rove finds the binary, reads its login state, and can locate each session's transcript — enough to watch it for activity and to hand the conversation to another engine. It still doesn't parse that transcript (the wire format is unverified), so auto-title keeps the placeholder and rove api read-output reports engine_unsupported rather than guessing.

Picking an engine

Per task, at creation time, or with v in the sidebar. The default for new tasks comes from Settings → Engines (defaultVendor), and Rove remembers the last engine you used per project.

Engines whose CLI isn't installed are hidden from the new-task dialog. Custom engines always show — you added it, so Rove assumes you meant it.

Reasoning effort

Codex accepts none, low, medium, high, xhigh, passed as -c model_reasoning_effort=<level>. Other engines have no effort flag Rove can drive; a selected effort is ignored there rather than passed through.

Workspace trust

Claude, Codex, and Kimi each gate a first launch in a never-seen directory behind a trust dialog — and every task worktree is such a directory, so a hosted session can't answer it (Kimi's dialog even exits the process when a pasted first message lands on "Don't trust"). Before spawning an engine into a Rove-created worktree, Rove writes the vendor's own trust record for that path — ~/.claude.json projects[<path>].hasTrustDialogAccepted, ~/.codex/config.toml [projects."<path>"] trust_level = "trusted", or ~/.kimi-code/workspace-trust/ — merging into existing entries, never clobbering. This only ever fires for worktrees Rove itself created from a repo you already work in; your own directories are untouched.

Custom launch commands

Override any engine's launch command in Settings → Engines, or by hand in state.json:

{ "engineCommand.claude": "claude --model opus" }

Quotes are honored, so claude --append-system-prompt "be terse" works. For Claude, Rove appends its own --session-id so the tab stays resumable — but if your override already pins the conversation (--session-id, --resume, --continue, --from-pr), Rove leaves it alone.

If an engine exits non-zero, the terminal stays open with a banner pointing at Settings → Engines, and drops you into a shell.

Activity badges

The sidebar shows what each session is doing: working, done, or needs input. There's nothing to configure — Rove reads the engine's own hook events, falling back to its transcript when hooks aren't available.

One thing worth knowing: only claude and codex can show "needs input". Distinguishing "waiting on a permission prompt" from "thinking" requires a hook; the other engines top out at working/done. Rove labels the gap honestly rather than guessing.

Codex won't run Rove's hooks until you trust them once via /hooks, so Codex badges stay dark until you approve. That's by design — Rove writes the hook definition but never bypasses the trust prompt for you.

Mechanics: design/engine-internals.md.

Resuming and forking

Resume. A Claude tab whose process is gone (reboot, unarchive) relaunches into the same conversation instead of a blank one. A tab that never sent a first message isn't resumed — there's no transcript yet. Codex, Copilot, Kimi, and custom engines can't take a caller-set session id, so their tabs relaunch fresh.

ctrl+a y opens the resume picker for the active task.

Continue in a new tab. ctrl+a c opens the continuation flow in the same worktree. What happens depends on the source and destination engines:

Same engine → a native fork only when that CLI can actually branch a conversation. The two resulting tabs keep the source context and then diverge:

EngineNative fork?How
claude--resume <src> --fork-session
codexcodex fork <src>
copilotstarts a fresh Copilot session with a transcript handoff
kimistarts a fresh Kimi session with a transcript handoff
customrefused; Rove doesn't know its session store

Copilot's --resume and Kimi's -S reopen rather than branch, which would put two live processes on one transcript. Rove therefore uses the same transcript handoff as a cross-engine continuation: the new tab is a fresh conversation that reads where the previous one stopped. A custom engine without a known session store is refused instead of silently opening a blank continuation.

Different built-in engine → a handoff. This is the move that saves you when you hit a usage limit mid-task. The new engine starts fresh with a first prompt that points it at the old session's transcript and asks it to state where the previous one stopped — that sentence is how you check the handoff landed.

Handoffs work in every direction between the four built-ins — the receiving agent is handed the previous transcript's path and reads it in whatever format it finds, so no format ever has to be converted. Only a custom engine can't be a handoff source (Rove doesn't know its session store); that case is refused with a reason. A handoff to a custom engine works fine.

Custom engines

Any CLI can be an engine. Settings → Engines → + Add engine asks for an id, a launch command, and an optional display name. Or by hand:

{
  "customEngineIds": ["aider"],
  "engineCommand.aider": "aider --model sonnet",
  "engineName.aider": "Aider"
}

Being in customEngineIds is the registration.

What you get: a real hosted session with the full keep-alive and per-repo init treatment. What you don't: no history reader, no account detection, no activity badge, no session resume. Rove launches your CLI and stays out of the way rather than pretending to understand its internals.

Press x on an engine row in Settings to reset a built-in's overrides, or remove a custom engine entirely.

Where conversations are stored

Engines own their own history. Rove reads it, never writes it.

EngineTranscripts
claude~/.claude/projects/<encoded-cwd>/<sessionId>.jsonl
codex~/.codex/sessions/<YYYY>/<MM>/<DD>/rollout-*.jsonl
copilot~/.copilot/session-state/<id>/events.jsonl
kimi~/.kimi-code/sessions/<workspace>/<session>/agents/main/wire.jsonl

That's why a crash never loses a conversation, and why history survives rove reset and a machine reboot.

On this page