@sma1lboy/rove 0.9.78 → 0.9.79

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli/rove.js CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
- import{join as z1}from"node:path";import{createInterface as $1}from"node:readline/promises";import{pathToFileURL as J1}from"node:url";import{spawnSync as h}from"node:child_process";import{constants as t,accessSync as u}from"node:fs";import{homedir as o}from"node:os";import{basename as r,delimiter as l,dirname as i,join as q}from"node:path";import{fileURLToPath as U}from"node:url";var c={$schema:"https://json.schemastore.org/package.json",name:"@sma1lboy/rove",version:"0.9.78",description:"Rove — the agent multiplexer for your terminal. Run coding agents on parallel tasks with isolated worktrees and persistent sessions.",keywords:["terminal","tui","cli","multiplexer","ai-agents","coding-agent","ai-coding-assistant","agentic-ai","parallel-agents","git-worktree","claude-code","codex","llm","developer-tools"],type:"module",packageManager:"bun@1.3.13",bin:{kobe:"dist/cli/kobe.js",rove:"dist/cli/rove.js"},files:["dist/cli","dist/web-ui","dist/skills","dist/*.wav","README.md","LICENSE"],publishConfig:{access:"public"},repository:{type:"git",url:"git+https://github.com/Sma1lboy/rove.git"},homepage:"https://rove.run",bugs:{url:"https://github.com/Sma1lboy/rove/issues"},engines:{bun:">=1.3.11"},scripts:{dev:"ROVE_DEV=1 bun --conditions=browser ./src/cli/rove.ts","dev:kobe":"KOBE_DEV=1 bun --conditions=browser ./src/cli/kobe.ts","dev:mock":"KOBE_DEV=1 bun ./src/tui-react/mock/host.tsx","dev:mock-react":"KOBE_DEV=1 bun ./src/tui-react/mock/host.tsx","dev:mock-react-task-dialogs":"KOBE_DEV=1 bun ./src/tui-react/component/mock-dialogs-host.tsx","dev:mock-react-filetree":"KOBE_DEV=1 bun ./src/tui-react/panes/filetree/mock-host.tsx","dev:mock-react-sidebar":"KOBE_DEV=1 bun ./src/tui-react/panes/sidebar/mock-host.tsx","dev:mock-react-terminal":"KOBE_DEV=1 bun ./src/tui-react/panes/terminal/mock-host.tsx","dev:mock-react-dialogs":"KOBE_DEV=1 bun ./src/tui-react/mock/dialogs-host.tsx","dev:mock-react-workspace":"KOBE_DEV=1 bun ./src/tui-react/workspace/mock-host.tsx","dev:sandbox":"bun run scripts/dev-sandbox.ts run","dev:sandbox:reset":"bun run scripts/dev-sandbox.ts reset",build:"bun run scripts/build.ts","build:with-web":"bun run build",compile:"bun run scripts/compile.ts",typecheck:"tsc --noEmit","check-i18n":"bun run scripts/check-i18n.ts",test:"bun run test:fast && bun run test:socket","perf:golden":"bun scripts/perf-golden.ts","pty:soak":"bun scripts/pty-soak.ts","test:fast":"vitest run --passWithNoTests --minWorkers=1 --maxWorkers=8","test:socket":"KOBE_INCLUDE_SOCKET=1 vitest run test/daemon --pool forks --minWorkers=1 --maxWorkers=4 --passWithNoTests","test:socket:coverage":"KOBE_INCLUDE_SOCKET=1 KOBE_COVERAGE_DAEMON=1 vitest run test/daemon --coverage --pool forks --minWorkers=1 --maxWorkers=4 --passWithNoTests","test:behavior":"KOBE_INCLUDE_BEHAVIOR=1 vitest run test/behavior --pool forks --minWorkers=1 --maxWorkers=1 --retry=2 --passWithNoTests","test:render":"bun test test/render --coverage --coverage-reporter=text --coverage-reporter=lcov --coverage-dir=coverage-render",coverage:"vitest run --coverage --passWithNoTests",bench:"vitest bench --run",lint:"biome check .",knip:"knip-bun",postinstall:"bun run scripts/check-preview-deps.ts || true",prepublishOnly:"bun run typecheck && bun run build","plugin-sandbox":"bun run scripts/plugin-sandbox.ts"},"//":"biome.json + bunfig.toml live at the monorepo root since they apply repo-wide; bun.lock also lives at root (workspace-shared).",dependencies:{"@ansi-tools/parser":"^1.0.15","@opentui/core":"0.4.3","@opentui/react":"0.4.3","@xterm/addon-serialize":"^0.14.0","@xterm/addon-unicode11":"^0.9.0","@xterm/headless":"^6.0.0","node-pty":"^1.1.0",react:"^19.2.8",ws:"^8.18.0"},devDependencies:{"@biomejs/biome":"1.9.4","@sma1lboy/kobe-daemon":"0.7.17","@tsconfig/bun":"1.0.10","@types/bun":"1.3.14","@types/node":"25.6.2","@types/react":"^19.2.0","@vitest/coverage-v8":"2.1.9",knip:"^6.14.2","kobe-web":"workspace:*","react-devtools-core":"^7.0.1",typescript:"5.8.2",vitest:"2.1.9"},trustedDependencies:[]};var x="rove",w="kobe";var E="ROVE_INVOKED_AS";function Y(b=process.env){return b[E]===x?x:w}var K="ROVE_BUN",a="ROVE_NO_BUN_BOOTSTRAP",p="ROVE_SKIP_BUN_CHECK",F=c.engines.bun.match(/\d+\.\d+\.\d+/)?.[0]??"0.0.0",B=(b)=>{try{return u(b,t.X_OK),!0}catch{return!1}},e=(b)=>b==="win32"?"bun.exe":"bun",n=(b)=>{let W=h(b,["--version"],{encoding:"utf8",timeout:5000});if(W.error||W.status!==0)return null;return W.stdout?.split(`
3
- `)[0]?.trim()??""};function g(b){return b.trim().match(/^v?(\d+\.\d+\.\d+)/)?.[1]??null}function j(b,W=F){let k=g(b),J=g(W);if(!k||!J)return!0;let $=k.split(".").map(Number),z=J.split(".").map(Number);for(let Q=0;Q<3;Q++){let H=$[Q]??0,Z=z[Q]??0;if(H!==Z)return H>Z}return!0}function G(b=process.env){return b[p]==="1"}function C(b={}){let W=b.env??process.env,k=b.platform??process.platform,J=b.home??W.HOME??W.USERPROFILE??o(),$=e(k),z=[],Q=W[K]?.trim();if(Q)z.push(Q);for(let P of(W.PATH??W.Path??"").split(l))if(P)z.push(q(P,$));let H=W.BUN_INSTALL?.trim();if(H)z.push(q(H,"bin",$));if(J)z.push(q(J,".bun","bin",$));let Z=b.launcherDir;if(Z)z.push(q(Z,"..","..","node_modules","bun","bin",$)),z.push(q(Z,"..","..","..","bun","bin",$));return z}function b1(b={}){let W=b.isExecutable??B;return C(b).find((k)=>W(k))??null}function L(b={}){let W=b.isExecutable??B,k=b.bunVersionOf??n;if(G(b.env??process.env))return{bun:b1(b),stale:null,unusable:null};let J=null,$=null;for(let z of C(b)){if(!W(z))continue;let Q=k(z);if(Q===null){$??=z;continue}if(j(Q))return{bun:z,stale:J,unusable:$};J??={path:z,version:g(Q)??Q}}return{bun:null,stale:J,unusable:$}}function O(b){return i(U(b))}function M(b){return r(U(b)).replace(/\.[cm]?[jt]s$/,"")}function W1(b=process.platform){return b==="win32"?["powershell","-NoProfile","-Command","irm bun.sh/install.ps1 | iex"]:["bash","-c","curl -fsSL https://bun.sh/install | bash"]}function T(b=Y(),W=process.platform){let k=W==="win32"?'powershell -c "irm bun.sh/install.ps1 | iex"':"curl -fsSL https://bun.sh/install | bash";return[`${b}: Rove runs on the Bun runtime, and no Bun was found on this machine.`,"","Install Bun, then run this command again:",` ${k}`," npm install -g bun # any platform, if you already have npm","","Or install Bun and Rove together in one step:"," curl -fsSL https://rove.run/install.sh | sh","",`Already have Bun somewhere unusual? Point Rove at it: ${K}=/path/to/bun`,""].join(`
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 j}from"node:child_process";import{constants as t,accessSync as u}from"node:fs";import{homedir as r}from"node:os";import{basename as o,delimiter as l,dirname as i,join as q}from"node:path";import{fileURLToPath as U}from"node:url";var c={$schema:"https://json.schemastore.org/package.json",name:"@sma1lboy/rove",version:"0.9.79",description:"Rove — the agent multiplexer for your terminal. Run coding agents on parallel tasks with isolated worktrees and persistent sessions.",keywords:["terminal","tui","cli","multiplexer","ai-agents","coding-agent","ai-coding-assistant","agentic-ai","parallel-agents","git-worktree","claude-code","codex","llm","developer-tools"],type:"module",packageManager:"bun@1.3.13",bin:{kobe:"dist/cli/kobe.js",rove:"dist/cli/rove.js"},files:["dist/cli","dist/web-ui","dist/skills","dist/*.wav","README.md","LICENSE"],publishConfig:{access:"public"},repository:{type:"git",url:"git+https://github.com/Sma1lboy/rove.git"},homepage:"https://rove.run",bugs:{url:"https://github.com/Sma1lboy/rove/issues"},engines:{bun:">=1.3.11"},scripts:{dev:"ROVE_DEV=1 bun --conditions=browser ./src/cli/rove.ts","dev:kobe":"KOBE_DEV=1 bun --conditions=browser ./src/cli/kobe.ts","dev:mock":"KOBE_DEV=1 bun ./src/tui-react/mock/host.tsx","dev:mock-react":"KOBE_DEV=1 bun ./src/tui-react/mock/host.tsx","dev:mock-react-task-dialogs":"KOBE_DEV=1 bun ./src/tui-react/component/mock-dialogs-host.tsx","dev:mock-react-filetree":"KOBE_DEV=1 bun ./src/tui-react/panes/filetree/mock-host.tsx","dev:mock-react-sidebar":"KOBE_DEV=1 bun ./src/tui-react/panes/sidebar/mock-host.tsx","dev:mock-react-terminal":"KOBE_DEV=1 bun ./src/tui-react/panes/terminal/mock-host.tsx","dev:mock-react-dialogs":"KOBE_DEV=1 bun ./src/tui-react/mock/dialogs-host.tsx","dev:mock-react-workspace":"KOBE_DEV=1 bun ./src/tui-react/workspace/mock-host.tsx","dev:sandbox":"bun run scripts/dev-sandbox.ts run","dev:sandbox:reset":"bun run scripts/dev-sandbox.ts reset",build:"bun run scripts/build.ts","build:with-web":"bun run build",compile:"bun run scripts/compile.ts",typecheck:"tsc --noEmit","check-i18n":"bun run scripts/check-i18n.ts",test:"bun run test:fast && bun run test:socket","perf:golden":"bun scripts/perf-golden.ts","pty:soak":"bun scripts/pty-soak.ts","test:fast":"vitest run --passWithNoTests --minWorkers=1 --maxWorkers=8","test:socket":"KOBE_INCLUDE_SOCKET=1 vitest run test/daemon --pool forks --minWorkers=1 --maxWorkers=4 --passWithNoTests","test:socket:coverage":"KOBE_INCLUDE_SOCKET=1 KOBE_COVERAGE_DAEMON=1 vitest run test/daemon --coverage --pool forks --minWorkers=1 --maxWorkers=4 --passWithNoTests","test:behavior":"KOBE_INCLUDE_BEHAVIOR=1 vitest run test/behavior --pool forks --minWorkers=1 --maxWorkers=1 --retry=2 --passWithNoTests","test:render":"bun test test/render --coverage --coverage-reporter=text --coverage-reporter=lcov --coverage-dir=coverage-render",coverage:"vitest run --coverage --passWithNoTests",bench:"vitest bench --run",lint:"biome check .",knip:"knip-bun",postinstall:"bun run scripts/check-preview-deps.ts || true",prepublishOnly:"bun run typecheck && bun run build","plugin-sandbox":"bun run scripts/plugin-sandbox.ts"},"//":"biome.json + bunfig.toml live at the monorepo root since they apply repo-wide; bun.lock also lives at root (workspace-shared).",dependencies:{"@ansi-tools/parser":"^1.0.15","@dagrejs/dagre":"^3.1.1","@opentui/core":"0.4.3","@opentui/react":"0.4.3","@xterm/addon-serialize":"^0.14.0","@xterm/addon-unicode11":"^0.9.0","@xterm/headless":"^6.0.0","node-pty":"^1.1.0",react:"^19.2.8",ws:"^8.18.0"},devDependencies:{"@biomejs/biome":"1.9.4","@sma1lboy/kobe-daemon":"0.7.17","@tsconfig/bun":"1.0.10","@types/bun":"1.3.14","@types/node":"25.6.2","@types/react":"^19.2.0","@vitest/coverage-v8":"2.1.9",knip:"^6.14.2","kobe-web":"workspace:*","react-devtools-core":"^7.0.1",typescript:"5.8.2",vitest:"2.1.9"},trustedDependencies:[]};var x="rove",g="kobe";var E="ROVE_INVOKED_AS";function Y(b=process.env){return b[E]===x?x:g}var K="ROVE_BUN",a="ROVE_NO_BUN_BOOTSTRAP",p="ROVE_SKIP_BUN_CHECK",F=c.engines.bun.match(/\d+\.\d+\.\d+/)?.[0]??"0.0.0",B=(b)=>{try{return u(b,t.X_OK),!0}catch{return!1}},e=(b)=>b==="win32"?"bun.exe":"bun",n=(b)=>{let W=j(b,["--version"],{encoding:"utf8",timeout:5000});if(W.error||W.status!==0)return null;return W.stdout?.split(`
3
+ `)[0]?.trim()??""};function w(b){return b.trim().match(/^v?(\d+\.\d+\.\d+)/)?.[1]??null}function h(b,W=F){let k=w(b),J=w(W);if(!k||!J)return!0;let $=k.split(".").map(Number),z=J.split(".").map(Number);for(let Q=0;Q<3;Q++){let H=$[Q]??0,Z=z[Q]??0;if(H!==Z)return H>Z}return!0}function G(b=process.env){return b[p]==="1"}function C(b={}){let W=b.env??process.env,k=b.platform??process.platform,J=b.home??W.HOME??W.USERPROFILE??r(),$=e(k),z=[],Q=W[K]?.trim();if(Q)z.push(Q);for(let P of(W.PATH??W.Path??"").split(l))if(P)z.push(q(P,$));let H=W.BUN_INSTALL?.trim();if(H)z.push(q(H,"bin",$));if(J)z.push(q(J,".bun","bin",$));let Z=b.launcherDir;if(Z)z.push(q(Z,"..","..","node_modules","bun","bin",$)),z.push(q(Z,"..","..","..","bun","bin",$));return z}function b1(b={}){let W=b.isExecutable??B;return C(b).find((k)=>W(k))??null}function L(b={}){let W=b.isExecutable??B,k=b.bunVersionOf??n;if(G(b.env??process.env))return{bun:b1(b),stale:null,unusable:null};let J=null,$=null;for(let z of C(b)){if(!W(z))continue;let Q=k(z);if(Q===null){$??=z;continue}if(h(Q))return{bun:z,stale:J,unusable:$};J??={path:z,version:w(Q)??Q}}return{bun:null,stale:J,unusable:$}}function O(b){return i(U(b))}function M(b){return o(U(b)).replace(/\.[cm]?[jt]s$/,"")}function W1(b=process.platform){return b==="win32"?["powershell","-NoProfile","-Command","irm bun.sh/install.ps1 | iex"]:["bash","-c","curl -fsSL https://bun.sh/install | bash"]}function T(b=Y(),W=process.platform){let k=W==="win32"?'powershell -c "irm bun.sh/install.ps1 | iex"':"curl -fsSL https://bun.sh/install | bash";return[`${b}: Rove runs on the Bun runtime, and no Bun was found on this machine.`,"","Install Bun, then run this command again:",` ${k}`," npm install -g bun # any platform, if you already have npm","","Or install Bun and Rove together in one step:"," curl -fsSL https://rove.run/install.sh | sh","",`Already have Bun somewhere unusual? Point Rove at it: ${K}=/path/to/bun`,""].join(`
4
4
  `)}function D(b,W,k=Y()){return[`${k}: this machine's Bun is too old for Rove — found ${W} at ${b}, need ${F} or newer.`,"","Rove's terminals are built on Bun's PTY API. An older Bun ignores it silently,","so every terminal and engine tab would open empty and stay empty.","","Upgrade Bun, then run this command again:"," bun upgrade # Bun installed itself (~/.bun)"," brew upgrade bun # Homebrew"," npm install -g bun@latest # npm-managed Bun","",`Have a newer Bun elsewhere? Point Rove at it: ${K}=/path/to/bun`,`Run on this one anyway (unsupported, terminals will be blank): ${p}=1`,""].join(`
5
5
  `)}function s(b,W=Y()){return[`${W}: the Bun at ${b} could not be run — \`${b} --version\` failed or never returned.`,"","Rove skipped it rather than starting through it, which would hang or fail","with a message from that binary instead of this one.","","Reinstall Bun, then run this command again:"," curl -fsSL https://bun.sh/install | bash","",`Have a working Bun elsewhere? Point Rove at it: ${K}=/path/to/bun`,""].join(`
6
- `)}function y(b=process.env,W=process.stdin,k=process.stdout){if(b[a]==="1")return!1;if(b.CI==="true"||b.CI==="1")return!1;return Boolean(W.isTTY&&k.isTTY)}function d(b={},W=h){let k=b.platform??process.platform,[J,...$]=W1(k);if(!J)return null;let z=W(J,$,{stdio:"inherit"});if(z.error||z.status!==0)return null;return L(b).bun}function k1(b){if(typeof b.status==="number")return b.status;if(b.signal)return 128+(Object.hasOwn(V,b.signal)?V[b.signal]:0);return 1}var V={SIGINT:2,SIGQUIT:3,SIGKILL:9,SIGTERM:15};function f(b,W,k,J=h){let $=J(b,[W,...k],{stdio:"inherit"});if($.error)return process.stderr.write(`rove: could not start Bun at ${b}: ${$.error.message}
7
- `),1;return k1($)}var I=O(import.meta.url),X=M(import.meta.url),A=z1(I,`${X}-run.js`);async function Q1(b){let W=$1({input:process.stdin,output:process.stdout});try{let k=(await W.question(b)).trim().toLowerCase();return k===""||k==="y"||k==="yes"}finally{W.close()}}async function X1(){let b={launcherDir:I},W=L(b);if(W.bun||!y())return W;let k=W.stale?`${X}: Bun ${W.stale.version} is too old for Rove (needs ${F}+). Install the latest Bun now? [Y/n] `:`${X}: Rove runs on the Bun runtime, and none is installed. Install Bun now? [Y/n] `;if(!await Q1(k))return W;return{bun:d(b),stale:W.stale,unusable:W.unusable}}var R=globalThis.Bun;if(R){let b=R.version;if(b&&!G()&&!j(b))process.stderr.write(D(process.execPath,b,X)),process.exit(1);await import(J1(A).href)}else{let{bun:b,stale:W,unusable:k}=await X1();if(!b){let J=W?D(W.path,W.version,X):k?s(k,X):T(X);process.stderr.write(J),process.exit(1)}process.exit(f(b,A,process.argv.slice(2)))}
6
+ `)}function y(b=process.env,W=process.stdin,k=process.stdout){if(b[a]==="1")return!1;if(b.CI==="true"||b.CI==="1")return!1;return Boolean(W.isTTY&&k.isTTY)}function d(b={},W=j){let k=b.platform??process.platform,[J,...$]=W1(k);if(!J)return null;let z=W(J,$,{stdio:"inherit"});if(z.error||z.status!==0)return null;return L(b).bun}function k1(b){if(typeof b.status==="number")return b.status;if(b.signal)return 128+(Object.hasOwn(V,b.signal)?V[b.signal]:0);return 1}var V={SIGINT:2,SIGQUIT:3,SIGKILL:9,SIGTERM:15};function f(b,W,k,J=j){let $=J(b,[W,...k],{stdio:"inherit"});if($.error)return process.stderr.write(`rove: could not start Bun at ${b}: ${$.error.message}
7
+ `),1;return k1($)}var I=O(import.meta.url),X=M(import.meta.url),A=z1(I,`${X}-run.js`);async function Q1(b){let W=$1({input:process.stdin,output:process.stdout});try{let k=(await W.question(b)).trim().toLowerCase();return k===""||k==="y"||k==="yes"}finally{W.close()}}async function X1(){let b={launcherDir:I},W=L(b);if(W.bun||!y())return W;let k=W.stale?`${X}: Bun ${W.stale.version} is too old for Rove (needs ${F}+). Install the latest Bun now? [Y/n] `:`${X}: Rove runs on the Bun runtime, and none is installed. Install Bun now? [Y/n] `;if(!await Q1(k))return W;return{bun:d(b),stale:W.stale,unusable:W.unusable}}var R=globalThis.Bun;if(R){let b=R.version;if(b&&!G()&&!h(b))process.stderr.write(D(process.execPath,b,X)),process.exit(1);await import(J1(A).href)}else{let{bun:b,stale:W,unusable:k}=await X1();if(!b){let J=W?D(W.path,W.version,X):k?s(k,X):T(X);process.stderr.write(J),process.exit(1)}process.exit(f(b,A,process.argv.slice(2)))}
@@ -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: 38 — bump in lockstep with KOBE_SKILL_VERSION (src/lib/skill-install.ts). -->
6
+ <!-- rove-skill-version: 39 — bump in lockstep with KOBE_SKILL_VERSION (src/lib/skill-install.ts). -->
7
7
 
8
8
  # Rove shell control
9
9
 
@@ -332,6 +332,10 @@ rove api pane-open --placement tab --title logs --command "tail -f app.log"
332
332
  # Close panes you opened, by their --title (engine panes are never closed).
333
333
  rove api pane-close --title logs
334
334
 
335
+ # Close one whole Terminal Tab by the id from `get-task .tabs[]`.
336
+ # This works with or without an attached TUI.
337
+ rove api tab-close --task-id <id> --tab tab-3
338
+
335
339
  # Toast a one-liner in every attached Rove UI — surface "done / needs input /
336
340
  # error" moments without touching any session (kinds get severity styling).
337
341
  rove api notify --title "build green, artifacts in dist/" --kind done
@@ -85,6 +85,7 @@ note --task-id(REQ) --text(REQ)
85
85
  note-list --repo(REQ)
86
86
  pane-open --command --task-id --tab --direction[right|down] --placement[split|tab] --title
87
87
  pane-close --title(REQ) --task-id --tab
88
+ tab-close --task-id(REQ) --tab(REQ)
88
89
  notify --title(REQ) --kind --task-id --source
89
90
  prompt --title(REQ) --placeholder --initial --timeout
90
91
  set-active --task-id | --none
@@ -106,6 +107,12 @@ treatment and an unread mark, anything else renders neutrally.
106
107
  `pane-open --command` runs through the login shell's `-ilc`, so pipes and
107
108
  your rc's PATH work.
108
109
 
110
+ `tab-close` names one exact Terminal Tab from `get-task .tabs[].id`. Unlike
111
+ `pane-close`, it also works headless: it removes the persisted tab snapshot
112
+ and ends that tab's hosted PTYs. It accepts engine, shell/command, and content
113
+ tabs; closing the last tab leaves the task open with no session. A missing or
114
+ already-closed id returns `TAB_NOT_FOUND` and points back to `get-task`.
115
+
109
116
  ## create / edit / lifecycle
110
117
 
111
118
  ```text
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.78",
4
+ "version": "0.9.79",
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",
@@ -77,6 +77,7 @@
77
77
  "//": "biome.json + bunfig.toml live at the monorepo root since they apply repo-wide; bun.lock also lives at root (workspace-shared).",
78
78
  "dependencies": {
79
79
  "@ansi-tools/parser": "^1.0.15",
80
+ "@dagrejs/dagre": "^3.1.1",
80
81
  "@opentui/core": "0.4.3",
81
82
  "@opentui/react": "0.4.3",
82
83
  "@xterm/addon-serialize": "^0.14.0",