@sma1lboy/rove 0.9.110 → 0.9.148

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.
Files changed (194) hide show
  1. package/README.md +0 -1
  2. package/dist/cli/chunk-003tvywc.js +3 -0
  3. package/dist/cli/chunk-0b48bpkd.js +2 -0
  4. package/dist/cli/chunk-0dv2xssg.js +19 -0
  5. package/dist/cli/chunk-0sm2k04y.js +3 -0
  6. package/dist/cli/chunk-0vmrteyg.js +3 -0
  7. package/dist/cli/chunk-13s8rnk5.js +3 -0
  8. package/dist/cli/chunk-1kktfmtg.js +4 -0
  9. package/dist/cli/chunk-1rkb0j1j.js +3 -0
  10. package/dist/cli/chunk-1tx1s5v6.js +2 -0
  11. package/dist/cli/chunk-1x0vahnn.js +2 -0
  12. package/dist/cli/chunk-20pt9yqh.js +4 -0
  13. package/dist/cli/chunk-2brn8e1y.js +3 -0
  14. package/dist/cli/chunk-2fypr41w.js +3 -0
  15. package/dist/cli/chunk-2jxdzw4r.js +3 -0
  16. package/dist/cli/chunk-2pqqvse3.js +2 -0
  17. package/dist/cli/chunk-39s1ndtm.js +106 -0
  18. package/dist/cli/chunk-3bfm4hrs.js +3 -0
  19. package/dist/cli/chunk-3rqa4pyt.js +28 -0
  20. package/dist/cli/chunk-3ry6prwn.js +3 -0
  21. package/dist/cli/chunk-3ztek08w.js +4 -0
  22. package/dist/cli/chunk-49s2zc0h.js +8 -0
  23. package/dist/cli/chunk-4wwx51m5.js +3 -0
  24. package/dist/cli/chunk-5ar3vspk.js +9 -0
  25. package/dist/cli/chunk-5bn91n19.js +3 -0
  26. package/dist/cli/chunk-5c3d1y0r.js +2 -0
  27. package/dist/cli/chunk-5hhvrvgm.js +8 -0
  28. package/dist/cli/chunk-6dn6h640.js +3 -0
  29. package/dist/cli/chunk-6frfschk.js +2 -0
  30. package/dist/cli/chunk-6xppe9bj.js +3 -0
  31. package/dist/cli/chunk-6zwg6me2.js +4 -0
  32. package/dist/cli/chunk-764bsyb0.js +1 -0
  33. package/dist/cli/chunk-79gqh5p2.js +5 -0
  34. package/dist/cli/chunk-7ngv7v9g.js +9 -0
  35. package/dist/cli/chunk-7nhdvr5v.js +4 -0
  36. package/dist/cli/chunk-7pfnda5z.js +12 -0
  37. package/dist/cli/chunk-7q67dz4c.js +3 -0
  38. package/dist/cli/chunk-8ddjfc2v.js +4 -0
  39. package/dist/cli/chunk-8g456mmt.js +3 -0
  40. package/dist/cli/chunk-8sbevss4.js +4 -0
  41. package/dist/cli/chunk-91j0an0j.js +2 -0
  42. package/dist/cli/chunk-99devyxr.js +2 -0
  43. package/dist/cli/chunk-9c1e5z6a.js +3 -0
  44. package/dist/cli/chunk-a4a4qaa2.js +3 -0
  45. package/dist/cli/chunk-adez6hq4.js +69 -0
  46. package/dist/cli/chunk-aq912vvw.js +3 -0
  47. package/dist/cli/chunk-arf294te.js +2 -0
  48. package/dist/cli/chunk-awsawfrm.js +2 -0
  49. package/dist/cli/chunk-aynx3d2a.js +2 -0
  50. package/dist/cli/chunk-b8d162tf.js +3 -0
  51. package/dist/cli/chunk-b99tf0jr.js +3 -0
  52. package/dist/cli/chunk-bj59a9mg.js +3 -0
  53. package/dist/cli/chunk-c6mthex1.js +5 -0
  54. package/dist/cli/chunk-cb2fpajx.js +3 -0
  55. package/dist/cli/chunk-cbkje3aw.js +2 -0
  56. package/dist/cli/chunk-df7qe9y7.js +4 -0
  57. package/dist/cli/chunk-dkxhmj9k.js +25 -0
  58. package/dist/cli/chunk-dqndd97s.js +7 -0
  59. package/dist/cli/chunk-dvabncrk.js +7 -0
  60. package/dist/cli/chunk-dvcb6mk4.js +3 -0
  61. package/dist/cli/chunk-dw853n4w.js +3 -0
  62. package/dist/cli/chunk-dx6b3dv8.js +7 -0
  63. package/dist/cli/chunk-e1g9mvww.js +11 -0
  64. package/dist/cli/chunk-ef11h2am.js +3 -0
  65. package/dist/cli/chunk-ef39ym8f.js +3 -0
  66. package/dist/cli/chunk-eq5f3z2f.js +3 -0
  67. package/dist/cli/chunk-ewdhz3dv.js +2 -0
  68. package/dist/cli/chunk-f6zsej8e.js +3 -0
  69. package/dist/cli/chunk-g1ybdgad.js +25 -0
  70. package/dist/cli/chunk-gbasmvsc.js +4 -0
  71. package/dist/cli/chunk-gjf604bb.js +3 -0
  72. package/dist/cli/chunk-gm3vj0fv.js +5 -0
  73. package/dist/cli/chunk-grh6dvfv.js +5 -0
  74. package/dist/cli/chunk-gwcneg6c.js +2 -0
  75. package/dist/cli/chunk-h5j8b87f.js +2 -0
  76. package/dist/cli/chunk-h79zfebh.js +7 -0
  77. package/dist/cli/chunk-h82kzdsn.js +3 -0
  78. package/dist/cli/chunk-hape5vwj.js +3 -0
  79. package/dist/cli/chunk-hg5x2wr0.js +3 -0
  80. package/dist/cli/chunk-j4xfsn9g.js +5 -0
  81. package/dist/cli/chunk-jfqbq12b.js +18 -0
  82. package/dist/cli/chunk-jsss3ze7.js +11 -0
  83. package/dist/cli/chunk-jvpzy378.js +3 -0
  84. package/dist/cli/chunk-jvxh93nz.js +3 -0
  85. package/dist/cli/chunk-jyv82gf0.js +258 -0
  86. package/dist/cli/chunk-k3ksts6g.js +3 -0
  87. package/dist/cli/chunk-kdrrw9tm.js +2 -0
  88. package/dist/cli/chunk-kg11c1py.js +3 -0
  89. package/dist/cli/chunk-kwe61yx7.js +3 -0
  90. package/dist/cli/chunk-m0fz6g32.js +16 -0
  91. package/dist/cli/chunk-mb5m7ex7.js +2 -0
  92. package/dist/cli/chunk-me77sx3d.js +3 -0
  93. package/dist/cli/chunk-mfqjdpd8.js +2 -0
  94. package/dist/cli/chunk-mggca3k4.js +4 -0
  95. package/dist/cli/chunk-mjvq39gf.js +4 -0
  96. package/dist/cli/chunk-mrwee8sj.js +3 -0
  97. package/dist/cli/chunk-my20q579.js +3 -0
  98. package/dist/cli/chunk-nceh1q3d.js +12 -0
  99. package/dist/cli/chunk-ncsgawg7.js +2 -0
  100. package/dist/cli/chunk-nm6adny4.js +4 -0
  101. package/dist/cli/chunk-np07kccr.js +4 -0
  102. package/dist/cli/chunk-nrnjt5b6.js +2 -0
  103. package/dist/cli/chunk-p7kztgsd.js +4 -0
  104. package/dist/cli/chunk-pbqwegjy.js +2 -0
  105. package/dist/cli/chunk-pcvk98rr.js +3 -0
  106. package/dist/cli/chunk-pdh5w4ht.js +3 -0
  107. package/dist/cli/chunk-pdj8kqa1.js +74 -0
  108. package/dist/cli/chunk-pw6yfj10.js +3 -0
  109. package/dist/cli/chunk-q6579rbz.js +3 -0
  110. package/dist/cli/chunk-q7dr9eh6.js +3 -0
  111. package/dist/cli/chunk-qkehg2c1.js +3 -0
  112. package/dist/cli/chunk-qtke4x42.js +3 -0
  113. package/dist/cli/chunk-rxvbm4vt.js +7 -0
  114. package/dist/cli/chunk-s66eh0pw.js +8 -0
  115. package/dist/cli/chunk-s76r56rj.js +3 -0
  116. package/dist/cli/chunk-sdyzxayr.js +3 -0
  117. package/dist/cli/chunk-svpn3av1.js +3 -0
  118. package/dist/cli/chunk-t0kta7rb.js +5 -0
  119. package/dist/cli/chunk-v5893dx3.js +2 -0
  120. package/dist/cli/chunk-vapjtyv9.js +7 -0
  121. package/dist/cli/chunk-vpzvcxc1.js +3 -0
  122. package/dist/cli/chunk-vqpa27cf.js +15 -0
  123. package/dist/cli/chunk-vws0j65e.js +4 -0
  124. package/dist/cli/chunk-vyb5a2rh.js +4 -0
  125. package/dist/cli/chunk-vzxbe80f.js +7 -0
  126. package/dist/cli/chunk-w5xy83ze.js +2 -0
  127. package/dist/cli/chunk-wqfp8d9w.js +3 -0
  128. package/dist/cli/chunk-wsvf9eka.js +33 -0
  129. package/dist/cli/chunk-x760j10f.js +3 -0
  130. package/dist/cli/chunk-x930m5fs.js +2 -0
  131. package/dist/cli/chunk-xbc3gcry.js +2 -0
  132. package/dist/cli/chunk-xy8be792.js +3 -0
  133. package/dist/cli/chunk-xzrqnpmh.js +4 -0
  134. package/dist/cli/chunk-y2yq6zca.js +3 -0
  135. package/dist/cli/chunk-yhcz2d2r.js +34 -0
  136. package/dist/cli/chunk-yk2ha5yj.js +3 -0
  137. package/dist/cli/chunk-ykvk2546.js +3 -0
  138. package/dist/cli/chunk-ympakh8w.js +6 -0
  139. package/dist/cli/chunk-yn5a7xcv.js +2 -0
  140. package/dist/cli/chunk-zb56ck5f.js +3 -0
  141. package/dist/cli/index.js +15 -850
  142. package/dist/cli/kobe-run.js +1 -858
  143. package/dist/cli/kobe.js +6 -6
  144. package/dist/cli/pty-host-node.mjs +167 -50
  145. package/dist/cli/rove-run.js +1 -858
  146. package/dist/cli/rove.js +6 -6
  147. package/dist/skills/rove/SKILL.md +29 -10
  148. package/dist/skills/rove/references/api-flags.md +35 -13
  149. package/dist/web-ui/assets/{ChatTerminal-BshL3M8G.js → harness-CYGJ4uoR.js} +19 -20
  150. package/dist/web-ui/assets/index-BTJ-X_4s.js +10 -0
  151. package/dist/web-ui/assets/index-Cs2vPLNB.css +1 -0
  152. package/dist/web-ui/index.html +2 -9
  153. package/dist/web-ui/pty-server.mjs +4 -5
  154. package/package.json +1 -1
  155. package/dist/web-ui/assets/AppShell-BGRIs5hW.js +0 -5
  156. package/dist/web-ui/assets/AppShell-HiyATJse.css +0 -1
  157. package/dist/web-ui/assets/Board-Bt3cwp25.js +0 -1
  158. package/dist/web-ui/assets/BoardPeek-BKR-tpS2.js +0 -2
  159. package/dist/web-ui/assets/ChatTranscript-B67_nnd6.js +0 -1
  160. package/dist/web-ui/assets/ConfirmDialog-kyA624OF.js +0 -1
  161. package/dist/web-ui/assets/IssueIntakePanel-BMP8Vc3E.js +0 -1
  162. package/dist/web-ui/assets/IssuePeek-C7afOYax.js +0 -1
  163. package/dist/web-ui/assets/IssuesPage-DwRaBB-m.js +0 -1
  164. package/dist/web-ui/assets/SettingsPage-CC1sDI8j.js +0 -2
  165. package/dist/web-ui/assets/SlideOver-B4sEOPyN.css +0 -1
  166. package/dist/web-ui/assets/SlideOver-Dq0ifiEm.js +0 -173
  167. package/dist/web-ui/assets/ViewToggle-mNsDLJp8.js +0 -1
  168. package/dist/web-ui/assets/WorkspaceTabs-DLzL-Tad.css +0 -1
  169. package/dist/web-ui/assets/WorkspaceTabs-ifAIZ5Fj.js +0 -3
  170. package/dist/web-ui/assets/active-task-gVYiAkLv.js +0 -1
  171. package/dist/web-ui/assets/arrow-left-CavMh90a.js +0 -1
  172. package/dist/web-ui/assets/board-DoArj55z.js +0 -1
  173. package/dist/web-ui/assets/chips-CS9PLtWy.js +0 -1
  174. package/dist/web-ui/assets/createLucideIcon-CuIQtyYV.js +0 -1
  175. package/dist/web-ui/assets/external-link-Du2dMe8S.js +0 -1
  176. package/dist/web-ui/assets/external-store-BCBJewGi.js +0 -1
  177. package/dist/web-ui/assets/harness-ClZMF1wx.js +0 -1
  178. package/dist/web-ui/assets/index-B4xJZEqf.js +0 -10
  179. package/dist/web-ui/assets/index-BnjD9Q-3.css +0 -1
  180. package/dist/web-ui/assets/issues-DwrKXp9c.js +0 -4
  181. package/dist/web-ui/assets/issues-ISAZBras.js +0 -1
  182. package/dist/web-ui/assets/lazy-issue-panels-DvXQJhKy.js +0 -6
  183. package/dist/web-ui/assets/rotate-cw-BXdpzm3v.js +0 -1
  184. package/dist/web-ui/assets/routes-DEEkL5gG.js +0 -1
  185. package/dist/web-ui/assets/store-BLM6nh6E.js +0 -2
  186. package/dist/web-ui/assets/tabs-CMZJhcSB.js +0 -1
  187. package/dist/web-ui/assets/task._taskId-BCIhg4IQ.js +0 -1
  188. package/dist/web-ui/assets/terminal-DOp1a9g6.js +0 -1
  189. package/dist/web-ui/assets/text-match-DW3sD-Rt.js +0 -1
  190. package/dist/web-ui/assets/time-kviT26Tm.js +0 -1
  191. package/dist/web-ui/assets/toast-C4yXq6hM.js +0 -1
  192. package/dist/web-ui/assets/web-transport-Beqz2mQ8.js +0 -1
  193. package/dist/web-ui/assets/worktrees-BGvJOG2b.js +0 -1
  194. /package/dist/web-ui/assets/{ChatTerminal-BrP-ENHg.css → harness-BrP-ENHg.css} +0 -0
