@sma1lboy/rove 0.9.225 → 0.9.226
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/{chunk-k42pvhga.js → chunk-12n1vt01.js} +2 -2
- package/dist/cli/{chunk-3yh71rdr.js → chunk-1ksrew4v.js} +1 -1
- package/dist/cli/{chunk-dc82mtts.js → chunk-28wqt1yd.js} +2 -2
- package/dist/cli/{chunk-9n6d80fb.js → chunk-3s2tggeb.js} +1 -1
- package/dist/cli/{chunk-2r75ny8q.js → chunk-3vvsyc17.js} +1 -1
- package/dist/cli/{chunk-d8z70z0n.js → chunk-4av03df5.js} +1 -1
- package/dist/cli/{chunk-1f8c92xt.js → chunk-52p1q2nk.js} +6 -4
- package/dist/cli/chunk-544bwsss.js +4 -0
- package/dist/cli/chunk-5vknqr2f.js +3 -0
- package/dist/cli/{chunk-wc8axd0v.js → chunk-715ghn8f.js} +1 -1
- package/dist/cli/chunk-7b8bjams.js +2 -0
- package/dist/cli/{chunk-83cjdv26.js → chunk-7m4t1byg.js} +1 -1
- package/dist/cli/{chunk-sn2r47e9.js → chunk-857xzvfh.js} +1 -1
- package/dist/cli/{chunk-2c47eey6.js → chunk-85m905dp.js} +1 -1
- package/dist/cli/chunk-85x6zkf4.js +3 -0
- package/dist/cli/{chunk-vwf847fy.js → chunk-8b5br0kr.js} +1 -1
- package/dist/cli/{chunk-pej4e17m.js → chunk-8ga6w7zm.js} +3 -3
- package/dist/cli/{chunk-jnrxqadn.js → chunk-968y3wrz.js} +1 -1
- package/dist/cli/{chunk-v99665ht.js → chunk-9e1s5zgk.js} +2 -2
- package/dist/cli/{chunk-benjgjtt.js → chunk-9qq8k8fh.js} +1 -1
- package/dist/cli/{chunk-qv5y4xb3.js → chunk-a3yyrabb.js} +1 -1
- package/dist/cli/chunk-absw6vn3.js +9 -0
- package/dist/cli/{chunk-hybs0rpr.js → chunk-ca5g8vdg.js} +1 -1
- package/dist/cli/{chunk-90dvfjrd.js → chunk-d0dqgk8f.js} +1 -1
- package/dist/cli/{chunk-kbsrbpbf.js → chunk-eawt4n4g.js} +1 -1
- package/dist/cli/{chunk-122vhkba.js → chunk-f5e3dcxe.js} +1 -1
- package/dist/cli/{chunk-57qnjcre.js → chunk-f8cvww86.js} +1 -1
- package/dist/cli/{chunk-xmdbky9n.js → chunk-fx127943.js} +1 -1
- package/dist/cli/{chunk-1dhbsn9f.js → chunk-g1v0cxqq.js} +1 -1
- package/dist/cli/{chunk-whwv8dgk.js → chunk-h8w49kyg.js} +1 -1
- package/dist/cli/{chunk-ke26my5r.js → chunk-he76emdm.js} +1 -1
- package/dist/cli/{chunk-87hjfmx4.js → chunk-jkmfqs92.js} +1 -1
- package/dist/cli/{chunk-vnh0f2xw.js → chunk-kg1czrxn.js} +1 -1
- package/dist/cli/{chunk-wwb57kcp.js → chunk-kzn6bg8f.js} +2 -2
- package/dist/cli/{chunk-3h73z1x9.js → chunk-m9y3ehq9.js} +1 -1
- package/dist/cli/{chunk-d3phpprk.js → chunk-ms42shda.js} +1 -1
- package/dist/cli/chunk-nhakrm1f.js +4 -0
- package/dist/cli/{chunk-0aj86zz1.js → chunk-nqx62ax5.js} +1 -1
- package/dist/cli/{chunk-e32bx30h.js → chunk-p4z34t0m.js} +1 -1
- package/dist/cli/{chunk-wenasn1h.js → chunk-pz907kve.js} +1 -1
- package/dist/cli/{chunk-aqmzfwd5.js → chunk-q88bmheb.js} +1 -1
- package/dist/cli/{chunk-mjdt28x6.js → chunk-qagek3wg.js} +1 -1
- package/dist/cli/{chunk-tr4xzm5w.js → chunk-qkqt3g6r.js} +1 -1
- package/dist/cli/{chunk-8h0q0gy3.js → chunk-qmc928as.js} +1 -1
- package/dist/cli/{chunk-gfwxx6mh.js → chunk-rdj6ffbz.js} +1 -1
- package/dist/cli/{chunk-z62bf0dh.js → chunk-rp53sace.js} +1 -1
- package/dist/cli/{chunk-6m3xjvp7.js → chunk-ry3n6zj8.js} +16 -17
- package/dist/cli/{chunk-r0y0tazs.js → chunk-s95bfq1d.js} +2 -2
- package/dist/cli/{chunk-wrnv7sn7.js → chunk-sjw2fcd3.js} +1 -1
- package/dist/cli/{chunk-kh6v3cq1.js → chunk-snjte1rd.js} +1 -1
- package/dist/cli/{chunk-4esn0bed.js → chunk-wapcw2dp.js} +1 -1
- package/dist/cli/{chunk-jd4v771h.js → chunk-wr35dvwz.js} +1 -1
- package/dist/cli/{chunk-5t8cazgm.js → chunk-wtqxv2rv.js} +1 -1
- package/dist/cli/{chunk-jd8c23wq.js → chunk-xr8y71d6.js} +1 -1
- package/dist/cli/{chunk-2kh0qk5f.js → chunk-y9kf5bas.js} +5 -5
- package/dist/cli/{chunk-ctnactxq.js → chunk-yb7960bb.js} +1 -1
- package/dist/cli/index.js +3 -3
- package/dist/cli/kobe.js +1 -1
- package/dist/cli/pty-host-node.mjs +3 -0
- package/dist/cli/rove.js +1 -1
- package/dist/completions/kobe.bash +1 -1
- package/dist/completions/kobe.fish +1 -1
- package/dist/completions/kobe.zsh +1 -1
- package/dist/completions/rove.bash +1 -1
- package/dist/completions/rove.fish +1 -1
- package/dist/completions/rove.zsh +1 -1
- package/dist/skills/rove/SKILL.md +1 -1
- package/dist/skills/rove/references/api-flags.md +7 -0
- package/package.json +1 -1
- package/dist/cli/chunk-255fberx.js +0 -9
- package/dist/cli/chunk-hrx15eky.js +0 -3
- package/dist/cli/chunk-p1zab1sy.js +0 -4
- package/dist/cli/chunk-rv421ny3.js +0 -2
- package/dist/cli/chunk-sdyzxayr.js +0 -3
- package/dist/cli/chunk-smc5n94s.js +0 -3
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// @bun
|
|
2
|
-
import{formatBytes,hookConfigIssues}from"./chunk-gjtyxam6.js";import{inspectLegacyTmux,legacyTmuxDoctorLines}from"./chunk-dqndd97s.js";import"./chunk-
|
|
2
|
+
import{formatBytes,hookConfigIssues}from"./chunk-gjtyxam6.js";import{inspectLegacyTmux,legacyTmuxDoctorLines}from"./chunk-dqndd97s.js";import"./chunk-52p1q2nk.js";import"./chunk-85pk7c74.js";import"./chunk-53afdybj.js";import"./chunk-rz8zs7j8.js";import{describeAccount,detectEngineStatuses,probeableEngineIds,summarizeEngines}from"./chunk-857xzvfh.js";import"./chunk-mhg40es1.js";import"./chunk-r2pztgm6.js";import"./chunk-1da3bqjc.js";import"./chunk-85mk6j0s.js";import"./chunk-xsrcwcjc.js";import"./chunk-59xc6m1q.js";import{resolveNodeBinary}from"./chunk-rdj6ffbz.js";import{formatDaemonInfo}from"./chunk-rcyasw34.js";import"./chunk-b99tf0jr.js";import"./chunk-chmhmxmc.js";import"./chunk-rhczy26f.js";import"./chunk-7mfjczcz.js";import"./chunk-w7zv47mp.js";import"./chunk-khj0apc7.js";import"./chunk-g3r1dwy9.js";import"./chunk-w25b7xxz.js";import"./chunk-h4n8ffqy.js";import"./chunk-vyb5a2rh.js";import"./chunk-jvxh93nz.js";import{isStaleInstallError,resolveKobeSpawn}from"./chunk-wtqxv2rv.js";import"./chunk-pz907kve.js";import"./chunk-2brn8e1y.js";import"./chunk-y3k1accw.js";import"./chunk-bw73t1zw.js";import"./chunk-7kysxgbq.js";import{readableLegacyIndexPath}from"./chunk-2xsem13q.js";import"./chunk-xy8be792.js";import"./chunk-05jej26n.js";import{CURRENT_VERSION,package_default}from"./chunk-3vvsyc17.js";import{kobeSkillState,skillInstallCommand}from"./chunk-12n1vt01.js";import"./chunk-hg87p5n8.js";import"./chunk-40dgv828.js";import"./chunk-mkksdcsw.js";import{activeCliName}from"./chunk-ppwpjm39.js";import"./chunk-fxs82dsx.js";import"./chunk-zyd6k6ak.js";import{homeDir,kvStatePath,roveStateDir}from"./chunk-8hbtca1g.js";import"./chunk-hq2n27y1.js";import{LEGACY_KOBE_STATE_DIR_BASENAME}from"./chunk-sb0ns0c7.js";import{readPidFile}from"./chunk-vnpqemb0.js";import"./chunk-9prawccj.js";import{t}from"./chunk-g1v0cxqq.js";import"./chunk-5vknqr2f.js";import"./chunk-nhakrm1f.js";import"./chunk-pxk2c2vj.js";import{KobeDaemonClient}from"./chunk-qagek3wg.js";import{isForeignDaemonHome}from"./chunk-544bwsss.js";import"./chunk-hqbmzz4t.js";import"./chunk-3es6spp4.js";import"./chunk-pw6yfj10.js";import"./chunk-f10n6063.js";import{defaultDaemonLogPath,defaultDaemonPidPath,defaultDaemonSocketPath,defaultPtyHostLogPath,defaultPtyHostPidPath,defaultPtyHostSocketPath}from"./chunk-y8fqdnh3.js";import"./chunk-hq4b3fca.js";import{__require}from"./chunk-wqfp8d9w.js";import{existsSync,readFileSync as readFileSync2,statSync as statSync2}from"fs";import{join as join2}from"path";var MIN_BUN_VERSION=package_default.engines.bun.match(/\d+\.\d+\.\d+/)?.[0]??"0.0.0";function parseBunVersion(raw){return raw.trim().match(/^v?(\d+\.\d+\.\d+)/)?.[1]??null}function isBunAtLeast(raw,minimum=MIN_BUN_VERSION){let found=parseBunVersion(raw),floor=parseBunVersion(minimum);if(!found||!floor)return!0;let a=found.split(".").map(Number),b=floor.split(".").map(Number);for(let i=0;i<3;i++){let av=a[i]??0,bv=b[i]??0;if(av!==bv)return av>bv}return!0}import{createInterface}from"readline";function daemonRestartFix(cliName,reason){return{kind:"run",id:"daemon-restart",label:t(`doctor.fix.${reason}`),command:[cliName,"daemon","restart"],why:t("doctor.fix.daemonRestartWhy")}}function skillInstallFix(installCommand,stale){return{kind:"run",id:"skill-install",label:t(stale?"doctor.fix.skillStale":"doctor.fix.skillMissing"),command:installCommand.split(" "),why:t("doctor.fix.skillInstallWhy")}}function resetManualFix(cliName,reason){return{kind:"manual",id:`reset:${reason}`,label:t(`doctor.fix.${reason}`),action:`${cliName} reset`,why:t("doctor.fix.resetWhy")}}function killOrphansManualFix(cliName,count){return{kind:"manual",id:"kill-orphans",label:t("doctor.fix.orphans",{count}),action:`${cliName} doctor --kill-orphans`,why:t("doctor.fix.orphansWhy")}}function engineTabsManualFix(){return{kind:"manual",id:"engine-tabs",label:t("doctor.fix.engineTabs"),action:t("doctor.fix.engineTabsAction"),why:t("doctor.fix.engineTabsWhy")}}function reinstallManualFix(){return{kind:"manual",id:"reinstall",label:t("doctor.fix.staleInstall"),action:t("doctor.fix.staleInstallAction"),why:t("doctor.fix.staleInstallWhy")}}function spawnHelperFix(paths){return{kind:"run",id:"spawn-helper-chmod",label:t("doctor.fix.spawnHelper"),command:["chmod","755",...paths],why:t("doctor.fix.spawnHelperWhy")}}function humanOnlyFix(reason,vars){return{kind:"manual",id:reason,label:t(`doctor.fix.${reason}`),action:t(`doctor.fix.${reason}Action`,vars),why:t("doctor.fix.humanOnlyWhy")}}function noEngineFix(signedOut){return signedOut.length>0?humanOnlyFix("noEngineLogin",{list:signedOut.join(", ")}):humanOnlyFix("noEngine")}function dedupeFixes(fixes){let seen=new Set;return fixes.filter((fix)=>{if(seen.has(fix.id))return!1;return seen.add(fix.id),!0})}async function applyFixes(collected,rt){let fixes=dedupeFixes(collected);if(fixes.length===0){rt.out(""),rt.out(t("doctor.fix.none"));return}let runnable=fixes.filter((fix)=>fix.kind==="run");if(runnable.length>0){rt.out(""),rt.out(t("doctor.fix.header"));for(let fix of runnable){if(rt.out(` ${fix.label}`),rt.out(` ${t("doctor.fix.willRun",{command:fix.command.join(" ")})}`),rt.out(` ${fix.why}`),!rt.interactive)continue;if(!await rt.confirm(` ${t("doctor.fix.confirmPrompt")}`)){rt.out(` ${t("doctor.fix.skipped")}`);continue}let code=await rt.exec(fix.command);rt.out(code===0?` ${t("doctor.fix.done")}`:` ${t("doctor.fix.failed",{code})}`)}if(!rt.interactive)rt.out(` ${t("doctor.fix.nonInteractive")}`)}let manual=fixes.filter((fix)=>fix.kind==="manual");if(manual.length>0){rt.out(""),rt.out(t("doctor.fix.manualHeader"));for(let fix of manual)rt.out(` ${fix.label}`),rt.out(` \u2192 ${fix.action}`),rt.out(` ${fix.why}`)}}async function confirmTty(question){let readline=createInterface({input:process.stdin,output:process.stdout});try{let answer=await new Promise((resolve)=>readline.question(question,resolve));return answer.trim().toLowerCase()==="y"||answer.trim().toLowerCase()==="yes"}finally{readline.close()}}async function execInherited(command){try{return await Bun.spawn([...command],{stdin:"inherit",stdout:"inherit",stderr:"inherit"}).exited}catch{return 127}}function defaultFixRuntime(){return{confirm:confirmTty,exec:execInherited,out:(line)=>console.log(line),interactive:process.stdin.isTTY===!0}}function classifyHookChannel(input){let total=0,hooked=0;for(let tabs of Object.values(input.tabs))for(let entry of Object.values(tabs))if(total++,entry.source==="hook")hooked++;if(total===0)return{kind:"no-tabs"};if(hooked===0)return{kind:"down",totalTabs:total};return{kind:"live",hookTabs:hooked,totalTabs:total}}function hookChannelDoctorLines(verdict,input,cliName){let configLines=(input.configIssues??[]).flatMap((issue)=>[` \u26A0 hook install skipped: ${issue.file}`,` ${issue.reason} \u2014 fix the file, then relaunch Rove`]);if(verdict.kind==="no-tabs")return["hooks: \u2014 no engine tabs yet (nothing to check)",...configLines];if(verdict.kind==="live")return[`hooks: \u2713 engine hook channel live (${verdict.hookTabs}/${verdict.totalTabs} tab(s) hook-sourced)`,...configLines];let out=[`hooks: \u2717 NO hook events reaching the daemon (0/${verdict.totalTabs} tab(s) hook-sourced)`," badges fall back to a ~10s poll, so activity looks seconds late",` daemon socket: ${input.socketPath}`,...configLines];return out.push(' \u2192 compare with an engine tab\'s own path: `ps eww -p <engine-pid> | tr " " "\\n" | grep DAEMON_SOCKET_PATH`',` \u2192 restart the engine tabs (they may hold a stale socket path), or run \`${cliName} daemon restart\``,` \u2192 debug one hook directly: \`KOBE_HOOK_DEBUG=1 echo '{}' | ${cliName} hook turn-start --engine claude\``),out}import{readdirSync,statSync}from"fs";import{createRequire}from"module";import{dirname,join}from"path";function installedSpawnHelpers(){let pkg;try{pkg=dirname(createRequire(import.meta.url).resolve("node-pty/package.json"))}catch{return[]}let prebuilds=join(pkg,"prebuilds"),arches;try{arches=readdirSync(prebuilds).filter((name)=>name.startsWith("darwin-"))}catch{return[]}let helpers=[];for(let arch of arches){let path=join(prebuilds,arch,"spawn-helper");try{helpers.push({path,executable:(statSync(path).mode&64)!==0})}catch{}}return helpers}function spawnHelperDoctorLines(helpers){let broken=helpers.filter((helper)=>!helper.executable).map((helper)=>helper.path);if(helpers.length===0)return{lines:["node-pty: ? no darwin spawn-helper found next to node-pty"],broken};if(broken.length===0)return{lines:[`node-pty: \u2713 spawn-helper executable (${helpers.length} arch)`],broken};return{lines:["node-pty: \u2717 spawn-helper is not executable \u2014 every node-pty PTY spawn fails",...broken.map((path)=>` ${path}`),` \u2192 chmod 755 ${broken.join(" ")}`],broken}}import{appendFileSync,readFileSync}from"fs";var PTY_MARKER="KOBE_TERMINAL_PTY=1",run=async(argv)=>{try{let proc=Bun.spawn([...argv],{stdin:"ignore",stdout:"pipe",stderr:"ignore"}),[stdout,code]=await Promise.all([new Response(proc.stdout).text().catch(()=>""),proc.exited]);return{code,stdout}}catch{return{code:127,stdout:""}}};function parsePsRows(output){let rows=[];for(let line of output.split(`
|
|
3
3
|
`)){let parts=line.trim().split(/\s+/);if(parts.length<6)continue;let[pid,ppid,pgid]=[parts[0],parts[1],parts[2]].map((value)=>Number.parseInt(value??"",10)),rssKb=Number.parseInt(parts[4]??"",10);if(!Number.isFinite(pid)||!Number.isFinite(ppid)||!Number.isFinite(pgid)||!Number.isFinite(rssKb))continue;rows.push({pid,ppid,pgid,etime:parts[3]??"",rssKb,command:parts.slice(5).join(" ")})}return rows}function pidAlive(pid,rows){return rows.some((row)=>row.pid===pid)}function orphanCandidates(rows,selfPgid,liveSessionPids){return rows.filter((row)=>row.ppid===1&&row.pgid!==selfPgid&&!liveSessionPids.has(row.pgid)&&!pidAlive(row.pgid,rows))}async function markedPids(pids,deps={}){let runProbe=deps.run??run,readEnviron=deps.readEnviron??((pid)=>readFileSync(`/proc/${pid}/environ`,"utf8")),marked=new Set;if(pids.length===0)return{marked,failed:null};if((deps.platform??process.platform)==="linux"){let refused=null;for(let pid of pids)try{if(readEnviron(pid).split("\x00").includes(PTY_MARKER))marked.add(pid)}catch(err){let code=err.code;if(code!=="ENOENT"&&code!=="ESRCH")refused??=`/proc/${pid}/environ: ${code??"unreadable"}`}return{marked,failed:refused}}let result=await runProbe(["ps","eww","-o","pid=,command=","-p",pids.join(",")]);if(result.code!==0)return{marked,failed:`ps eww exited ${result.code}`};let marker=new RegExp(`(^|\\s)${PTY_MARKER}(\\s|$)`);for(let line of result.stdout.split(`
|
|
4
4
|
`)){let pid=Number.parseInt(line.trim().split(/\s+/)[0]??"",10);if(Number.isFinite(pid)&&marker.test(line))marked.add(pid)}return{marked,failed:null}}async function ownPgid(runProbe){let result=await runProbe(["ps","-o","pgid=","-p",String(process.pid)]),pgid=Number.parseInt(result.stdout.trim(),10);return Number.isFinite(pgid)?pgid:-1}async function collectOrphans(liveSessionPids,deps={}){let runProbe=deps.run??run;if((deps.platform??process.platform)==="win32")return{orphans:[],error:null};let ps=await runProbe(["ps","-A","-o","pid=,ppid=,pgid=,etime=,rss=,command="]);if(ps.code!==0)return{orphans:[],error:`could not read the process table \u2014 ps exited ${ps.code}`};let rows=parsePsRows(ps.stdout),candidates=orphanCandidates(rows,await ownPgid(runProbe),liveSessionPids),{marked,failed}=await markedPids(candidates.map((row)=>row.pid),deps);if(failed)return{orphans:[],error:`could not read process environments \u2014 ${failed}`};return{orphans:candidates.filter((row)=>marked.has(row.pid)),error:null}}function formatMb(rssKb){return`${(rssKb/1024).toFixed(0)} MB`}function orphanDoctorLines(orphans,error,cliName,killing=!1){if(error)return[`orphans: \u2717 ${error}`];if(orphans.length===0)return["orphans: \u2713 none \u2014 no processes left behind by a dead PTY session"];let totalMb=orphans.reduce((sum,row)=>sum+row.rssKb,0)/1024,lines=[`orphans: \u26A0 ${orphans.length} process(es) outlived the PTY session that spawned them (${totalMb.toFixed(0)} MB RSS)`," each is reparented to init, carries Rove's PTY marker, and its process"," group leader is gone \u2014 no live task owns them"];for(let row of[...orphans].sort((a,b)=>b.rssKb-a.rssKb))lines.push(` pid ${row.pid} (group ${row.pgid}) up ${row.etime}, ${formatMb(row.rssKb)}: ${row.command.slice(0,90)}`);if(!killing)lines.push(` \u2192 \`${cliName} doctor --kill-orphans\` ends those process groups (SIGTERM, then SIGKILL)`," read the list first: something you backgrounded from a Rove terminal and then"," closed the tab on looks exactly like a leak, and doctor cannot tell them apart");return lines}var GROUP_EXIT_GRACE_MS=2000,GROUP_POLL_MS=100;function logOrphanKill(pgid,signal,logPath=defaultDaemonLogPath()){try{appendFileSync(logPath,formatDaemonInfo("doctor-kill-orphans",`${signal} process group ${pgid}`))}catch{}}function groupAlive(pgid){try{return process.kill(-pgid,0),!0}catch(err){return err.code!=="ESRCH"}}async function killOrphanGroups(orphans){let groups=[...new Set(orphans.map((row)=>row.pgid))];for(let pgid of groups)try{process.kill(-pgid,"SIGTERM"),logOrphanKill(pgid,"SIGTERM")}catch{}let deadline=Date.now()+GROUP_EXIT_GRACE_MS,survivors=groups.filter(groupAlive);while(survivors.length>0&&Date.now()<deadline)await new Promise((resolve)=>setTimeout(resolve,GROUP_POLL_MS)),survivors=survivors.filter(groupAlive);for(let pgid of survivors)try{process.kill(-pgid,"SIGKILL"),logOrphanKill(pgid,"SIGKILL")}catch{}return await new Promise((resolve)=>setTimeout(resolve,GROUP_POLL_MS)),{groups,survivors:survivors.filter(groupAlive)}}function multiplexerLabel(env){if(env.TMUX)return"tmux";if(env.ZELLIJ)return"zellij";if(env.STY)return"screen";return"no"}function terminalEnvLines(env){let show=(v)=>v&&v.length>0?v:"(unset)",program=env.TERM_PROGRAM?`${env.TERM_PROGRAM}${env.TERM_PROGRAM_VERSION?` v${env.TERM_PROGRAM_VERSION}`:""}`:"(unset)";return[`terminal: TERM=${show(env.TERM)} TERM_PROGRAM=${program} COLORTERM=${show(env.COLORTERM)}`,` running inside a multiplexer: ${multiplexerLabel(env)}`]}function parseKittyProbeReply(data){let kitty=data.match(/\x1b\[\?(\d+)u/);if(kitty?.[1]!==void 0)return{kind:"supported",flags:Number.parseInt(kitty[1],10)};if(/\x1b\[\?[\d;]*c/.test(data))return{kind:"unsupported"};return null}function kittyProbeLine(result){switch(result.kind){case"supported":return` kitty keyboard protocol: \u2713 answered (flags=${result.flags})`;case"unsupported":return[" kitty keyboard protocol: \u2717 not supported \u2014 legacy key path"," (ctrl+h/ctrl+j arrive as C0 backspace/linefeed bytes; the"," split chords ctrl+\\ and ctrl+= cannot be encoded at all)"].join(`
|
|
5
5
|
`);case"no-response":return" kitty keyboard protocol: ? no reply (terminal ignored both the kitty query and DA1)";case"skipped":return` kitty keyboard protocol: skipped (${result.reason})`}}async function probeKittyKeyboard(timeoutMs=300){let stdin=process.stdin;if(!stdin.isTTY||!process.stdout.isTTY)return{kind:"skipped",reason:"not an interactive terminal"};let wasRaw=stdin.isRaw===!0,buffer="";return await new Promise((resolve)=>{let done=!1,finish=(result)=>{if(done)return;if(done=!0,clearTimeout(timer),stdin.off("data",onData),stdin.pause(),!wasRaw)stdin.setRawMode(!1);resolve(result)},onData=(chunk)=>{buffer+=chunk.toString("latin1");let decided=parseKittyProbeReply(buffer);if(decided)finish(decided)},timer=setTimeout(()=>finish({kind:"no-response"}),timeoutMs);stdin.setRawMode(!0),stdin.resume(),stdin.on("data",onData),process.stdout.write("\x1B[?u\x1B[c")})}async function terminalDoctorLines(){return[...terminalEnvLines(process.env),kittyProbeLine(await probeKittyKeyboard())]}async function probeGit(){try{let proc=Bun.spawn(["git","--version"],{stdin:"ignore",stdout:"pipe",stderr:"ignore"}),text=(await new Response(proc.stdout).text()).trim();if(await proc.exited===0&&text)return{line:`git: \u2713 ${text}`,found:!0}}catch{}return{line:"git: \u2717 not found on PATH",found:!1}}function binaryLabel(binary){return binary.found?`\u2713 ${binary.path}`:`\u2717 ${binary.error}`}async function probeEngines(){let statuses=await detectEngineStatuses(await probeableEngineIds()),lines=["engines:"];for(let status of statuses){let account=describeAccount(status.account),name=`${status.vendor.padEnd(7)} `;if(lines.push(` ${name}${binaryLabel(status.binary)}${status.binary.found?` \u2014 ${account}`:""}`),status.accountError)lines.push(` \u26A0 ${status.accountError}`)}let{usable,signedOut}=summarizeEngines(statuses);return{lines,anyUsable:usable.length>0,signedOut}}var CLI_NAME=activeCliName();function isProcessAlive(pid){try{return process.kill(pid,0),!0}catch(err){return err.code==="EPERM"}}async function requestIfReachable(socketPath,name){let client=new KobeDaemonClient(socketPath);try{return await client.request(name,{})}catch{return null}finally{client.close()}}function fmtDuration(ms){let seconds=Math.floor(ms/1000);if(seconds<60)return`${seconds}s`;let minutes=Math.floor(seconds/60);if(minutes<60)return`${minutes}m ${seconds%60}s`;return`${Math.floor(minutes/60)}h ${minutes%60}m`}function describeFile(path){try{let stat=statSync2(path);return`present (${formatBytes(stat.size)}, modified ${stat.mtime.toISOString()})`}catch{return"absent"}}function taskCount(path){try{let parsed=JSON.parse(readFileSync2(path,"utf8"));return Array.isArray(parsed.tasks)?parsed.tasks.length:null}catch{return null}}function tailFile(path,count){try{return readFileSync2(path,"utf8").split(`
|
package/dist/cli/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env bun
|
|
2
2
|
// @bun
|
|
3
|
-
import{matchPathGlob}from"./chunk-kg11c1py.js";import{argvHasFlag}from"./chunk-jvxh93nz.js";import{connectIfRunning}from"./chunk-
|
|
4
|
-
`),process.exit(1);let projectRoot=await projectRootFor(dir);await withDaemonOrLocal({daemon:async(client)=>{let taskId;if(projectRoot)taskId=(await client.request("task.ensureMain",{repo:projectRoot})).task.id;else taskId=(await client.request("task.openDir",{dir})).taskId;await client.request("task.setActive",{taskId})},local:async(orch)=>{let task=projectRoot?await orch.ensureMainTask(projectRoot):await orch.openDirectoryTask({dir}),{writeLastActiveTaskId}=await import("./chunk-hgx20x94.js");writeLastActiveTaskId(String(task.id))}});let{publishKobeTerminalTitle}=await import("./chunk-1tx1s5v6.js");publishKobeTerminalTitle();let{startTui}=await import("./chunk-
|
|
3
|
+
import{matchPathGlob}from"./chunk-kg11c1py.js";import{argvHasFlag}from"./chunk-jvxh93nz.js";import{connectIfRunning}from"./chunk-wtqxv2rv.js";import"./chunk-pz907kve.js";import{expandTilde}from"./chunk-nvqdmx7q.js";import{errorMessage}from"./chunk-2brn8e1y.js";import{BUILTIN_VENDORS,coerceVendorId,isBuiltinVendor}from"./chunk-05jej26n.js";import{CURRENT_VERSION}from"./chunk-3vvsyc17.js";import{rejectionReason}from"./chunk-mkksdcsw.js";import{activeCliName,prepareCliEnvironment}from"./chunk-ppwpjm39.js";import"./chunk-fxs82dsx.js";import"./chunk-zyd6k6ak.js";import"./chunk-8hbtca1g.js";import"./chunk-hq2n27y1.js";import"./chunk-sb0ns0c7.js";import"./chunk-vnpqemb0.js";import"./chunk-9prawccj.js";import"./chunk-qagek3wg.js";import"./chunk-544bwsss.js";import"./chunk-hqbmzz4t.js";import"./chunk-3es6spp4.js";import"./chunk-pw6yfj10.js";import{pathSyntax}from"./chunk-f10n6063.js";import"./chunk-y8fqdnh3.js";import"./chunk-hq4b3fca.js";import{__require}from"./chunk-wqfp8d9w.js";import{resolve as resolve2}from"path";function debugEnabled(env){return env.KOBE_DEBUG==="1"||env.ROVE_DEBUG==="1"}function failureSubject(cliName,argv){let verb=argv[2];return verb&&!verb.startsWith("-")&&!verb.includes("/")?`${cliName} ${verb}`:cliName}function summarizeCliGitError(message,cwd){if(!/not a git repository/i.test(message))return null;return`${cwd} is not a git repository \u2014 run this inside one, or pass a repo path.`}function formatCliFailure(err,opts){let subject=failureSubject(opts.cliName,opts.argv);if(debugEnabled(opts.env))return`${subject}: ${String(err instanceof Error?err.stack??err:err)}`;let raw=errorMessage(err);return`${subject}: ${summarizeCliGitError(raw,opts.cwd)??raw}`}var DYNAMIC_COMMANDS=new Map([["completions",async(args)=>{let{runCompletionsSubcommand}=await import("./chunk-kzn6bg8f.js");await runCompletionsSubcommand(args)}],["export",async(args)=>{let{runExportSubcommand}=await import("./chunk-s1e0e9hc.js");await runExportSubcommand(args)}],["repo",async(args)=>{let{runRepoSubcommand}=await import("./chunk-vh5bkm9k.js");await runRepoSubcommand(args)}],["api",async(args)=>{let{runApiSubcommand}=await import("./chunk-s95bfq1d.js");await runApiSubcommand(args)}],["update",async(args)=>{let{runUpdateSubcommand}=await import("./chunk-9e1s5zgk.js");await runUpdateSubcommand(args)}],["theme",async(args)=>{let{runThemeSubcommand}=await import("./chunk-k7g060qr.js");await runThemeSubcommand(args)}],["feedback",async(args)=>{let{runFeedbackSubcommand}=await import("./chunk-ms42shda.js");await runFeedbackSubcommand(args)}],["daemon",async(args)=>{let{runDaemonSubcommand}=await import("./chunk-rp53sace.js");await runDaemonSubcommand(args)}],["machine",async(args)=>{let{runMachineSubcommand}=await import("./chunk-b1kg21v2.js");await runMachineSubcommand(args)}],["doctor",async(args)=>{let{runDoctorSubcommand}=await import("./chunk-yb7960bb.js");await runDoctorSubcommand(args)}],["config",async(args)=>{let{runConfigSubcommand}=await import("./chunk-3htqngp4.js");await runConfigSubcommand(args)}],["reset",async(args)=>{let{runResetSubcommand}=await import("./chunk-xr8y71d6.js");await runResetSubcommand(args)}],["pty-host",async(args)=>{let{runPtyHostSubcommand}=await import("./chunk-h8w49kyg.js");await runPtyHostSubcommand(args)}],["skill",async(args)=>{let{runSkillSubcommand}=await import("./chunk-28wqt1yd.js");await runSkillSubcommand(args)}],["plugin",async(args)=>{let{runPluginSubcommand}=await import("./chunk-8ga6w7zm.js");await runPluginSubcommand(args)}],["hook",async(args)=>{let{runHookSubcommand}=await import("./chunk-wapcw2dp.js");await runHookSubcommand(args)}]]);import{statSync}from"fs";import{resolve}from"path";async function openLocalOrchestrator(){let{TaskIndexStore}=await import("./chunk-vzqrj32e.js"),{GitWorktreeManager}=await import("./chunk-57q6gykd.js"),{Orchestrator}=await import("./chunk-fx127943.js"),store=new TaskIndexStore;return await store.load(),new Orchestrator({store,worktrees:new GitWorktreeManager})}async function withDaemonOrLocal(bridge){let client=await connectIfRunning();if(client)try{return await bridge.daemon(client)}finally{client.close()}let orch=await openLocalOrchestrator();return bridge.local(orch)}function isPathLikeArg(arg){return arg==="."||arg===".."||arg.startsWith("./")||arg.startsWith("../")||arg.startsWith(".\\")||arg.startsWith("..\\")||pathSyntax(arg).isAbsolute(arg)||arg.startsWith("/")||arg==="~"||arg.startsWith("~/")||arg.startsWith("~\\")}async function projectRootFor(dir){let{isGitRepo,resolveRepoRoot}=await import("./chunk-frrjz0dr.js"),{projectRejection}=await import("./chunk-9mtxxsb3.js"),top=resolveRepoRoot(dir);if(top!==dir)return null;return projectRejection(top,isGitRepo,"explicit")?null:top}async function runOpenDirectory(arg){let dir=resolve(process.cwd(),expandTilde(arg)),isDir=!1;try{isDir=statSync(dir).isDirectory()}catch{isDir=!1}if(!isDir)process.stderr.write(`${activeCliName()}: "${arg}" is not a directory (resolved to ${dir}).
|
|
4
|
+
`),process.exit(1);let projectRoot=await projectRootFor(dir);await withDaemonOrLocal({daemon:async(client)=>{let taskId;if(projectRoot)taskId=(await client.request("task.ensureMain",{repo:projectRoot})).task.id;else taskId=(await client.request("task.openDir",{dir})).taskId;await client.request("task.setActive",{taskId})},local:async(orch)=>{let task=projectRoot?await orch.ensureMainTask(projectRoot):await orch.openDirectoryTask({dir}),{writeLastActiveTaskId}=await import("./chunk-hgx20x94.js");writeLastActiveTaskId(String(task.id))}});let{publishKobeTerminalTitle}=await import("./chunk-1tx1s5v6.js");publishKobeTerminalTitle();let{startTui}=await import("./chunk-8b5br0kr.js");await startTui()}function topLevelUsage(cliName=activeCliName()){return[`${cliName} ${CURRENT_VERSION}`,"",`Usage: ${cliName} [command] [options]`,"","Run with no command to launch PureTUI.",`Run \`${cliName} .\` (or \`${cliName} <path>\`) to open a directory as a standalone task.`,"","Commands:"," completions <shell> Generate shell completion script (bash/zsh/fish)"," add [path] Save a repo path for the new-task picker"," remove [path] Forget a saved project (inverse of add; non-destructive)"," adopt [glob] Import existing git worktrees as tasks"," export [--csv|--json] Print the task list (json/csv/table; daemon-free)"," repo <verb> Per-repo init script + first prompt (show|set|unset)",` api <verb> Scriptable RPC surface for agents (see \`${cliName} api --help\`)`," daemon <verb> Manage the daemon (start|stop|status|restart)"," machine <verb> Other computers running Rove (add|remove|list)"," doctor [--report|--fix] Diagnose daemon/PTY/engines/git; --fix walks the remedies",` config [--path] Open ${cliName}'s config file (state.json) in your editor`," reset [--hard] Stop runtimes; optionally wipe task/UI state"," theme <verb> Manage user themes (list|add|remove)",` skill <verb> Install the ${cliName} agent skill (install|status|command|print)`," plugin <verb> Install and run plugins (install|link|list|action|\u2026)"," feedback Send feedback to GitHub Discussions",` update [version|channel|list] Self-update ${cliName}, switch channel, or list versions`,"","Options:"," -v, --version Print version"," -h, --help Print this help"," --skill Print the agent skill file and exit"].join(`
|
|
5
5
|
`)}prepareCliEnvironment();var CLI_NAME=activeCliName(),ADD_USAGE=[`Usage: ${CLI_NAME} add [path]`,` ${CLI_NAME} add --remote --host <host> --user <user> --path <basePath> [--port N] [--key [path] | --password]`,"","Save a repo for the new-task picker. With --remote, register an SSH-backed","project whose worktrees live on <host>; engine launch over SSH is pending.",""].join(`
|
|
6
6
|
`);async function runAddSubcommand(rest){let arg=rest[0];if(arg==="--help"||arg==="-h"||arg==="help"){process.stdout.write(ADD_USAGE);return}if(arg==="--remote"){let{runAddRemote}=await import("./chunk-d1a1kw0c.js");await runAddRemote(rest.slice(1));return}if(arg?.startsWith("-"))process.stderr.write(`${CLI_NAME} add: unknown flag "${arg}"
|
|
7
7
|
|
|
@@ -22,4 +22,4 @@ ${ADOPT_USAGE}
|
|
|
22
22
|
pass a path glob to adopt, e.g. ${CLI_NAME} adopt '${repo}/*' --yes`);return}let matched=worktrees.filter(isMatch);if(matched.length===0){console.log(`
|
|
23
23
|
no worktrees match glob ${JSON.stringify(glob)}`);return}if(!yes){console.log(`
|
|
24
24
|
${matched.length} worktree(s) match \u2014 re-run with --yes to adopt them`);return}await adoptWorktreesInto(orch,repo,matched,vendor),console.log(`done \u2014 adopted ${matched.length} worktree(s)`)}function printTopLevelUsage(out){out.write(`${topLevelUsage()}
|
|
25
|
-
`)}var COMMANDS=new Map([["add",runAddSubcommand],["remove",runRemoveSubcommand],["adopt",runAdoptSubcommand],...DYNAMIC_COMMANDS]);async function main(){let[,,...rawArgs]=process.argv,[subcommand,...rest]=rawArgs;if(subcommand==="--version"||subcommand==="-v"||subcommand==="version"){let{CURRENT_VERSION:CURRENT_VERSION2}=await import("./chunk-
|
|
25
|
+
`)}var COMMANDS=new Map([["add",runAddSubcommand],["remove",runRemoveSubcommand],["adopt",runAdoptSubcommand],...DYNAMIC_COMMANDS]);async function main(){let[,,...rawArgs]=process.argv,[subcommand,...rest]=rawArgs;if(subcommand==="--version"||subcommand==="-v"||subcommand==="version"){let{CURRENT_VERSION:CURRENT_VERSION2}=await import("./chunk-3s2tggeb.js");console.log(`${CLI_NAME} ${CURRENT_VERSION2}`);return}if(subcommand==="--help"||subcommand==="-h"||subcommand==="help"){printTopLevelUsage(process.stdout);return}if(subcommand==="--skill"){let{runSkillSubcommand}=await import("./chunk-28wqt1yd.js");await runSkillSubcommand(["print"]);return}let handler=subcommand!==void 0?COMMANDS.get(subcommand):void 0;if(handler){await handler(rest);return}if(subcommand!==void 0&&isPathLikeArg(subcommand)){await runOpenDirectory(subcommand);return}if(subcommand!==void 0)console.error(`${CLI_NAME}: unknown command '${subcommand}'`),printTopLevelUsage(process.stderr),process.exit(2);let{publishKobeTerminalTitle}=await import("./chunk-1tx1s5v6.js");publishKobeTerminalTitle();let{startTui}=await import("./chunk-8b5br0kr.js");await startTui();let{runPendingWelcomeInstalls}=await import("./chunk-wr35dvwz.js");runPendingWelcomeInstalls()}main().catch((err)=>{console.error(formatCliFailure(err,{cliName:CLI_NAME,argv:process.argv,cwd:process.cwd(),env:process.env})),process.exit(1)});
|
package/dist/cli/kobe.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import{join as G1}from"node:path";import{createInterface as K1}from"node:readline/promises";import{pathToFileURL as U1}from"node:url";import{spawnSync as V}from"node:child_process";import{constants as a,accessSync as e}from"node:fs";import{homedir as W1}from"node:os";import{basename as z1,delimiter as J1,dirname as Q1,join as G}from"node:path";import{fileURLToPath as N}from"node:url";var M={$schema:"https://json.schemastore.org/package.json",name:"@sma1lboy/rove",version:"0.9.
|
|
2
|
+
import{join as G1}from"node:path";import{createInterface as K1}from"node:readline/promises";import{pathToFileURL as U1}from"node:url";import{spawnSync as V}from"node:child_process";import{constants as a,accessSync as e}from"node:fs";import{homedir as W1}from"node:os";import{basename as z1,delimiter as J1,dirname as Q1,join as G}from"node:path";import{fileURLToPath as N}from"node:url";var M={$schema:"https://json.schemastore.org/package.json",name:"@sma1lboy/rove",version:"0.9.226",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/completions","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","build:rubric":"bun run scripts/build-tier-rubric.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 scripts/render-track.mjs",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","smol-toml":"^1.7.1",ws:"^8.18.0"},devDependencies:{"@biomejs/biome":"1.9.4","@sma1lboy/kobe-daemon":"0.7.19","@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 O="rove",T="kobe";var I=T;var L=O;var t="ROVE_INVOKED_AS";function K(W=process.env){return W[t]===L?L:I}var U="ROVE_BUN",Z1="ROVE_NO_BUN_BOOTSTRAP",R="ROVE_SKIP_BUN_CHECK",x=M.engines.bun.match(/\d+\.\d+\.\d+/)?.[0]??"0.0.0",y=(W)=>{try{return e(W,a.X_OK),!0}catch{return!1}},$1=(W)=>W==="win32"?"bun.exe":"bun",X1=(W)=>{let z=V(W,["--version"],{encoding:"utf8",timeout:5000});if(z.error||z.status!==0)return null;return z.stdout?.split(`
|
|
3
3
|
`)[0]?.trim()??""};function F(W){return W.trim().match(/^v?(\d+\.\d+\.\d+)/)?.[1]??null}function C(W,z=x){let J=F(W),$=F(z);if(!J||!$)return!0;let Z=J.split(".").map(Number),Q=$.split(".").map(Number);for(let X=0;X<3;X++){let Y=Z[X]??0,b=Q[X]??0;if(Y!==b)return Y>b}return!0}function j(W=process.env){return W[R]==="1"}function k(W={}){let z=W.env??process.env,J=W.platform??process.platform,$=W.home??z.HOME??z.USERPROFILE??W1(),Z=$1(J),Q=[],X=z[U]?.trim();if(X)Q.push(X);for(let w of(z.PATH??z.Path??"").split(J1))if(w)Q.push(G(w,Z));let Y=z.BUN_INSTALL?.trim();if(Y)Q.push(G(Y,"bin",Z));if($)Q.push(G($,".bun","bin",Z));let b=W.launcherDir;if(b)Q.push(G(b,"..","..","node_modules","bun","bin",Z)),Q.push(G(b,"..","..","..","bun","bin",Z));return Q}function q1(W={}){let z=W.isExecutable??y;return k(W).find((J)=>z(J))??null}function B(W={}){let z=W.isExecutable??y,J=W.bunVersionOf??X1;if(j(W.env??process.env))return{bun:q1(W),stale:null,unusable:null};let $=null,Z=null;for(let Q of k(W)){if(!z(Q))continue;let X=J(Q);if(X===null){Z??=Q;continue}if(C(X))return{bun:Q,stale:$,unusable:Z};$??={path:Q,version:F(X)??X}}return{bun:null,stale:$,unusable:Z}}function _(W){return Q1(N(W))}function P(W){return z1(N(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 D(W=K(),z=process.platform){let J=z==="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:",` ${J}`," 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: ${U}=/path/to/bun`,""].join(`
|
|
4
4
|
`)}function g(W,z,J=K()){return[`${J}: this machine's Bun is too old for Rove — found ${z} at ${W}, need ${x} 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: ${U}=/path/to/bun`,`Run on this one anyway (unsupported, terminals will be blank): ${R}=1`,""].join(`
|
|
5
5
|
`)}function p(W,z=K()){return[`${z}: 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: ${U}=/path/to/bun`,""].join(`
|
|
@@ -503,6 +503,9 @@ async function ensureOwnerOnlyDir(dir) {
|
|
|
503
503
|
function ensureOwnerOnlyStateDir(homeDir) {
|
|
504
504
|
return ensureOwnerOnlyDir(join3(homeDir, ROVE_STATE_DIR_BASENAME));
|
|
505
505
|
}
|
|
506
|
+
|
|
507
|
+
// ../kobe-daemon/src/daemon/automation-contracts.ts
|
|
508
|
+
var ROUTINE_RESPONSE_WINDOW_MS = 2 * 60 * 60000;
|
|
506
509
|
// ../kobe-plugin-sdk/dist/contract.js
|
|
507
510
|
var DAEMON_CHANNELS = [
|
|
508
511
|
"task.snapshot",
|
package/dist/cli/rove.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import{join as G1}from"node:path";import{createInterface as K1}from"node:readline/promises";import{pathToFileURL as U1}from"node:url";import{spawnSync as V}from"node:child_process";import{constants as a,accessSync as e}from"node:fs";import{homedir as W1}from"node:os";import{basename as z1,delimiter as J1,dirname as Q1,join as G}from"node:path";import{fileURLToPath as N}from"node:url";var M={$schema:"https://json.schemastore.org/package.json",name:"@sma1lboy/rove",version:"0.9.
|
|
2
|
+
import{join as G1}from"node:path";import{createInterface as K1}from"node:readline/promises";import{pathToFileURL as U1}from"node:url";import{spawnSync as V}from"node:child_process";import{constants as a,accessSync as e}from"node:fs";import{homedir as W1}from"node:os";import{basename as z1,delimiter as J1,dirname as Q1,join as G}from"node:path";import{fileURLToPath as N}from"node:url";var M={$schema:"https://json.schemastore.org/package.json",name:"@sma1lboy/rove",version:"0.9.226",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/completions","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","build:rubric":"bun run scripts/build-tier-rubric.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 scripts/render-track.mjs",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","smol-toml":"^1.7.1",ws:"^8.18.0"},devDependencies:{"@biomejs/biome":"1.9.4","@sma1lboy/kobe-daemon":"0.7.19","@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 O="rove",T="kobe";var I=T;var L=O;var t="ROVE_INVOKED_AS";function K(W=process.env){return W[t]===L?L:I}var U="ROVE_BUN",Z1="ROVE_NO_BUN_BOOTSTRAP",R="ROVE_SKIP_BUN_CHECK",x=M.engines.bun.match(/\d+\.\d+\.\d+/)?.[0]??"0.0.0",y=(W)=>{try{return e(W,a.X_OK),!0}catch{return!1}},$1=(W)=>W==="win32"?"bun.exe":"bun",X1=(W)=>{let z=V(W,["--version"],{encoding:"utf8",timeout:5000});if(z.error||z.status!==0)return null;return z.stdout?.split(`
|
|
3
3
|
`)[0]?.trim()??""};function F(W){return W.trim().match(/^v?(\d+\.\d+\.\d+)/)?.[1]??null}function C(W,z=x){let J=F(W),$=F(z);if(!J||!$)return!0;let Z=J.split(".").map(Number),Q=$.split(".").map(Number);for(let X=0;X<3;X++){let Y=Z[X]??0,b=Q[X]??0;if(Y!==b)return Y>b}return!0}function j(W=process.env){return W[R]==="1"}function k(W={}){let z=W.env??process.env,J=W.platform??process.platform,$=W.home??z.HOME??z.USERPROFILE??W1(),Z=$1(J),Q=[],X=z[U]?.trim();if(X)Q.push(X);for(let w of(z.PATH??z.Path??"").split(J1))if(w)Q.push(G(w,Z));let Y=z.BUN_INSTALL?.trim();if(Y)Q.push(G(Y,"bin",Z));if($)Q.push(G($,".bun","bin",Z));let b=W.launcherDir;if(b)Q.push(G(b,"..","..","node_modules","bun","bin",Z)),Q.push(G(b,"..","..","..","bun","bin",Z));return Q}function q1(W={}){let z=W.isExecutable??y;return k(W).find((J)=>z(J))??null}function B(W={}){let z=W.isExecutable??y,J=W.bunVersionOf??X1;if(j(W.env??process.env))return{bun:q1(W),stale:null,unusable:null};let $=null,Z=null;for(let Q of k(W)){if(!z(Q))continue;let X=J(Q);if(X===null){Z??=Q;continue}if(C(X))return{bun:Q,stale:$,unusable:Z};$??={path:Q,version:F(X)??X}}return{bun:null,stale:$,unusable:Z}}function _(W){return Q1(N(W))}function P(W){return z1(N(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 D(W=K(),z=process.platform){let J=z==="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:",` ${J}`," 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: ${U}=/path/to/bun`,""].join(`
|
|
4
4
|
`)}function g(W,z,J=K()){return[`${J}: this machine's Bun is too old for Rove — found ${z} at ${W}, need ${x} 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: ${U}=/path/to/bun`,`Run on this one anyway (unsupported, terminals will be blank): ${R}=1`,""].join(`
|
|
5
5
|
`)}function p(W,z=K()){return[`${z}: 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: ${U}=/path/to/bun`,""].join(`
|
|
@@ -12,7 +12,7 @@ _kobe() {
|
|
|
12
12
|
fi
|
|
13
13
|
if [[ ${COMP_CWORD} -eq 2 ]]; then
|
|
14
14
|
case "${prev}" in
|
|
15
|
-
api) COMPREPLY=( $(compgen -W "schema engine-list list get-task pty-list collect context digest agent-turns inspect read-output watch add send dispatch interrupt note note-list note-delete pane-open pane-close pane-graphics tab-close notify prompt engine-report row-token set-active feedback issue-list issue-create issue-set-status issue-update issue-delete routine-list routine-create routine-update routine-set-enabled routine-delete routine-run-now routine-runs workitem-list workitem-start rename set-branch set-command set-effort set-model set-status pin land delete ensure-worktree remove-worktree discover-adoptable adopt" -- "${cur}") ) ;;
|
|
15
|
+
api) COMPREPLY=( $(compgen -W "schema engine-list list get-task pty-list collect context digest agent-turns inspect read-output watch add send dispatch interrupt note note-list note-delete pane-open pane-close pane-graphics tab-close notify prompt engine-report row-token set-active feedback issue-list issue-create issue-set-status issue-update issue-delete routine-list routine-create routine-update routine-set-enabled routine-delete routine-run-now routine-respond routine-runs workitem-list workitem-start rename set-branch set-command set-effort set-model set-status pin land delete ensure-worktree remove-worktree discover-adoptable adopt" -- "${cur}") ) ;;
|
|
16
16
|
daemon) COMPREPLY=( $(compgen -W "status start stop restart" -- "${cur}") ) ;;
|
|
17
17
|
machine) COMPREPLY=( $(compgen -W "add remove list" -- "${cur}") ) ;;
|
|
18
18
|
plugin) COMPREPLY=( $(compgen -W "install link list search outdated update enable disable unlink uninstall config-dir log action pane" -- "${cur}") ) ;;
|
|
@@ -18,7 +18,7 @@ complete -c kobe -f -n __fish_use_subcommand -a skill
|
|
|
18
18
|
complete -c kobe -f -n __fish_use_subcommand -a plugin
|
|
19
19
|
complete -c kobe -f -n __fish_use_subcommand -a feedback
|
|
20
20
|
complete -c kobe -f -n __fish_use_subcommand -a update
|
|
21
|
-
complete -c kobe -f -n "__fish_seen_subcommand_from api" -a "schema engine-list list get-task pty-list collect context digest agent-turns inspect read-output watch add send dispatch interrupt note note-list note-delete pane-open pane-close pane-graphics tab-close notify prompt engine-report row-token set-active feedback issue-list issue-create issue-set-status issue-update issue-delete routine-list routine-create routine-update routine-set-enabled routine-delete routine-run-now routine-runs workitem-list workitem-start rename set-branch set-command set-effort set-model set-status pin land delete ensure-worktree remove-worktree discover-adoptable adopt"
|
|
21
|
+
complete -c kobe -f -n "__fish_seen_subcommand_from api" -a "schema engine-list list get-task pty-list collect context digest agent-turns inspect read-output watch add send dispatch interrupt note note-list note-delete pane-open pane-close pane-graphics tab-close notify prompt engine-report row-token set-active feedback issue-list issue-create issue-set-status issue-update issue-delete routine-list routine-create routine-update routine-set-enabled routine-delete routine-run-now routine-respond routine-runs workitem-list workitem-start rename set-branch set-command set-effort set-model set-status pin land delete ensure-worktree remove-worktree discover-adoptable adopt"
|
|
22
22
|
complete -c kobe -f -n "__fish_seen_subcommand_from daemon" -a "status start stop restart"
|
|
23
23
|
complete -c kobe -f -n "__fish_seen_subcommand_from machine" -a "add remove list"
|
|
24
24
|
complete -c kobe -f -n "__fish_seen_subcommand_from plugin" -a "install link list search outdated update enable disable unlink uninstall config-dir log action pane"
|
|
@@ -13,7 +13,7 @@ _kobe() {
|
|
|
13
13
|
|
|
14
14
|
verbs=()
|
|
15
15
|
case "${words[2]}" in
|
|
16
|
-
api) verbs=("schema" "engine-list" "list" "get-task" "pty-list" "collect" "context" "digest" "agent-turns" "inspect" "read-output" "watch" "add" "send" "dispatch" "interrupt" "note" "note-list" "note-delete" "pane-open" "pane-close" "pane-graphics" "tab-close" "notify" "prompt" "engine-report" "row-token" "set-active" "feedback" "issue-list" "issue-create" "issue-set-status" "issue-update" "issue-delete" "routine-list" "routine-create" "routine-update" "routine-set-enabled" "routine-delete" "routine-run-now" "routine-runs" "workitem-list" "workitem-start" "rename" "set-branch" "set-command" "set-effort" "set-model" "set-status" "pin" "land" "delete" "ensure-worktree" "remove-worktree" "discover-adoptable" "adopt") ;;
|
|
16
|
+
api) verbs=("schema" "engine-list" "list" "get-task" "pty-list" "collect" "context" "digest" "agent-turns" "inspect" "read-output" "watch" "add" "send" "dispatch" "interrupt" "note" "note-list" "note-delete" "pane-open" "pane-close" "pane-graphics" "tab-close" "notify" "prompt" "engine-report" "row-token" "set-active" "feedback" "issue-list" "issue-create" "issue-set-status" "issue-update" "issue-delete" "routine-list" "routine-create" "routine-update" "routine-set-enabled" "routine-delete" "routine-run-now" "routine-respond" "routine-runs" "workitem-list" "workitem-start" "rename" "set-branch" "set-command" "set-effort" "set-model" "set-status" "pin" "land" "delete" "ensure-worktree" "remove-worktree" "discover-adoptable" "adopt") ;;
|
|
17
17
|
daemon) verbs=("status" "start" "stop" "restart") ;;
|
|
18
18
|
machine) verbs=("add" "remove" "list") ;;
|
|
19
19
|
plugin) verbs=("install" "link" "list" "search" "outdated" "update" "enable" "disable" "unlink" "uninstall" "config-dir" "log" "action" "pane") ;;
|
|
@@ -12,7 +12,7 @@ _rove() {
|
|
|
12
12
|
fi
|
|
13
13
|
if [[ ${COMP_CWORD} -eq 2 ]]; then
|
|
14
14
|
case "${prev}" in
|
|
15
|
-
api) COMPREPLY=( $(compgen -W "schema engine-list list get-task pty-list collect context digest agent-turns inspect read-output watch add send dispatch interrupt note note-list note-delete pane-open pane-close pane-graphics tab-close notify prompt engine-report row-token set-active feedback issue-list issue-create issue-set-status issue-update issue-delete routine-list routine-create routine-update routine-set-enabled routine-delete routine-run-now routine-runs workitem-list workitem-start rename set-branch set-command set-effort set-model set-status pin land delete ensure-worktree remove-worktree discover-adoptable adopt" -- "${cur}") ) ;;
|
|
15
|
+
api) COMPREPLY=( $(compgen -W "schema engine-list list get-task pty-list collect context digest agent-turns inspect read-output watch add send dispatch interrupt note note-list note-delete pane-open pane-close pane-graphics tab-close notify prompt engine-report row-token set-active feedback issue-list issue-create issue-set-status issue-update issue-delete routine-list routine-create routine-update routine-set-enabled routine-delete routine-run-now routine-respond routine-runs workitem-list workitem-start rename set-branch set-command set-effort set-model set-status pin land delete ensure-worktree remove-worktree discover-adoptable adopt" -- "${cur}") ) ;;
|
|
16
16
|
daemon) COMPREPLY=( $(compgen -W "status start stop restart" -- "${cur}") ) ;;
|
|
17
17
|
machine) COMPREPLY=( $(compgen -W "add remove list" -- "${cur}") ) ;;
|
|
18
18
|
plugin) COMPREPLY=( $(compgen -W "install link list search outdated update enable disable unlink uninstall config-dir log action pane" -- "${cur}") ) ;;
|
|
@@ -18,7 +18,7 @@ complete -c rove -f -n __fish_use_subcommand -a skill
|
|
|
18
18
|
complete -c rove -f -n __fish_use_subcommand -a plugin
|
|
19
19
|
complete -c rove -f -n __fish_use_subcommand -a feedback
|
|
20
20
|
complete -c rove -f -n __fish_use_subcommand -a update
|
|
21
|
-
complete -c rove -f -n "__fish_seen_subcommand_from api" -a "schema engine-list list get-task pty-list collect context digest agent-turns inspect read-output watch add send dispatch interrupt note note-list note-delete pane-open pane-close pane-graphics tab-close notify prompt engine-report row-token set-active feedback issue-list issue-create issue-set-status issue-update issue-delete routine-list routine-create routine-update routine-set-enabled routine-delete routine-run-now routine-runs workitem-list workitem-start rename set-branch set-command set-effort set-model set-status pin land delete ensure-worktree remove-worktree discover-adoptable adopt"
|
|
21
|
+
complete -c rove -f -n "__fish_seen_subcommand_from api" -a "schema engine-list list get-task pty-list collect context digest agent-turns inspect read-output watch add send dispatch interrupt note note-list note-delete pane-open pane-close pane-graphics tab-close notify prompt engine-report row-token set-active feedback issue-list issue-create issue-set-status issue-update issue-delete routine-list routine-create routine-update routine-set-enabled routine-delete routine-run-now routine-respond routine-runs workitem-list workitem-start rename set-branch set-command set-effort set-model set-status pin land delete ensure-worktree remove-worktree discover-adoptable adopt"
|
|
22
22
|
complete -c rove -f -n "__fish_seen_subcommand_from daemon" -a "status start stop restart"
|
|
23
23
|
complete -c rove -f -n "__fish_seen_subcommand_from machine" -a "add remove list"
|
|
24
24
|
complete -c rove -f -n "__fish_seen_subcommand_from plugin" -a "install link list search outdated update enable disable unlink uninstall config-dir log action pane"
|
|
@@ -13,7 +13,7 @@ _rove() {
|
|
|
13
13
|
|
|
14
14
|
verbs=()
|
|
15
15
|
case "${words[2]}" in
|
|
16
|
-
api) verbs=("schema" "engine-list" "list" "get-task" "pty-list" "collect" "context" "digest" "agent-turns" "inspect" "read-output" "watch" "add" "send" "dispatch" "interrupt" "note" "note-list" "note-delete" "pane-open" "pane-close" "pane-graphics" "tab-close" "notify" "prompt" "engine-report" "row-token" "set-active" "feedback" "issue-list" "issue-create" "issue-set-status" "issue-update" "issue-delete" "routine-list" "routine-create" "routine-update" "routine-set-enabled" "routine-delete" "routine-run-now" "routine-runs" "workitem-list" "workitem-start" "rename" "set-branch" "set-command" "set-effort" "set-model" "set-status" "pin" "land" "delete" "ensure-worktree" "remove-worktree" "discover-adoptable" "adopt") ;;
|
|
16
|
+
api) verbs=("schema" "engine-list" "list" "get-task" "pty-list" "collect" "context" "digest" "agent-turns" "inspect" "read-output" "watch" "add" "send" "dispatch" "interrupt" "note" "note-list" "note-delete" "pane-open" "pane-close" "pane-graphics" "tab-close" "notify" "prompt" "engine-report" "row-token" "set-active" "feedback" "issue-list" "issue-create" "issue-set-status" "issue-update" "issue-delete" "routine-list" "routine-create" "routine-update" "routine-set-enabled" "routine-delete" "routine-run-now" "routine-respond" "routine-runs" "workitem-list" "workitem-start" "rename" "set-branch" "set-command" "set-effort" "set-model" "set-status" "pin" "land" "delete" "ensure-worktree" "remove-worktree" "discover-adoptable" "adopt") ;;
|
|
17
17
|
daemon) verbs=("status" "start" "stop" "restart") ;;
|
|
18
18
|
machine) verbs=("add" "remove" "list") ;;
|
|
19
19
|
plugin) verbs=("install" "link" "list" "search" "outdated" "update" "enable" "disable" "unlink" "uninstall" "config-dir" "log" "action" "pane") ;;
|
|
@@ -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:
|
|
6
|
+
<!-- rove-skill-version: 52 — bump in lockstep with KOBE_SKILL_VERSION (src/lib/skill-install.ts). -->
|
|
7
7
|
|
|
8
8
|
# Rove shell control
|
|
9
9
|
|
|
@@ -267,6 +267,7 @@ routine-update --id(REQ) --name --prompt|--prompt-file --schedule --vendor
|
|
|
267
267
|
routine-set-enabled --id(REQ) --enabled(REQ)
|
|
268
268
|
routine-delete --id(REQ)
|
|
269
269
|
routine-run-now --id(REQ)
|
|
270
|
+
routine-respond --run(REQ) --text --prompt-file
|
|
270
271
|
routine-runs --id(REQ)
|
|
271
272
|
```
|
|
272
273
|
<!-- generated:end -->
|
|
@@ -299,6 +300,12 @@ A bare `--enabled` means true, so pausing a routine is
|
|
|
299
300
|
and does not shift the schedule. `routine-delete` leaves already-created tasks
|
|
300
301
|
alone.
|
|
301
302
|
|
|
303
|
+
A delivered routine prompt starts with `[ROVE ROUTINE] "<name>" run #<n> — when
|
|
304
|
+
done, report with: … routine-respond --run <runId> --prompt-file -`. When you
|
|
305
|
+
received one, finish by answering THAT run: lead with the conclusion, markdown
|
|
306
|
+
welcome, 32,000 characters max. Responding again replaces the answer. Nothing
|
|
307
|
+
is inferred if you skip it; the run just shows "no response".
|
|
308
|
+
|
|
302
309
|
Run statuses from `routine-runs`: `dispatched`, `revived` (standing session
|
|
303
310
|
respawned — files kept, conversation did not), `skipped_precheck` (nothing to do),
|
|
304
311
|
`skipped_missed`, `skipped_unavailable`, `dispatch_failed`.
|
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.
|
|
4
|
+
"version": "0.9.226",
|
|
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",
|