@sma1lboy/rove 0.9.84 → 0.9.86

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli/rove.js CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import{join as z1}from"node:path";import{createInterface as $1}from"node:readline/promises";import{pathToFileURL as J1}from"node:url";import{spawnSync as h}from"node:child_process";import{constants as t,accessSync as u}from"node:fs";import{homedir as o}from"node:os";import{basename as r,delimiter as l,dirname as i,join as q}from"node:path";import{fileURLToPath as U}from"node:url";var c={$schema:"https://json.schemastore.org/package.json",name:"@sma1lboy/rove",version:"0.9.84",description:"Rove — the agent multiplexer for your terminal. Run coding agents on parallel tasks with isolated worktrees and persistent sessions.",keywords:["terminal","tui","cli","multiplexer","ai-agents","coding-agent","ai-coding-assistant","agentic-ai","parallel-agents","git-worktree","claude-code","codex","llm","developer-tools"],type:"module",packageManager:"bun@1.3.13",bin:{kobe:"dist/cli/kobe.js",rove:"dist/cli/rove.js"},files:["dist/cli","dist/web-ui","dist/skills","dist/*.wav","README.md","LICENSE"],publishConfig:{access:"public"},repository:{type:"git",url:"git+https://github.com/Sma1lboy/rove.git"},homepage:"https://rove.run",bugs:{url:"https://github.com/Sma1lboy/rove/issues"},engines:{bun:">=1.3.11"},scripts:{dev:"ROVE_DEV=1 bun --conditions=browser ./src/cli/rove.ts","dev:kobe":"KOBE_DEV=1 bun --conditions=browser ./src/cli/kobe.ts","dev:mock":"KOBE_DEV=1 bun ./src/tui-react/mock/host.tsx","dev:mock-react":"KOBE_DEV=1 bun ./src/tui-react/mock/host.tsx","dev:mock-react-task-dialogs":"KOBE_DEV=1 bun ./src/tui-react/component/mock-dialogs-host.tsx","dev:mock-react-filetree":"KOBE_DEV=1 bun ./src/tui-react/panes/filetree/mock-host.tsx","dev:mock-react-sidebar":"KOBE_DEV=1 bun ./src/tui-react/panes/sidebar/mock-host.tsx","dev:mock-react-terminal":"KOBE_DEV=1 bun ./src/tui-react/panes/terminal/mock-host.tsx","dev:mock-react-dialogs":"KOBE_DEV=1 bun ./src/tui-react/mock/dialogs-host.tsx","dev:mock-react-workspace":"KOBE_DEV=1 bun ./src/tui-react/workspace/mock-host.tsx","dev:sandbox":"bun run scripts/dev-sandbox.ts run","dev:sandbox:reset":"bun run scripts/dev-sandbox.ts reset",build:"bun run scripts/build.ts","build:with-web":"bun run build",compile:"bun run scripts/compile.ts",typecheck:"tsc --noEmit","check-i18n":"bun run scripts/check-i18n.ts",test:"bun run test:fast && bun run test:socket","perf:golden":"bun scripts/perf-golden.ts","pty:soak":"bun scripts/pty-soak.ts","test:fast":"vitest run --passWithNoTests --minWorkers=1 --maxWorkers=8","test:socket":"KOBE_INCLUDE_SOCKET=1 vitest run test/daemon --pool forks --minWorkers=1 --maxWorkers=4 --passWithNoTests","test:socket:coverage":"KOBE_INCLUDE_SOCKET=1 KOBE_COVERAGE_DAEMON=1 vitest run test/daemon --coverage --pool forks --minWorkers=1 --maxWorkers=4 --passWithNoTests","test:behavior":"KOBE_INCLUDE_BEHAVIOR=1 vitest run test/behavior --pool forks --minWorkers=1 --maxWorkers=1 --retry=2 --passWithNoTests","test:render":"bun test test/render --coverage --coverage-reporter=text --coverage-reporter=lcov --coverage-dir=coverage-render",coverage:"vitest run --coverage --passWithNoTests",bench:"vitest bench --run",lint:"biome check .",knip:"knip-bun",postinstall:"bun run scripts/check-preview-deps.ts || true",prepublishOnly:"bun run typecheck && bun run build","plugin-sandbox":"bun run scripts/plugin-sandbox.ts"},"//":"biome.json + bunfig.toml live at the monorepo root since they apply repo-wide; bun.lock also lives at root (workspace-shared).",dependencies:{"@ansi-tools/parser":"^1.0.15","@opentui/core":"0.4.3","@opentui/react":"0.4.3","@xterm/addon-serialize":"^0.14.0","@xterm/addon-unicode11":"^0.9.0","@xterm/headless":"^6.0.0","node-pty":"^1.1.0",react:"^19.2.8",ws:"^8.18.0"},devDependencies:{"@biomejs/biome":"1.9.4","@sma1lboy/kobe-daemon":"0.7.17","@tsconfig/bun":"1.0.10","@types/bun":"1.3.14","@types/node":"25.6.2","@types/react":"^19.2.0","@vitest/coverage-v8":"2.1.9",knip:"^6.14.2","kobe-web":"workspace:*","react-devtools-core":"^7.0.1",typescript:"5.8.2",vitest:"2.1.9"},trustedDependencies:[]};var x="rove",w="kobe";var E="ROVE_INVOKED_AS";function Y(b=process.env){return b[E]===x?x:w}var K="ROVE_BUN",a="ROVE_NO_BUN_BOOTSTRAP",p="ROVE_SKIP_BUN_CHECK",F=c.engines.bun.match(/\d+\.\d+\.\d+/)?.[0]??"0.0.0",B=(b)=>{try{return u(b,t.X_OK),!0}catch{return!1}},e=(b)=>b==="win32"?"bun.exe":"bun",n=(b)=>{let W=h(b,["--version"],{encoding:"utf8",timeout:5000});if(W.error||W.status!==0)return null;return W.stdout?.split(`
2
+ import{join as z1}from"node:path";import{createInterface as $1}from"node:readline/promises";import{pathToFileURL as J1}from"node:url";import{spawnSync as h}from"node:child_process";import{constants as t,accessSync as u}from"node:fs";import{homedir as o}from"node:os";import{basename as r,delimiter as l,dirname as i,join as q}from"node:path";import{fileURLToPath as U}from"node:url";var c={$schema:"https://json.schemastore.org/package.json",name:"@sma1lboy/rove",version:"0.9.86",description:"Rove — the agent multiplexer for your terminal. Run coding agents on parallel tasks with isolated worktrees and persistent sessions.",keywords:["terminal","tui","cli","multiplexer","ai-agents","coding-agent","ai-coding-assistant","agentic-ai","parallel-agents","git-worktree","claude-code","codex","llm","developer-tools"],type:"module",packageManager:"bun@1.3.13",bin:{kobe:"dist/cli/kobe.js",rove:"dist/cli/rove.js"},files:["dist/cli","dist/web-ui","dist/skills","dist/*.wav","README.md","LICENSE"],publishConfig:{access:"public"},repository:{type:"git",url:"git+https://github.com/Sma1lboy/rove.git"},homepage:"https://rove.run",bugs:{url:"https://github.com/Sma1lboy/rove/issues"},engines:{bun:">=1.3.11"},scripts:{dev:"ROVE_DEV=1 bun --conditions=browser ./src/cli/rove.ts","dev:kobe":"KOBE_DEV=1 bun --conditions=browser ./src/cli/kobe.ts","dev:mock":"KOBE_DEV=1 bun ./src/tui-react/mock/host.tsx","dev:mock-react":"KOBE_DEV=1 bun ./src/tui-react/mock/host.tsx","dev:mock-react-task-dialogs":"KOBE_DEV=1 bun ./src/tui-react/component/mock-dialogs-host.tsx","dev:mock-react-filetree":"KOBE_DEV=1 bun ./src/tui-react/panes/filetree/mock-host.tsx","dev:mock-react-sidebar":"KOBE_DEV=1 bun ./src/tui-react/panes/sidebar/mock-host.tsx","dev:mock-react-terminal":"KOBE_DEV=1 bun ./src/tui-react/panes/terminal/mock-host.tsx","dev:mock-react-dialogs":"KOBE_DEV=1 bun ./src/tui-react/mock/dialogs-host.tsx","dev:mock-react-workspace":"KOBE_DEV=1 bun ./src/tui-react/workspace/mock-host.tsx","dev:sandbox":"bun run scripts/dev-sandbox.ts run","dev:sandbox:reset":"bun run scripts/dev-sandbox.ts reset",build:"bun run scripts/build.ts","build:with-web":"bun run build",compile:"bun run scripts/compile.ts",typecheck:"tsc --noEmit","check-i18n":"bun run scripts/check-i18n.ts",test:"bun run test:fast && bun run test:socket","perf:golden":"bun scripts/perf-golden.ts","pty:soak":"bun scripts/pty-soak.ts","test:fast":"vitest run --passWithNoTests --minWorkers=1 --maxWorkers=8","test:socket":"KOBE_INCLUDE_SOCKET=1 vitest run test/daemon --pool forks --minWorkers=1 --maxWorkers=4 --passWithNoTests","test:socket:coverage":"KOBE_INCLUDE_SOCKET=1 KOBE_COVERAGE_DAEMON=1 vitest run test/daemon --coverage --pool forks --minWorkers=1 --maxWorkers=4 --passWithNoTests","test:behavior":"KOBE_INCLUDE_BEHAVIOR=1 vitest run test/behavior --pool forks --minWorkers=1 --maxWorkers=1 --retry=2 --passWithNoTests","test:render":"bun test test/render --coverage --coverage-reporter=text --coverage-reporter=lcov --coverage-dir=coverage-render",coverage:"vitest run --coverage --passWithNoTests",bench:"vitest bench --run",lint:"biome check .",knip:"knip-bun",postinstall:"bun run scripts/check-preview-deps.ts || true",prepublishOnly:"bun run typecheck && bun run build","plugin-sandbox":"bun run scripts/plugin-sandbox.ts"},"//":"biome.json + bunfig.toml live at the monorepo root since they apply repo-wide; bun.lock also lives at root (workspace-shared).",dependencies:{"@ansi-tools/parser":"^1.0.15","@opentui/core":"0.4.3","@opentui/react":"0.4.3","@xterm/addon-serialize":"^0.14.0","@xterm/addon-unicode11":"^0.9.0","@xterm/headless":"^6.0.0","node-pty":"^1.1.0",react:"^19.2.8",ws:"^8.18.0"},devDependencies:{"@biomejs/biome":"1.9.4","@sma1lboy/kobe-daemon":"0.7.17","@tsconfig/bun":"1.0.10","@types/bun":"1.3.14","@types/node":"25.6.2","@types/react":"^19.2.0","@vitest/coverage-v8":"2.1.9",knip:"^6.14.2","kobe-web":"workspace:*","react-devtools-core":"^7.0.1",typescript:"5.8.2",vitest:"2.1.9"},trustedDependencies:[]};var x="rove",w="kobe";var E="ROVE_INVOKED_AS";function Y(b=process.env){return b[E]===x?x:w}var K="ROVE_BUN",a="ROVE_NO_BUN_BOOTSTRAP",p="ROVE_SKIP_BUN_CHECK",F=c.engines.bun.match(/\d+\.\d+\.\d+/)?.[0]??"0.0.0",B=(b)=>{try{return u(b,t.X_OK),!0}catch{return!1}},e=(b)=>b==="win32"?"bun.exe":"bun",n=(b)=>{let W=h(b,["--version"],{encoding:"utf8",timeout:5000});if(W.error||W.status!==0)return null;return W.stdout?.split(`
3
3
  `)[0]?.trim()??""};function g(b){return b.trim().match(/^v?(\d+\.\d+\.\d+)/)?.[1]??null}function j(b,W=F){let k=g(b),J=g(W);if(!k||!J)return!0;let $=k.split(".").map(Number),z=J.split(".").map(Number);for(let Q=0;Q<3;Q++){let H=$[Q]??0,Z=z[Q]??0;if(H!==Z)return H>Z}return!0}function G(b=process.env){return b[p]==="1"}function C(b={}){let W=b.env??process.env,k=b.platform??process.platform,J=b.home??W.HOME??W.USERPROFILE??o(),$=e(k),z=[],Q=W[K]?.trim();if(Q)z.push(Q);for(let P of(W.PATH??W.Path??"").split(l))if(P)z.push(q(P,$));let H=W.BUN_INSTALL?.trim();if(H)z.push(q(H,"bin",$));if(J)z.push(q(J,".bun","bin",$));let Z=b.launcherDir;if(Z)z.push(q(Z,"..","..","node_modules","bun","bin",$)),z.push(q(Z,"..","..","..","bun","bin",$));return z}function b1(b={}){let W=b.isExecutable??B;return C(b).find((k)=>W(k))??null}function L(b={}){let W=b.isExecutable??B,k=b.bunVersionOf??n;if(G(b.env??process.env))return{bun:b1(b),stale:null,unusable:null};let J=null,$=null;for(let z of C(b)){if(!W(z))continue;let Q=k(z);if(Q===null){$??=z;continue}if(j(Q))return{bun:z,stale:J,unusable:$};J??={path:z,version:g(Q)??Q}}return{bun:null,stale:J,unusable:$}}function O(b){return i(U(b))}function M(b){return r(U(b)).replace(/\.[cm]?[jt]s$/,"")}function W1(b=process.platform){return b==="win32"?["powershell","-NoProfile","-Command","irm bun.sh/install.ps1 | iex"]:["bash","-c","curl -fsSL https://bun.sh/install | bash"]}function T(b=Y(),W=process.platform){let k=W==="win32"?'powershell -c "irm bun.sh/install.ps1 | iex"':"curl -fsSL https://bun.sh/install | bash";return[`${b}: Rove runs on the Bun runtime, and no Bun was found on this machine.`,"","Install Bun, then run this command again:",` ${k}`," npm install -g bun # any platform, if you already have npm","","Or install Bun and Rove together in one step:"," curl -fsSL https://rove.run/install.sh | sh","",`Already have Bun somewhere unusual? Point Rove at it: ${K}=/path/to/bun`,""].join(`
4
4
  `)}function D(b,W,k=Y()){return[`${k}: this machine's Bun is too old for Rove — found ${W} at ${b}, need ${F} or newer.`,"","Rove's terminals are built on Bun's PTY API. An older Bun ignores it silently,","so every terminal and engine tab would open empty and stay empty.","","Upgrade Bun, then run this command again:"," bun upgrade # Bun installed itself (~/.bun)"," brew upgrade bun # Homebrew"," npm install -g bun@latest # npm-managed Bun","",`Have a newer Bun elsewhere? Point Rove at it: ${K}=/path/to/bun`,`Run on this one anyway (unsupported, terminals will be blank): ${p}=1`,""].join(`
5
5
  `)}function s(b,W=Y()){return[`${W}: the Bun at ${b} could not be run — \`${b} --version\` failed or never returned.`,"","Rove skipped it rather than starting through it, which would hang or fail","with a message from that binary instead of this one.","","Reinstall Bun, then run this command again:"," curl -fsSL https://bun.sh/install | bash","",`Have a working Bun elsewhere? Point Rove at it: ${K}=/path/to/bun`,""].join(`
@@ -3,7 +3,7 @@ name: rove
3
3
  description: Use when controlling Rove tasks, parallel coding attempts, hosted agent sessions, task lifecycle, or the daemon-owned issue tracker from a shell. Also the ONLY channel for messaging another agent session on this machine — `rove api send`, never a peer/MCP side channel.
4
4
  ---
5
5
 
6
- <!-- rove-skill-version: 39 — bump in lockstep with KOBE_SKILL_VERSION (src/lib/skill-install.ts). -->
6
+ <!-- rove-skill-version: 41 — bump in lockstep with KOBE_SKILL_VERSION (src/lib/skill-install.ts). -->
7
7
 
8
8
  # Rove shell control
9
9
 
@@ -229,12 +229,22 @@ Four names that have actually been guessed wrong here: `add --vendor` is
229
229
  `--prompt` (`--text` belongs to `note`); `issue-list` has no `--state` at all
230
230
  — filter its JSON yourself.
231
231
 
232
- **[`references/api-flags.md`](references/api-flags.md) is every verb and flag**,
233
- including the groups this file leaves out on purpose: `routine-*` (scheduled
234
- prompts), `workitem-*` (GitHub issues via `gh`), `note`/`note-list` (the repo's
235
- durable field-note store), `read-output`/`digest`/`agent-turns`/`pty-list`, and
236
- the error-code table. Read it when you need a verb that is not above; reach for
237
- `schema` when the binary and that file disagree.
232
+ **[`references/api-flags.md`](references/api-flags.md) is every verb and flag.**
233
+ Find your section by what you were ASKED, not by Rove's noun for it:
234
+
235
+ | You are asked to … | Read section |
236
+ |---|---|
237
+ | schedule / recur / cron / "every morning" / "keep messaging one window" / 定时 / 每天自动 | routines |
238
+ | a GitHub issue, "file it upstream" / 提 issue | workitems |
239
+ | track work in Rove's own backlog, move a kanban card | issues |
240
+ | remember this for the repo, leave a field note / 记一笔 | drive |
241
+ | what did the agent do, per-turn cost, read its screen | read |
242
+ | make / rename / retarget / land / close a task | create / edit / lifecycle |
243
+ | materialize or adopt a checkout | worktree |
244
+ | which engines exist, send Rove product feedback | discover / feedback |
245
+ | an error code came back, `nextCommandArgs` | Error codes |
246
+
247
+ Reach for `schema` when the binary and that file disagree.
238
248
 
239
249
  ```bash
240
250
  rove api schema --verb add # or --group create, --all
@@ -9,6 +9,11 @@ Authoritative source is still the binary — `rove api schema --verb <name>` or
9
9
  `rove api <verb> --help`. Read that when this file and a rejection disagree;
10
10
  the CLI is what ships.
11
11
 
12
+ Every fenced block below is GENERATED from the same verb specs `schema`
13
+ serves (`bun scripts/gen-skill-api-flags.ts`); the prose between them is
14
+ written by hand. Notation: `(REQ)` required, `(x)` the default when the flag is
15
+ omitted, `{a|b}` the allowed values, `--a|--b` two spellings of one choice.
16
+
12
17
  Global: `--pretty` (readable JSON), `--help` (usage, exit).
13
18
  Every `--repo` resolves relative paths against `$PWD` and wants the git toplevel.
14
19
 
@@ -52,24 +57,32 @@ Seeing one of these in guidance means that guidance predates the rename —
52
57
 
53
58
  ## read
54
59
 
60
+ <!-- generated:begin read -->
55
61
  ```text
56
- list (none) every task
57
- get-task --task-id(REQ) one task + .tabs[] — the read before `send --tab`
58
- collect --task-ids <csv> --repo comparison snapshot across tasks
59
- inspect --task-id daemon activity + pty walk + tab snapshots
60
- pty-list (none) live hosted PTYs: key, alive, pid, command, OSC title
61
- read-output --task-id --tab --source[auto|history|terminal] --cursor --limit
62
- digest --repo(REQ) --since-days(7)
63
- agent-turns --task-id --repo --since-days(7) --limit(200)
62
+ list (none)
63
+ get-task --task-id(REQ)
64
+ pty-list (none)
65
+ collect --task-ids <a,b,c> --group --repo
66
+ digest --repo(REQ) --since-days(7)
67
+ agent-turns --task-id --repo --since-days(7) --limit(200)
68
+ inspect --task-id
69
+ read-output --task-id --tab --source{auto|history|terminal}(auto) --cursor --limit(40)
64
70
  ```
71
+ <!-- generated:end -->
72
+
73
+ `get-task` is the read before `send --tab` — one task plus its `.tabs[]`.
74
+ `collect` is the comparison snapshot across tasks: pass `--group <groupId>`
75
+ (what `add --count` returned), a `--task-ids` csv, or a `--repo`; `inspect` is
76
+ the wider diagnostic — daemon activity, a pty walk, and every tab snapshot.
65
77
 
66
78
  `pty-list` is what `NO_ENGINE_TAB`'s hint points at: when `.tabs[]` and reality
67
- disagree, it is the ground truth for what is actually alive.
79
+ disagree, it is the ground truth for what is actually alive — key, alive, pid,
80
+ command, OSC title.
68
81
 
69
- `read-output --limit` maxes at 50 (default 40). `--tab` is terminal-only —
70
- it cannot combine with `--source history`. The cursor is pinned to one
71
- source/session/tab; a moved target returns `SOURCE_CHANGED` rather than
72
- silently paging something else.
82
+ `read-output --limit` maxes at 50. `--tab` is terminal-only — it cannot combine
83
+ with `--source history`. The cursor is pinned to one source/session/tab; a
84
+ moved target returns `SOURCE_CHANGED` rather than silently paging something
85
+ else.
73
86
 
74
87
  `digest` and `agent-turns` are the measurement reads — `digest` aggregates a
75
88
  repo's recent task + routine activity, `agent-turns` is per-turn telemetry
@@ -78,18 +91,22 @@ needs numbers, not when you want to know what a task is doing.
78
91
 
79
92
  ## drive
80
93
 
94
+ <!-- generated:begin drive -->
81
95
  ```text
82
- send --prompt|--prompt-file(REQ) --task-id --tab --command --plain
83
- dispatch --task-id(REQ) --prompt|--prompt-file(REQ) --tab
84
- note --task-id(REQ) --text(REQ)
85
- note-list --repo(REQ)
86
- pane-open --command --task-id --tab --direction[right|down] --placement[split|tab] --title
87
- pane-close --title(REQ) --task-id --tab
88
- tab-close --task-id(REQ) --tab(REQ)
89
- notify --title(REQ) --kind --task-id --source
90
- prompt --title(REQ) --placeholder --initial --timeout
91
- set-active --task-id | --none
96
+ send --task-id --prompt|--prompt-file(REQ) --tab --command --plain --allow-empty
97
+ dispatch --task-id(REQ) --prompt|--prompt-file(REQ) --tab
98
+ note --task-id(REQ) --text(REQ)
99
+ note-list --repo(REQ)
100
+ pane-open --task-id --tab --command --direction{right|down}(right)
101
+ --placement{split|tab}(split) --title
102
+ pane-close --task-id --title(REQ) --tab
103
+ tab-close --task-id(REQ) --tab(REQ)
104
+ notify --title(REQ) --kind(done) --task-id --source
105
+ prompt --title(REQ) --placeholder --initial --timeout
106
+ engine-report --task-id --kind(REQ) --engine --tab --detail
107
+ set-active --task-id --none
92
108
  ```
109
+ <!-- generated:end -->
93
110
 
94
111
  **`note` is the repo's durable field-note store.** One line, a verified
95
112
  conclusion another session could act on — it is appended to the repo's notes
@@ -97,6 +114,10 @@ conclusion another session could act on — it is appended to the repo's notes
97
114
  dispatcher. Read them back with `note-list --repo`. This is the right home for
98
115
  a resolved gotcha; an issue is for work that still needs doing.
99
116
 
117
+ `send --allow-empty` is the escape hatch for a `succeeded:` report from a task
118
+ that legitimately produced no commits (an investigation, a review, a question
119
+ answered); without it such a report is refused with `EMPTY_SUCCESS_REPORT`.
120
+
100
121
  `notify --kind` styles the toast: `done`, `needs_input`, `error` get severity
101
122
  treatment and an unread mark, anything else renders neutrally.
102
123
 
@@ -113,18 +134,36 @@ and ends that tab's hosted PTYs. It accepts engine, shell/command, and content
113
134
  tabs; closing the last tab leaves the task open with no session. A missing or
114
135
  already-closed id returns `TAB_NOT_FOUND` and points back to `get-task`.
115
136
 
137
+ `engine-report` is the engine adapter's own channel for reporting a session
138
+ event (`--kind`) back to the daemon — not a verb you reach for by hand.
139
+
140
+ `set-active` takes one or the other: a `--task-id` to focus, or `--none` to
141
+ clear the shared active task.
142
+
116
143
  ## create / edit / lifecycle
117
144
 
145
+ <!-- generated:begin create,edit,lifecycle -->
118
146
  ```text
119
- add --repo(REQ) + the hot-path flags above
120
- rename --task-id(REQ) --title(REQ)
121
- set-branch --task-id(REQ) --branch(REQ)
122
- set-command --task-id(REQ) --command(REQ) next launch only
123
- set-status --task-id(REQ) --status(REQ)[backlog|in_progress|in_review|done|canceled|error]
124
- pin --task-id(REQ) --pinned(true)
125
- land --task-id(REQ) --strategy[merge|squash] --delete-branch --remove-worktree(true)
126
- delete --task-id(REQ) --force --delete-branch
147
+ add --repo(REQ) --title --branch --base-branch --command --count
148
+ --agents <claude:2,codex:1>
149
+ --status{backlog|in_progress|in_review|done|canceled|error}(backlog) --pin
150
+ --activate(false) --prompt|--prompt-file
151
+ rename --task-id(REQ) --title(REQ)
152
+ set-branch --task-id(REQ) --branch(REQ)
153
+ set-command --task-id(REQ) --command(REQ)
154
+ set-effort --task-id(REQ) --level(REQ)
155
+ set-status --task-id(REQ)
156
+ --status{backlog|in_progress|in_review|done|canceled|error}(REQ)
157
+ pin --task-id(REQ) --pinned(true)
158
+ land --task-id(REQ) --strategy{merge|squash}(merge) --delete-branch
159
+ --remove-worktree(true)
160
+ delete --task-id(REQ) --force --delete-branch --wait
127
161
  ```
162
+ <!-- generated:end -->
163
+
164
+ `set-command` takes effect on the NEXT launch only. `set-effort --level` is
165
+ engine-owned — the levels a vendor accepts come from its registry entry, so
166
+ check `engine-list` rather than guessing.
128
167
 
129
168
  Task `--status` and issue `--status` are DIFFERENT enums — a task is
130
169
  `backlog|in_progress|in_review|done|canceled|error`, an issue is
@@ -135,22 +174,29 @@ ahead (`EMPTY_BRANCH`; `EMPTY_BRANCH_DIRTY_WORKTREE` when the worktree still
135
174
  holds the uncommitted work, with a send-back recovery path). Conflict aborts
136
175
  cleanly and returns the conflicted files.
137
176
 
177
+ `delete --wait` is what turns "queued" into an answer — without it the call
178
+ returns before the worktree is gone.
179
+
138
180
  ## worktree
139
181
 
182
+ <!-- generated:begin worktree -->
140
183
  ```text
141
- ensure-worktree --task-id(REQ)
142
- discover-adoptable --repo(REQ)
143
- adopt --repo(REQ) --worktree(REQ) --branch --title --command
184
+ ensure-worktree --task-id(REQ)
185
+ discover-adoptable --repo(REQ)
186
+ adopt --repo(REQ) --worktree(REQ) --branch --command --title
144
187
  ```
188
+ <!-- generated:end -->
145
189
 
146
190
  ## issues (daemon-owned)
147
191
 
192
+ <!-- generated:begin issues -->
148
193
  ```text
149
194
  issue-list --repo(REQ)
150
195
  issue-create --repo(REQ) --title(REQ) --body
151
- issue-update --repo(REQ) --id(REQ,int) --title --body --task
152
- issue-set-status --repo(REQ) --id(REQ,int) --status(REQ)[open|doing|hold|done]
196
+ issue-set-status --repo(REQ) --id(REQ) --status{open|doing|hold|done}(REQ)
197
+ issue-update --repo(REQ) --id(REQ) --title --body --task
153
198
  ```
199
+ <!-- generated:end -->
154
200
 
155
201
  `--id` is an int, not the ULID a task uses. `issue-update --task <taskId>` is
156
202
  the kanban "move to In progress"; `--task none` unlinks. Kanban semantics are
@@ -161,31 +207,44 @@ in SKILL.md — do not move cards with `issue-set-status doing`.
161
207
  Read-only against the repo's real GitHub issues; nothing is copied into Rove's
162
208
  own store. These are the INBOUND user reports; Rove issues are the backlog.
163
209
 
210
+ <!-- generated:begin workitems -->
164
211
  ```text
165
- workitem-list --repo(REQ) --state[open|closed|all] --limit(20,max 50) --search --assignee --label
166
- workitem-start --repo(REQ) --number(REQ,int) --vendor --base-branch
212
+ workitem-list --repo(REQ) --state{open|closed|all}(open) --limit(20) --search --assignee
213
+ --label
214
+ workitem-start --repo(REQ) --number(REQ) --vendor{claude|codex|copilot|kimi}
215
+ --base-branch
167
216
  ```
217
+ <!-- generated:end -->
168
218
 
169
- `workitem-start` creates a worktree + engine whose first message carries the
170
- issue title, body, and URL, and keeps a link back to the issue. Note it takes
171
- `--vendor` (an engine enum), not `--command` — the one place the older
172
- vocabulary survives.
219
+ `workitem-list --limit` caps at 50. `workitem-start` creates a worktree +
220
+ engine whose first message carries the issue title, body, and URL, and keeps a
221
+ link back to the issue. Note it takes `--vendor` (an engine enum), not
222
+ `--command` — the one place the older vocabulary survives.
173
223
 
174
224
  ## routines (scheduled prompts)
175
225
 
176
- Each firing creates a FRESH task worktree, engine, delivered prompt. An
177
- enabled routine holds the daemon alive so it fires with no TUI attached.
226
+ A cron rule + a prompt + a repo, owned by the daemon. By default each firing
227
+ creates a FRESH task worktree, engine, delivered prompt. With
228
+ `--persistent-session` every firing lands in ONE standing task as the next
229
+ turn of the same conversation (a Claude Code-style routine: one window, one
230
+ vendor, messages keep arriving). An enabled routine holds the daemon alive so
231
+ it fires with no TUI attached.
178
232
 
233
+ <!-- generated:begin routine -->
179
234
  ```text
180
235
  routine-list (none)
181
- routine-create --repo(REQ) --name(REQ) --prompt(REQ) --schedule(REQ)
182
- --vendor --base-branch --precheck --precheck-timeout(120) --grace(60) --disabled
183
- routine-update --id(REQ) --name --prompt --schedule --vendor --base-branch --precheck --precheck-timeout --grace
184
- routine-set-enabled --id(REQ) --enabled(REQ,bool)
236
+ routine-create --repo(REQ) --name(REQ) --prompt|--prompt-file(REQ) --schedule(REQ)
237
+ --vendor{claude|codex|copilot|kimi} --base-branch --precheck
238
+ --precheck-timeout(120) --grace(60) --persistent-session --disabled
239
+ routine-update --id(REQ) --name --prompt|--prompt-file --schedule
240
+ --vendor{claude|codex|copilot|kimi} --base-branch --precheck
241
+ --precheck-timeout(120) --grace(60) --persistent-session
242
+ routine-set-enabled --id(REQ) --enabled(REQ)
185
243
  routine-delete --id(REQ)
186
244
  routine-run-now --id(REQ)
187
245
  routine-runs --id(REQ)
188
246
  ```
247
+ <!-- generated:end -->
189
248
 
190
249
  `--schedule` is five-field cron in the DAEMON HOST's local time
191
250
  (`'0 9 * * MON-FRI'`). `--precheck` is a shell command run in the repo before
@@ -194,21 +253,50 @@ which is the cheap way to not burn a turn on "nothing to do". `--grace` is how
194
253
  late a missed occurrence may still run after the daemon was down; only the
195
254
  most recent missed occurrence ever runs.
196
255
 
256
+ Pick the mode by what the prompt DOES. A routine that EDITS code wants the
257
+ default: each run is its own branch you can review and land; a week of runs
258
+ piled onto one branch is a branch nobody can merge. A routine that ASKS the
259
+ same question every day (a trend check, a digest, "what changed since
260
+ yesterday?") is worthless from zero each morning — give it
261
+ `--persistent-session`. Its standing task is folded behind the sidebar's
262
+ `N routine sessions` row, raises an Inbox entry when a turn finishes, and
263
+ never wins the cold-start "which task to open" fallback. If the engine process
264
+ is gone when the next firing arrives (an overnight gap usually means it is),
265
+ the daemon respawns it in the SAME worktree — files and branch carry over, the
266
+ conversation does not — and records that run as `revived`, not `dispatched`.
267
+
268
+ **Routines take `--prompt` only.** Unlike `send`/`add`/`dispatch` there is no
269
+ `--prompt-file` here, so a prompt with backticks, `$vars` or quotes has no
270
+ escape hatch — write it with single quotes and keep `$` out of it, or set it
271
+ from the TUI.
272
+
273
+ A bare `--enabled` means true, so pausing a routine is
274
+ `routine-set-enabled --id <id> --enabled=false` (the same `=false` spelling
275
+ `pin --pinned=false` uses).
276
+
197
277
  `routine-update --schedule` re-anchors the next run. `--precheck ''` clears it.
198
278
  `routine-run-now` skips the precheck deliberately (asking for it IS the answer)
199
279
  and does not shift the schedule. `routine-delete` leaves already-created tasks
200
280
  alone.
201
281
 
202
- Run statuses from `routine-runs`: `dispatched`, `skipped_precheck` (nothing to
203
- do), `skipped_missed`, `skipped_unavailable`, `dispatch_failed`.
282
+ Run statuses from `routine-runs`: `dispatched`, `revived` (standing session
283
+ respawned — files kept, conversation did not), `deferred` (composer busy; the
284
+ prompt is queued in the Inbox, NOT lost), `skipped_precheck` (nothing to do),
285
+ `skipped_missed`, `skipped_unavailable`, `dispatch_failed`.
204
286
 
205
287
  ## discover / feedback
206
288
 
289
+ <!-- generated:begin discover,feedback -->
207
290
  ```text
208
- schema --verb <name> | --group <g> | --all (bare = compact index)
209
- engine-list (none) ids + RAW launch command + protocol
210
- feedback --title(REQ) --body(REQ) --category(feedback)
291
+ schema --verb --group --all
292
+ engine-list (none)
293
+ feedback --title(REQ) --body(REQ) --category(feedback)
211
294
  ```
295
+ <!-- generated:end -->
296
+
297
+ Bare `schema` is the compact index; `--verb <name>` drills into one verb,
298
+ `--group <g>` lists one group, `--all` dumps everything. `engine-list` is the
299
+ ids + RAW launch command + protocol.
212
300
 
213
301
  `feedback` opens a GitHub Discussion in the Rove repo through `gh` — Rove's own
214
302
  product feedback channel, not a way to file work for another project (that is
@@ -225,6 +313,8 @@ Errors go to stderr as `{"error":{"message","code",...}}`. Most carry `hint`
225
313
  | `BAD_FLAG` | flag not on that verb | check the table above, then `schema --verb <v>` |
226
314
  | `TASK_NOT_FOUND` | id deleted or mistyped | `rove api list` |
227
315
  | `NO_ENGINE_TAB` | live tabs exist, none is an engine | `--tab tab-N` from `pty-list`, or `--tab new` |
316
+ | `TAB_NOT_FOUND` | `--tab` names a closed/unknown tab | `get-task` for the live `.tabs[]` |
228
317
  | `DISPATCHER_UNREACHABLE` | bare `send` reply, dispatcher gone | nothing alive to reply to — never silently spawns |
318
+ | `EMPTY_SUCCESS_REPORT` | `succeeded:` from a branch with 0 commits | commit first, or say so with `--allow-empty` |
229
319
  | `SOURCE_CHANGED` | `read-output` cursor's target moved | re-read without the cursor |
230
320
  | `EMPTY_BRANCH` | `land` on zero commits ahead | the worker committed nothing |
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "$schema": "https://json.schemastore.org/package.json",
3
3
  "name": "@sma1lboy/rove",
4
- "version": "0.9.84",
4
+ "version": "0.9.86",
5
5
  "description": "Rove — the agent multiplexer for your terminal. Run coding agents on parallel tasks with isolated worktrees and persistent sessions.",
6
6
  "keywords": [
7
7
  "terminal",