package/dist/cli/rove.js CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
- import{join as $1}from"node:path";import{createInterface as J1}from"node:readline/promises";import{pathToFileURL as Q1}from"node:url";import{spawnSync as L}from"node:child_process";import{constants as u,accessSync as l}from"node:fs";import{homedir as t}from"node:os";import{basename as o,delimiter as r,dirname as i,join as Y}from"node:path";import{fileURLToPath as C}from"node:url";var U={$schema:"https://json.schemastore.org/package.json",name:"@sma1lboy/rove",version:"0.9.110",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:sandbox":"bun run scripts/dev-sandbox.ts run","dev:sandbox:reset":"bun run scripts/dev-sandbox.ts reset",build:"bun run scripts/build.ts",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.18","@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","react-devtools-core":"^7.0.1",typescript:"5.8.2",vitest:"2.1.9"},trustedDependencies:[]};var x="rove",j="kobe";var E="ROVE_INVOKED_AS";function F(W=process.env){return W[E]===x?x:j}var k="ROVE_BUN",a="ROVE_NO_BUN_BOOTSTRAP",M="ROVE_SKIP_BUN_CHECK",G=U.engines.bun.match(/\d+\.\d+\.\d+/)?.[0]??"0.0.0",T=(W)=>{try{return l(W,u.X_OK),!0}catch{return!1}},n=(W)=>W==="win32"?"bun.exe":"bun",e=(W)=>{let b=L(W,["--version"],{encoding:"utf8",timeout:5000});if(b.error||b.status!==0)return null;return b.stdout?.split(`
3
- `)[0]?.trim()??""};function K(W){return W.trim().match(/^v?(\d+\.\d+\.\d+)/)?.[1]??null}function P(W,b=G){let z=K(W),Q=K(b);if(!z||!Q)return!0;let J=z.split(".").map(Number),$=Q.split(".").map(Number);for(let X=0;X<3;X++){let q=J[X]??0,H=$[X]??0;if(q!==H)return q>H}return!0}function g(W=process.env){return W[M]==="1"}function p(W={}){let b=W.env??process.env,z=W.platform??process.platform,Q=W.home??b.HOME??b.USERPROFILE??t(),J=n(z),$=[],X=b[k]?.trim();if(X)$.push(X);for(let D of(b.PATH??b.Path??"").split(r))if(D)$.push(Y(D,J));let q=b.BUN_INSTALL?.trim();if(q)$.push(Y(q,"bin",J));if(Q)$.push(Y(Q,".bun","bin",J));let H=W.launcherDir;if(H)$.push(Y(H,"..","..","node_modules","bun","bin",J)),$.push(Y(H,"..","..","..","bun","bin",J));return $}function W1(W={}){let b=W.isExecutable??T;return p(W).find((z)=>b(z))??null}function w(W={}){let b=W.isExecutable??T,z=W.bunVersionOf??e;if(g(W.env??process.env))return{bun:W1(W),stale:null,unusable:null};let Q=null,J=null;for(let $ of p(W)){if(!b($))continue;let X=z($);if(X===null){J??=$;continue}if(P(X))return{bun:$,stale:Q,unusable:J};Q??={path:$,version:K(X)??X}}return{bun:null,stale:Q,unusable:J}}function B(W){return i(C(W))}function O(W){return o(C(W)).replace(/\.[cm]?[jt]s$/,"")}function b1(W=process.platform){return W==="win32"?["powershell","-NoProfile","-Command","irm bun.sh/install.ps1 | iex"]:["bash","-c","curl -fsSL https://bun.sh/install | bash"]}function y(W=F(),b=process.platform){let z=b==="win32"?'powershell -c "irm bun.sh/install.ps1 | iex"':"curl -fsSL https://bun.sh/install | bash";return[`${W}: Rove runs on the Bun runtime, and no Bun was found on this machine.`,"","Install Bun, then run this command again:",` ${z}`," 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
- `)}function h(W,b,z=F()){return[`${z}: this machine's Bun is too old for Rove — found ${b} at ${W}, need ${G} 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): ${M}=1`,""].join(`
5
- `)}function A(W,b=F()){return[`${b}: the Bun at ${W} could not be run — \`${W} --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(`
6
- `)}function f(W=process.env,b=process.stdin,z=process.stdout){if(W[a]==="1")return!1;if(W.CI==="true"||W.CI==="1")return!1;return Boolean(b.isTTY&&z.isTTY)}function I(W={},b=L){let z=W.platform??process.platform,[Q,...J]=b1(z);if(!Q)return null;let $=b(Q,J,{stdio:"inherit"});if($.error||$.status!==0)return null;return w(W).bun}function z1(W){if(typeof W.status==="number")return W.status;if(W.signal)return 128+(Object.hasOwn(V,W.signal)?V[W.signal]:0);return 1}var V={SIGINT:2,SIGQUIT:3,SIGKILL:9,SIGTERM:15};function R(W,b,z,Q=L){let J=Q(W,[b,...z],{stdio:"inherit"});if(J.error)return process.stderr.write(`rove: could not start Bun at ${W}: ${J.error.message}
7
- `),1;return z1(J)}var N=B(import.meta.url),Z=O(import.meta.url),c=$1(N,`${Z}-run.js`);async function X1(W){let b=J1({input:process.stdin,output:process.stdout});try{let z=(await b.question(W)).trim().toLowerCase();return z===""||z==="y"||z==="yes"}finally{b.close()}}async function Z1(){let W={launcherDir:N},b=w(W);if(b.bun||!f())return b;let z=b.stale?`${Z}: Bun ${b.stale.version} is too old for Rove (needs ${G}+). Install the latest Bun now? [Y/n] `:`${Z}: Rove runs on the Bun runtime, and none is installed. Install Bun now? [Y/n] `;if(!await X1(z))return b;return{bun:I(W),stale:b.stale,unusable:b.unusable}}var v=globalThis.Bun;if(v){let W=v.version;if(W&&!g()&&!P(W))process.stderr.write(h(process.execPath,W,Z)),process.exit(1);await import(Q1(c).href)}else{let{bun:W,stale:b,unusable:z}=await Z1();if(!W){let Q=b?h(b.path,b.version,Z):z?A(z,Z):y(Z);process.stderr.write(Q),process.exit(1)}process.exit(R(W,c,process.argv.slice(2)))}
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 L}from"node:child_process";import{constants as m,accessSync as u}from"node:fs";import{homedir as l}from"node:os";import{basename as t,delimiter as o,dirname as r,join as Y}from"node:path";import{fileURLToPath as T}from"node:url";var h={$schema:"https://json.schemastore.org/package.json",name:"@sma1lboy/rove",version:"0.9.148",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:sandbox":"bun run scripts/dev-sandbox.ts run","dev:sandbox:reset":"bun run scripts/dev-sandbox.ts reset",build:"bun run scripts/build.ts",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.18","@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","react-devtools-core":"^7.0.1",typescript:"5.8.2",vitest:"2.1.9"},trustedDependencies:[]};var U="rove",C="kobe";var V=C;var k=U;var E="ROVE_INVOKED_AS";function x(W=process.env){return W[E]===k?k:V}var F="ROVE_BUN",i="ROVE_NO_BUN_BOOTSTRAP",O="ROVE_SKIP_BUN_CHECK",G=h.engines.bun.match(/\d+\.\d+\.\d+/)?.[0]??"0.0.0",B=(W)=>{try{return u(W,m.X_OK),!0}catch{return!1}},a=(W)=>W==="win32"?"bun.exe":"bun",n=(W)=>{let b=L(W,["--version"],{encoding:"utf8",timeout:5000});if(b.error||b.status!==0)return null;return b.stdout?.split(`
3
+ `)[0]?.trim()??""};function K(W){return W.trim().match(/^v?(\d+\.\d+\.\d+)/)?.[1]??null}function j(W,b=G){let z=K(W),Q=K(b);if(!z||!Q)return!0;let J=z.split(".").map(Number),$=Q.split(".").map(Number);for(let X=0;X<3;X++){let q=J[X]??0,H=$[X]??0;if(q!==H)return q>H}return!0}function P(W=process.env){return W[O]==="1"}function p(W={}){let b=W.env??process.env,z=W.platform??process.platform,Q=W.home??b.HOME??b.USERPROFILE??l(),J=a(z),$=[],X=b[F]?.trim();if(X)$.push(X);for(let w of(b.PATH??b.Path??"").split(o))if(w)$.push(Y(w,J));let q=b.BUN_INSTALL?.trim();if(q)$.push(Y(q,"bin",J));if(Q)$.push(Y(Q,".bun","bin",J));let H=W.launcherDir;if(H)$.push(Y(H,"..","..","node_modules","bun","bin",J)),$.push(Y(H,"..","..","..","bun","bin",J));return $}function e(W={}){let b=W.isExecutable??B;return p(W).find((z)=>b(z))??null}function D(W={}){let b=W.isExecutable??B,z=W.bunVersionOf??n;if(P(W.env??process.env))return{bun:e(W),stale:null,unusable:null};let Q=null,J=null;for(let $ of p(W)){if(!b($))continue;let X=z($);if(X===null){J??=$;continue}if(j(X))return{bun:$,stale:Q,unusable:J};Q??={path:$,version:K(X)??X}}return{bun:null,stale:Q,unusable:J}}function A(W){return r(T(W))}function R(W){return t(T(W)).replace(/\.[cm]?[jt]s$/,"")}function W1(W=process.platform){return W==="win32"?["powershell","-NoProfile","-Command","irm bun.sh/install.ps1 | iex"]:["bash","-c","curl -fsSL https://bun.sh/install | bash"]}function y(W=x(),b=process.platform){let z=b==="win32"?'powershell -c "irm bun.sh/install.ps1 | iex"':"curl -fsSL https://bun.sh/install | bash";return[`${W}: Rove runs on the Bun runtime, and no Bun was found on this machine.`,"","Install Bun, then run this command again:",` ${z}`," 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: ${F}=/path/to/bun`,""].join(`
4
+ `)}function g(W,b,z=x()){return[`${z}: this machine's Bun is too old for Rove — found ${b} at ${W}, need ${G} 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: ${F}=/path/to/bun`,`Run on this one anyway (unsupported, terminals will be blank): ${O}=1`,""].join(`
5
+ `)}function I(W,b=x()){return[`${b}: the Bun at ${W} could not be run — \`${W} --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: ${F}=/path/to/bun`,""].join(`
6
+ `)}function f(W=process.env,b=process.stdin,z=process.stdout){if(W[i]==="1")return!1;if(W.CI==="true"||W.CI==="1")return!1;return Boolean(b.isTTY&&z.isTTY)}function c(W={},b=L){let z=W.platform??process.platform,[Q,...J]=W1(z);if(!Q)return null;let $=b(Q,J,{stdio:"inherit"});if($.error||$.status!==0)return null;return D(W).bun}function b1(W){if(typeof W.status==="number")return W.status;if(W.signal)return 128+(Object.hasOwn(M,W.signal)?M[W.signal]:0);return 1}var M={SIGINT:2,SIGQUIT:3,SIGKILL:9,SIGTERM:15};function _(W,b,z,Q=L){let J=Q(W,[b,...z],{stdio:"inherit"});if(J.error)return process.stderr.write(`rove: could not start Bun at ${W}: ${J.error.message}
7
+ `),1;return b1(J)}var S=A(import.meta.url),Z=R(import.meta.url),N=z1(S,`${Z}-run.js`);async function Q1(W){let b=$1({input:process.stdin,output:process.stdout});try{let z=(await b.question(W)).trim().toLowerCase();return z===""||z==="y"||z==="yes"}finally{b.close()}}async function X1(){let W={launcherDir:S},b=D(W);if(b.bun||!f())return b;let z=b.stale?`${Z}: Bun ${b.stale.version} is too old for Rove (needs ${G}+). Install the latest Bun now? [Y/n] `:`${Z}: Rove runs on the Bun runtime, and none is installed. Install Bun now? [Y/n] `;if(!await Q1(z))return b;return{bun:c(W),stale:b.stale,unusable:b.unusable}}var v=globalThis.Bun;if(v){let W=v.version;if(W&&!P()&&!j(W))process.stderr.write(g(process.execPath,W,Z)),process.exit(1);await import(J1(N).href)}else{let{bun:W,stale:b,unusable:z}=await X1();if(!W){let Q=b?g(b.path,b.version,Z):z?I(z,Z):y(Z);process.stderr.write(Q),process.exit(1)}process.exit(_(W,N,process.argv.slice(2)))}
@@ -305,16 +305,35 @@ rove api collect --group <groupId> --pretty
305
305
  rove api list --pretty
306
306
  ```
307
307
 
308
- **A `deferred` send already landed do NOT retry.** When the target composer
309
- holds half-typed text, `send` exits 0 with `"deferred"` in the JSON instead of
310
- pasting over it: the daemon has stored the message and queued a
311
- `prompt_deferred` Inbox episode for a human to release. That is a SUCCESS, not
312
- a failure to deliver. Retrying stacks a duplicate and the second send fails
313
- `DEFERRED_PROMPT_PENDING` until the Inbox item is released, dismissed, or
314
- expires. Read the `delivered` / `deferred` keys, not just the exit code.
315
-
316
- `.running` means any hosted engine tab on the task is alive; a live shell,
317
- command, or content tab alone does not count. It is process truth, not
308
+ **A `deferred` send was ACCEPTED, not delivered and headless, nobody will
309
+ release it for you.** When the target composer holds half-typed text, `send`
310
+ exits 0 with `"deferred"` in the JSON instead of pasting over it: the daemon
311
+ took ownership of the message and queued a `prompt_deferred` Inbox episode.
312
+ Do NOT re-send the same text the daemon has it, and a second send to that
313
+ tab fails `DEFERRED_PROMPT_PENDING` anyway. But do not treat it as delivered
314
+ either: with a human attached, they release it from the Inbox; with nobody
315
+ attached, that never happens and the daemon sweeps the text at
316
+ `deferred.expiresAt` (24h after filing), undelivered and silently. Finish the
317
+ handoff yourself:
318
+
319
+ ```bash
320
+ rove api deferred-list # what the daemon is holding, and until when
321
+ rove api deferred-release --id <id> # deliver it now → { delivered: true }
322
+ rove api deferred-dismiss --id <id> # drop it and free the tab's slot
323
+ ```
324
+
325
+ `deferred-release` re-runs the gate rather than bypassing it, so a composer
326
+ that is still busy answers `delivered: false` with the blocking `reason` —
327
+ retry it, do not re-send. Read the `delivered` / `deferred` keys, not just
328
+ the exit code.
329
+
330
+ `.running` is `true` / `false` / `null`. It means an ENGINE PROCESS is alive
331
+ in one of the task's engine tabs — a live shell, command, or content tab alone
332
+ does not count, and neither does an engine tab whose engine exited (the PTY
333
+ survives it as a login shell; each tab reports that as `engineAlive`). `null`
334
+ means the pty host could not be asked: "couldn't look", NOT "nothing is
335
+ running". **Never act on `null` as if it were `false`** — deleting a task on it
336
+ destroys a worktree that may hold live work. It is process truth, not
318
337
  progress: a task whose work is merged and whose worker has signed off still
319
338
  reads `true` until somebody deletes it (see "A task is finished when it is
320
339
  GONE").
@@ -98,21 +98,35 @@ needs numbers, not when you want to know what a task is doing.
98
98
 
99
99
  <!-- generated:begin drive -->
100
100
  ```text
101
- send --task-id --prompt|--prompt-file(REQ) --tab --command --plain --allow-empty
102
- dispatch --task-id(REQ) --prompt|--prompt-file(REQ) --tab
103
- note --task-id(REQ) --text(REQ)
104
- note-list --repo(REQ)
105
- pane-open --task-id --tab --command --direction{right|down}(right)
106
- --placement{split|tab}(split) --title
107
- pane-close --task-id --title(REQ) --tab
108
- tab-close --task-id(REQ) --tab(REQ)
109
- notify --title(REQ) --body --kind(done) --task-id --source
110
- prompt --title(REQ) --placeholder --initial --timeout
111
- engine-report --task-id --kind(REQ) --engine --tab --detail
112
- set-active --task-id --none
101
+ send --task-id --prompt|--prompt-file(REQ) --tab --command --respawn --plain
102
+ --allow-empty
103
+ dispatch --task-id(REQ) --prompt|--prompt-file(REQ) --tab
104
+ deferred-list --task-id
105
+ deferred-release --id(REQ)
106
+ deferred-dismiss --id(REQ)
107
+ note --task-id(REQ) --text(REQ)
108
+ note-list --repo(REQ)
109
+ pane-open --task-id --tab --command --direction{right|down}(right)
110
+ --placement{split|tab}(split) --title
111
+ pane-close --task-id --title(REQ) --tab
112
+ tab-close --task-id(REQ) --tab(REQ)
113
+ notify --title(REQ) --body --kind(done) --task-id --source
114
+ prompt --title(REQ) --placeholder --initial --timeout
115
+ engine-report --task-id --kind(REQ) --engine --tab --detail
116
+ set-active --task-id --none
113
117
  ```
114
118
  <!-- generated:end -->
115
119
 
120
+ **The `deferred-*` trio is the Inbox, for a caller with no screen.** A `send`
121
+ into a busy composer exits 0 with `deferred` in its JSON: the daemon owns the
122
+ text now, and the TUI Inbox is where a human releases it. Headless there is no
123
+ human, so the record sits until `deferred.expiresAt` (24h after filing) and is
124
+ then swept UNDELIVERED — and every `send` to that tab fails
125
+ `DEFERRED_PROMPT_PENDING` meanwhile. `deferred-list` shows what is held and
126
+ until when, `deferred-release --id` delivers it (re-running the gate, so a
127
+ still-busy composer answers `delivered:false` with a `reason` — retry, do not
128
+ re-send), and `deferred-dismiss --id` drops it and frees the tab's slot.
129
+
116
130
  **`note` is the repo's durable field-note store.** One line, a verified
117
131
  conclusion another session could act on — it is appended to the repo's notes
118
132
  (every future session on this repo starts with them) AND relayed to the
@@ -160,7 +174,7 @@ set-effort --task-id(REQ) --level(REQ)
160
174
  set-status --task-id(REQ)
161
175
  --status{backlog|in_progress|in_review|done|canceled|error}(REQ)
162
176
  pin --task-id(REQ) --pinned(true)
163
- land --task-id(REQ) --strategy{merge|squash}(merge) --delete-branch
177
+ land --task-id(REQ) --dry-run --strategy{merge|squash}(merge) --delete-branch
164
178
  --remove-worktree(true)
165
179
  delete --task-id(REQ) --force --delete-branch --wait
166
180
  ```
@@ -312,9 +326,17 @@ Errors go to stderr as `{"error":{"message","code",...}}`. Most carry `hint`
312
326
  |---|---|---|
313
327
  | `BAD_FLAG` | flag not on that verb | check the table above, then `schema --verb <v>` |
314
328
  | `TASK_NOT_FOUND` | id deleted or mistyped | `rove api list` |
329
+ | `DIRTY_WORKTREE` | `delete` on a worktree with uncommitted files | send the worker back to commit, or `delete --force` to discard |
330
+ | `DEFERRED_PROMPT_PENDING` | that tab already holds a deferred prompt | `deferred-release --id` (or `deferred-dismiss --id`), then re-send |
331
+ | `DEFERRED_PROMPT_NOT_FOUND` | released, dismissed, or swept already | `rove api deferred-list` |
332
+ | `ISSUE_NOT_FOUND` | no issue with that number in this repo | `rove api issue-list --repo <path>` |
315
333
  | `NO_ENGINE_TAB` | live tabs exist, none is an engine | `--tab tab-N` from `pty-list`, or `--tab new` |
316
334
  | `TAB_NOT_FOUND` | `--tab` names a closed/unknown tab | `get-task` for the live `.tabs[]` |
317
335
  | `DISPATCHER_UNREACHABLE` | bare `send` reply, dispatcher gone | nothing alive to reply to — never silently spawns |
318
336
  | `EMPTY_SUCCESS_REPORT` | `succeeded:` from a branch with 0 commits | commit first, or say so with `--allow-empty` |
319
337
  | `SOURCE_CHANGED` | `read-output` cursor's target moved | re-read without the cursor |
320
338
  | `EMPTY_BRANCH` | `land` on zero commits ahead | the worker committed nothing |
339
+
340
+ Daemon-side refusals carry their OWN code (`DIRTY_WORKTREE`, `LAND_CONFLICT`,
341
+ `MISSING_REF`, `GIT_COMMAND_FAILED`, …), not `RPC_ERROR`. Match on `code`; the
342
+ `message` is prose for a human and does not repeat the code.