@sma1lboy/rove 0.9.274 → 0.9.276

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 (195) hide show
  1. package/dist/cli/chunk-0d7517kk.js +6 -0
  2. package/dist/cli/{chunk-55ajzrj6.js → chunk-0r1jf8m9.js} +1 -1
  3. package/dist/cli/{chunk-qe7xb4rm.js → chunk-1ca2j9w6.js} +2 -2
  4. package/dist/cli/chunk-1eef3z5v.js +3 -0
  5. package/dist/cli/{chunk-8h437k1q.js → chunk-1jjqk7sq.js} +1 -1
  6. package/dist/cli/chunk-1n03wzx4.js +3 -0
  7. package/dist/cli/{chunk-9trbc3kj.js → chunk-22rgewg0.js} +2 -2
  8. package/dist/cli/{chunk-jwedmkm8.js → chunk-283vd9h7.js} +1 -1
  9. package/dist/cli/chunk-2kqxz9a4.js +5 -0
  10. package/dist/cli/chunk-2xsxcdp6.js +3 -0
  11. package/dist/cli/{chunk-bj6sa371.js → chunk-372g44dg.js} +1 -1
  12. package/dist/cli/{chunk-4dxc29mm.js → chunk-387w0db1.js} +1 -1
  13. package/dist/cli/{chunk-ypd337d0.js → chunk-3xkhcfet.js} +2 -2
  14. package/dist/cli/{chunk-qvnr8c18.js → chunk-3y9xzbqh.js} +1 -1
  15. package/dist/cli/chunk-4117kgmx.js +2 -0
  16. package/dist/cli/chunk-4a05fgdh.js +2 -0
  17. package/dist/cli/chunk-4dt1gfb3.js +3 -0
  18. package/dist/cli/{chunk-ycd28edp.js → chunk-4xvmrg86.js} +3 -4
  19. package/dist/cli/{chunk-sa48rtjz.js → chunk-511103e8.js} +1 -1
  20. package/dist/cli/chunk-59p3h5e9.js +2 -0
  21. package/dist/cli/{chunk-egpcaxwb.js → chunk-5e9y8aw5.js} +1 -1
  22. package/dist/cli/chunk-5nvg3ek8.js +3 -0
  23. package/dist/cli/chunk-5yfffvqe.js +2 -0
  24. package/dist/cli/{chunk-16ttm9x6.js → chunk-63cwjceg.js} +1 -1
  25. package/dist/cli/{chunk-y5axx6ev.js → chunk-6mtfafaw.js} +1 -1
  26. package/dist/cli/{chunk-0g3sjn8z.js → chunk-6xga1a2d.js} +1 -1
  27. package/dist/cli/{chunk-xbwq4bc0.js → chunk-745pg3xm.js} +1 -1
  28. package/dist/cli/{chunk-29s67j3k.js → chunk-81thm1eb.js} +4 -4
  29. package/dist/cli/chunk-82apkcrk.js +5 -0
  30. package/dist/cli/chunk-84pvn784.js +2 -0
  31. package/dist/cli/{chunk-1exwrmjd.js → chunk-883fyezq.js} +1 -1
  32. package/dist/cli/{chunk-gryq2vgw.js → chunk-8dd60adw.js} +1 -1
  33. package/dist/cli/{chunk-qfe1wf5c.js → chunk-91tcwxph.js} +1 -1
  34. package/dist/cli/{chunk-mxgtz5vz.js → chunk-9c3brkb3.js} +1 -1
  35. package/dist/cli/chunk-9gh8kgjs.js +2 -0
  36. package/dist/cli/{chunk-h8t4xg1p.js → chunk-9rj2fx6v.js} +1 -1
  37. package/dist/cli/{chunk-w9cdc97q.js → chunk-a4r45qdn.js} +1 -1
  38. package/dist/cli/{chunk-p6jw0zcd.js → chunk-agvtzads.js} +1 -1
  39. package/dist/cli/{chunk-gcg5h667.js → chunk-awh7np6x.js} +1 -1
  40. package/dist/cli/chunk-b035pej7.js +20 -0
  41. package/dist/cli/{chunk-ez438kn3.js → chunk-b95q6zhk.js} +1 -1
  42. package/dist/cli/chunk-brgfsm5v.js +2 -0
  43. package/dist/cli/chunk-bw98jn7g.js +18 -0
  44. package/dist/cli/{chunk-bexnp6g4.js → chunk-c63vgbkw.js} +1 -1
  45. package/dist/cli/{chunk-8sggyn8y.js → chunk-c6fy8xew.js} +1 -1
  46. package/dist/cli/chunk-c7mz2aq0.js +2 -0
  47. package/dist/cli/{chunk-ec7f3wcm.js → chunk-cbrt4s7m.js} +2 -2
  48. package/dist/cli/chunk-ccwe9n56.js +19 -0
  49. package/dist/cli/chunk-cfzg8q3e.js +4 -0
  50. package/dist/cli/{chunk-387ecqb8.js → chunk-d0hpes59.js} +1 -1
  51. package/dist/cli/{chunk-edrxs4cy.js → chunk-d7f022eb.js} +5 -5
  52. package/dist/cli/{chunk-by6fjf7m.js → chunk-d7xbm9jp.js} +1 -1
  53. package/dist/cli/{chunk-3v9s3bcz.js → chunk-d9643dwf.js} +1 -1
  54. package/dist/cli/{chunk-x20bs6bs.js → chunk-dgx02565.js} +1 -1
  55. package/dist/cli/{chunk-ecrw211n.js → chunk-dt676ks9.js} +1 -1
  56. package/dist/cli/{chunk-g9yba5vh.js → chunk-e3cd4qd2.js} +2 -2
  57. package/dist/cli/chunk-e3t1zbv1.js +5 -0
  58. package/dist/cli/{chunk-0rrmz6k6.js → chunk-eege1x0a.js} +1 -1
  59. package/dist/cli/{chunk-t34kjg5y.js → chunk-ehm9abge.js} +4 -3
  60. package/dist/cli/{chunk-mmq6922s.js → chunk-eq7vey2j.js} +2 -2
  61. package/dist/cli/chunk-eyvw70yb.js +2 -0
  62. package/dist/cli/{chunk-m6yy3qc1.js → chunk-f76gzvq3.js} +1 -1
  63. package/dist/cli/{chunk-xkmdxcjg.js → chunk-fn7ffyam.js} +1 -1
  64. package/dist/cli/chunk-g4dtqbrj.js +2 -0
  65. package/dist/cli/chunk-g9ba25q5.js +3 -0
  66. package/dist/cli/{chunk-22d4fjjb.js → chunk-gafkp74h.js} +1 -1
  67. package/dist/cli/chunk-gctqthxq.js +97 -0
  68. package/dist/cli/{chunk-dpq60qph.js → chunk-gq57he03.js} +1 -1
  69. package/dist/cli/chunk-h2gznz46.js +2 -0
  70. package/dist/cli/{chunk-03rbg95q.js → chunk-h64rsbrx.js} +5 -5
  71. package/dist/cli/{chunk-5dd7trgf.js → chunk-h7vwn62z.js} +1 -1
  72. package/dist/cli/chunk-hcvp84b3.js +4 -0
  73. package/dist/cli/chunk-hhcmzs67.js +78 -0
  74. package/dist/cli/chunk-hmjg1qh3.js +2 -0
  75. package/dist/cli/{chunk-jd7p0y5x.js → chunk-j9b285x6.js} +1 -1
  76. package/dist/cli/{chunk-tw9w8pzg.js → chunk-jckx79gk.js} +3 -3
  77. package/dist/cli/{chunk-r77pfw4m.js → chunk-je80r59s.js} +1 -1
  78. package/dist/cli/{chunk-sbds7zx4.js → chunk-jfcn77n9.js} +1 -1
  79. package/dist/cli/chunk-jn10xeft.js +2 -0
  80. package/dist/cli/{chunk-g263457v.js → chunk-k1pwp155.js} +1 -1
  81. package/dist/cli/chunk-k235z3ct.js +2 -0
  82. package/dist/cli/{chunk-qs1r0tqr.js → chunk-m2a19yt4.js} +1 -1
  83. package/dist/cli/{chunk-5gzpq34w.js → chunk-m73x5nry.js} +3 -3
  84. package/dist/cli/chunk-ma21srvx.js +3 -0
  85. package/dist/cli/chunk-mdc7b01e.js +3 -0
  86. package/dist/cli/{chunk-kgs56yns.js → chunk-mkfc9a09.js} +1 -1
  87. package/dist/cli/{chunk-9er68n24.js → chunk-mq88bvj6.js} +1 -1
  88. package/dist/cli/chunk-mqfvzdpr.js +3 -0
  89. package/dist/cli/{chunk-m4dvx7bd.js → chunk-mz1ffkqb.js} +3 -3
  90. package/dist/cli/{chunk-1rjq808h.js → chunk-n0rdn2fn.js} +1 -1
  91. package/dist/cli/{chunk-sza3tyhs.js → chunk-n6marmjn.js} +1 -1
  92. package/dist/cli/chunk-n8t4y0bj.js +10 -0
  93. package/dist/cli/chunk-nbpq1tkx.js +98 -0
  94. package/dist/cli/{chunk-b492aee1.js → chunk-ne6x6g2c.js} +1 -1
  95. package/dist/cli/{chunk-fexzfgd1.js → chunk-nr7e3e82.js} +1 -1
  96. package/dist/cli/chunk-ns35rdyk.js +3 -0
  97. package/dist/cli/chunk-pap7k3b4.js +3 -0
  98. package/dist/cli/chunk-pdq3ya2e.js +3 -0
  99. package/dist/cli/chunk-q8ffd1pc.js +3 -0
  100. package/dist/cli/{chunk-39sfhppm.js → chunk-qna1s1r4.js} +1 -1
  101. package/dist/cli/{chunk-tjj9bt7n.js → chunk-qqr4tfhk.js} +1 -1
  102. package/dist/cli/chunk-r7kmn4js.js +2 -0
  103. package/dist/cli/chunk-r7ntkd6y.js +15 -0
  104. package/dist/cli/{chunk-rtpa8hg3.js → chunk-rjfdzjhj.js} +1 -1
  105. package/dist/cli/chunk-syfs63r2.js +2 -0
  106. package/dist/cli/{chunk-4hnz77xf.js → chunk-syn0tfwy.js} +1 -1
  107. package/dist/cli/chunk-t4qr9sv4.js +4 -0
  108. package/dist/cli/{chunk-6jk2khme.js → chunk-t52gzaeb.js} +1 -1
  109. package/dist/cli/chunk-teh40faw.js +1 -1
  110. package/dist/cli/{chunk-gqh6atvp.js → chunk-tjhw09bz.js} +1 -1
  111. package/dist/cli/chunk-tq0h3vy6.js +3 -0
  112. package/dist/cli/{chunk-snqa07h6.js → chunk-tvdrvgen.js} +1 -1
  113. package/dist/cli/chunk-tz373e5w.js +3 -0
  114. package/dist/cli/chunk-v1r83m3n.js +3 -0
  115. package/dist/cli/chunk-vp171as9.js +65 -0
  116. package/dist/cli/chunk-vtcr71fs.js +8 -0
  117. package/dist/cli/{chunk-zaw71cf4.js → chunk-vz0f8e8q.js} +1 -1
  118. package/dist/cli/chunk-w77s2df8.js +3 -0
  119. package/dist/cli/chunk-w7v4jzwy.js +3 -0
  120. package/dist/cli/chunk-wvqn1t55.js +2 -0
  121. package/dist/cli/{chunk-r40aj7z6.js → chunk-x1ghdmp1.js} +1 -1
  122. package/dist/cli/{chunk-nzbq51h9.js → chunk-x3n4y5sp.js} +1 -1
  123. package/dist/cli/{chunk-q6septaj.js → chunk-xb3p11g0.js} +1 -1
  124. package/dist/cli/{chunk-yzkhwn31.js → chunk-xd93fm1k.js} +1 -1
  125. package/dist/cli/chunk-xn2f56tg.js +3 -0
  126. package/dist/cli/chunk-xv3217yv.js +2 -0
  127. package/dist/cli/chunk-yhytkwpv.js +2 -0
  128. package/dist/cli/{chunk-hfdk7j28.js → chunk-yk9b8zgn.js} +1 -1
  129. package/dist/cli/chunk-zat16a83.js +2 -0
  130. package/dist/cli/chunk-zcrs4sm2.js +3 -0
  131. package/dist/cli/{chunk-kx53jjee.js → chunk-zkp6nty3.js} +8 -6
  132. package/dist/cli/index.js +5 -5
  133. package/dist/cli/pty-host-node.mjs +258 -29
  134. package/dist/cli/rove-run.js +1 -1
  135. package/dist/cli/rove.js +1 -1
  136. package/dist/completions/rove.bash +2 -2
  137. package/dist/completions/rove.fish +2 -2
  138. package/dist/completions/rove.zsh +2 -2
  139. package/dist/skills/rove/SKILL.md +23 -9
  140. package/dist/skills/rove/references/api-flags.md +20 -11
  141. package/dist/web/assets/index-C5t3gibI.css +1 -0
  142. package/dist/web/assets/index-Djp7M6r8.js +122 -0
  143. package/dist/web/index.html +2 -2
  144. package/dist/web/sw.js +52 -0
  145. package/package.json +3 -3
  146. package/dist/cli/chunk-033k4ap7.js +0 -2
  147. package/dist/cli/chunk-0ppkvphp.js +0 -2
  148. package/dist/cli/chunk-11wyec8z.js +0 -2
  149. package/dist/cli/chunk-15fp4p9v.js +0 -15
  150. package/dist/cli/chunk-1ffqacz9.js +0 -3
  151. package/dist/cli/chunk-2v68zaaa.js +0 -2
  152. package/dist/cli/chunk-2y29zrm1.js +0 -2
  153. package/dist/cli/chunk-4d1v6066.js +0 -3
  154. package/dist/cli/chunk-5zsdjrgz.js +0 -4
  155. package/dist/cli/chunk-68wpp5y8.js +0 -20
  156. package/dist/cli/chunk-6h4qdckd.js +0 -3
  157. package/dist/cli/chunk-6jj82bej.js +0 -2
  158. package/dist/cli/chunk-783d1ba0.js +0 -3
  159. package/dist/cli/chunk-78v1q5mz.js +0 -2
  160. package/dist/cli/chunk-7z463zkx.js +0 -3
  161. package/dist/cli/chunk-97m9nyw7.js +0 -2
  162. package/dist/cli/chunk-9bae7f3m.js +0 -4
  163. package/dist/cli/chunk-b5c7p22a.js +0 -2
  164. package/dist/cli/chunk-b5pytfgm.js +0 -2
  165. package/dist/cli/chunk-b68dd36h.js +0 -3
  166. package/dist/cli/chunk-bbksmb5a.js +0 -3
  167. package/dist/cli/chunk-cpf78z3x.js +0 -4
  168. package/dist/cli/chunk-cyzp2btw.js +0 -63
  169. package/dist/cli/chunk-e01321zn.js +0 -5
  170. package/dist/cli/chunk-erx7x9xg.js +0 -97
  171. package/dist/cli/chunk-ewqqwtrj.js +0 -2
  172. package/dist/cli/chunk-fmbv4m3y.js +0 -25
  173. package/dist/cli/chunk-fs51wx31.js +0 -3
  174. package/dist/cli/chunk-fvvb0072.js +0 -3
  175. package/dist/cli/chunk-g3tv8kht.js +0 -2
  176. package/dist/cli/chunk-g53yqr82.js +0 -78
  177. package/dist/cli/chunk-k67vbszb.js +0 -3
  178. package/dist/cli/chunk-kyt9ytz2.js +0 -20
  179. package/dist/cli/chunk-n2ejvjrd.js +0 -3
  180. package/dist/cli/chunk-p4s826r2.js +0 -96
  181. package/dist/cli/chunk-p6334e7v.js +0 -2
  182. package/dist/cli/chunk-q9zgj6kw.js +0 -3
  183. package/dist/cli/chunk-rzef6szc.js +0 -3
  184. package/dist/cli/chunk-sqxdfzdq.js +0 -5
  185. package/dist/cli/chunk-sz2xs0a2.js +0 -4
  186. package/dist/cli/chunk-t5y8k772.js +0 -2
  187. package/dist/cli/chunk-vht2e44j.js +0 -10
  188. package/dist/cli/chunk-vjp7drne.js +0 -2
  189. package/dist/cli/chunk-vm551pxs.js +0 -2
  190. package/dist/cli/chunk-w09356fj.js +0 -20
  191. package/dist/cli/chunk-xmqv1zx6.js +0 -2
  192. package/dist/cli/chunk-xn7bk4f9.js +0 -3
  193. package/dist/cli/chunk-zybjm7d5.js +0 -2
  194. package/dist/web/assets/index-C9vaSoIJ.js +0 -113
  195. package/dist/web/assets/index-sA2EEQJw.css +0 -1
@@ -494,7 +494,7 @@ function formatPtyHostLine(event, message, now = new Date) {
494
494
  }
495
495
 
496
496
  // ../rove-daemon/src/daemon/pty-server.ts
497
- import { readFileSync as readFileSync4 } from "node:fs";
497
+ import { readFileSync as readFileSync5 } from "node:fs";
498
498
  import { mkdir as mkdir4, unlink } from "node:fs/promises";
499
499
  import { createServer } from "node:net";
500
500
  import { dirname as dirname8 } from "node:path";
@@ -773,10 +773,14 @@ var BLOCKING_RPCS = new Set([
773
773
  "task.ensureWorktree",
774
774
  "task.spawn",
775
775
  "task.ensureMain",
776
+ "task.moveToProject",
776
777
  "worktree.discoverAdoptable",
777
778
  "worktree.adopt",
778
779
  "worktree.list",
779
- "worktree.remove"
780
+ "worktree.remove",
781
+ "task.checkpoint",
782
+ "task.rewind",
783
+ "task.exportBranch"
780
784
  ]);
781
785
  var PTY_STOP_REFUSED = "PtyStopRefused";
782
786
  function frameToLine(frame) {
@@ -939,6 +943,152 @@ import { mkdirSync as mkdirSync4, readFileSync as readFileSync3, readdirSync, re
939
943
  import { join as join7 } from "node:path";
940
944
  import { StringDecoder } from "node:string_decoder";
941
945
 
946
+ // ../rove-daemon/src/daemon/kitty-transmits.ts
947
+ var MAX_IMAGES = 8;
948
+ var MAX_BYTES = 16 * 1024 * 1024;
949
+ var ESC = 27;
950
+ var OPEN = Buffer.from("\x1B_");
951
+ var CLOSE = Buffer.from("\x1B\\");
952
+ function parseKeys(control) {
953
+ const keys = new Map;
954
+ for (const pair of control.split(",")) {
955
+ const eq = pair.indexOf("=");
956
+ if (eq > 0)
957
+ keys.set(pair.slice(0, eq), pair.slice(eq + 1));
958
+ }
959
+ return keys;
960
+ }
961
+
962
+ class KittyTransmits {
963
+ images = new Map;
964
+ bytes = 0;
965
+ apc = null;
966
+ apcBytes = 0;
967
+ escPending = false;
968
+ upload = null;
969
+ push(buf) {
970
+ let i = 0;
971
+ if (this.escPending && buf.length > 0) {
972
+ this.escPending = false;
973
+ if (this.apc && buf[0] === 92) {
974
+ this.finish();
975
+ i = 1;
976
+ } else {
977
+ this.apc = null;
978
+ if (buf[0] === 95)
979
+ this.open();
980
+ if (buf[0] === 95 || buf[0] === 99)
981
+ i = 1;
982
+ if (buf[0] === 99)
983
+ this.clear();
984
+ }
985
+ }
986
+ while (i < buf.length) {
987
+ if (this.apc) {
988
+ const esc2 = buf.indexOf(ESC, i);
989
+ if (esc2 === -1) {
990
+ this.append(buf.subarray(i));
991
+ return;
992
+ }
993
+ this.append(buf.subarray(i, esc2));
994
+ if (esc2 + 1 >= buf.length) {
995
+ this.escPending = true;
996
+ return;
997
+ }
998
+ if (buf[esc2 + 1] === 92)
999
+ this.finish();
1000
+ else
1001
+ this.apc = null;
1002
+ i = esc2 + 2;
1003
+ continue;
1004
+ }
1005
+ const esc = buf.indexOf(ESC, i);
1006
+ if (esc === -1)
1007
+ return;
1008
+ if (esc + 1 >= buf.length) {
1009
+ this.escPending = true;
1010
+ return;
1011
+ }
1012
+ const next = buf[esc + 1];
1013
+ if (next === 95)
1014
+ this.open();
1015
+ else if (next === 99)
1016
+ this.clear();
1017
+ i = esc + 2;
1018
+ }
1019
+ }
1020
+ replay() {
1021
+ return Buffer.concat([...this.images.values()]);
1022
+ }
1023
+ open() {
1024
+ this.apc = [];
1025
+ this.apcBytes = 0;
1026
+ }
1027
+ append(part) {
1028
+ if (!this.apc || part.length === 0)
1029
+ return;
1030
+ this.apcBytes += part.length;
1031
+ if (this.apcBytes > MAX_BYTES)
1032
+ this.apc = null;
1033
+ else
1034
+ this.apc.push(Buffer.from(part));
1035
+ }
1036
+ finish() {
1037
+ const body = this.apc ? Buffer.concat(this.apc) : null;
1038
+ this.apc = null;
1039
+ if (!body || body[0] !== 71)
1040
+ return;
1041
+ const semi = body.indexOf(59);
1042
+ const keys = parseKeys(body.subarray(1, semi === -1 ? body.length : semi).toString("latin1"));
1043
+ const raw = Buffer.concat([OPEN, body, CLOSE]);
1044
+ if (this.upload && [...keys.keys()].every((k) => k === "m" || k === "q")) {
1045
+ this.upload.parts.push(raw);
1046
+ this.upload.bytes += raw.length;
1047
+ if (this.upload.bytes > MAX_BYTES)
1048
+ this.upload = null;
1049
+ else if (keys.get("m") !== "1") {
1050
+ const { id: id2, parts } = this.upload;
1051
+ this.upload = null;
1052
+ this.keep(id2, Buffer.concat(parts));
1053
+ }
1054
+ return;
1055
+ }
1056
+ this.upload = null;
1057
+ const action = keys.get("a") ?? "t";
1058
+ const id = Number(keys.get("i"));
1059
+ if ((action === "t" || action === "T") && (keys.get("t") ?? "d") === "d" && id > 0) {
1060
+ if (keys.get("m") === "1")
1061
+ this.upload = { id, parts: [raw], bytes: raw.length };
1062
+ else
1063
+ this.keep(id, raw);
1064
+ } else if (action === "d" && (keys.get("d") === "i" || keys.get("d") === "I"))
1065
+ this.drop(id);
1066
+ }
1067
+ keep(id, raw) {
1068
+ this.drop(id);
1069
+ this.images.set(id, raw);
1070
+ this.bytes += raw.length;
1071
+ for (const [old, kept] of this.images) {
1072
+ if (this.images.size <= MAX_IMAGES && this.bytes <= MAX_BYTES)
1073
+ break;
1074
+ this.images.delete(old);
1075
+ this.bytes -= kept.length;
1076
+ }
1077
+ }
1078
+ drop(id) {
1079
+ const kept = this.images.get(id);
1080
+ if (!kept)
1081
+ return;
1082
+ this.images.delete(id);
1083
+ this.bytes -= kept.length;
1084
+ }
1085
+ clear() {
1086
+ this.images.clear();
1087
+ this.bytes = 0;
1088
+ this.upload = null;
1089
+ }
1090
+ }
1091
+
942
1092
  // ../rove-daemon/src/daemon/terminal-colors.ts
943
1093
  var DEFAULT_TERMINAL_COLORS = {
944
1094
  foreground: "#eae7df",
@@ -1010,7 +1160,7 @@ var MOUSE_ENCODINGS = { 1006: "sgr", 1016: "sgr-pixels" };
1010
1160
  var MAX_CARRY = 64;
1011
1161
  var DA1_REPLY = "\x1B[?1;2c";
1012
1162
  function freshModeTrack(modes = { ...DEFAULT_MODES }) {
1013
- return { modes, carry: "" };
1163
+ return { modes, carry: "", inString: null };
1014
1164
  }
1015
1165
  function normalizeTerminalModes(raw) {
1016
1166
  const modes = { ...DEFAULT_MODES };
@@ -1031,7 +1181,18 @@ function scanTerminalModes(track, chunk) {
1031
1181
  const text = track.carry + chunk;
1032
1182
  track.carry = "";
1033
1183
  const replies = [];
1034
- let i = text.indexOf("\x1B");
1184
+ let i = 0;
1185
+ if (track.inString) {
1186
+ const end = stringEnd(text, 0, track.inString);
1187
+ if (end < 0) {
1188
+ if (text.endsWith("\x1B"))
1189
+ track.carry = "\x1B";
1190
+ return replies;
1191
+ }
1192
+ track.inString = null;
1193
+ i = end;
1194
+ }
1195
+ i = text.indexOf("\x1B", i);
1035
1196
  while (i !== -1) {
1036
1197
  if (i + 1 >= text.length) {
1037
1198
  track.carry = "\x1B";
@@ -1050,6 +1211,18 @@ function scanTerminalModes(track, chunk) {
1050
1211
  i = text.indexOf("\x1B", end >= 0 ? end + 1 : i + 2);
1051
1212
  continue;
1052
1213
  }
1214
+ const kind = STRING_INTRODUCERS[text[i + 1]];
1215
+ if (kind) {
1216
+ const end = stringEnd(text, i + 2, kind);
1217
+ if (end < 0) {
1218
+ track.inString = kind;
1219
+ if (text.endsWith("\x1B"))
1220
+ track.carry = "\x1B";
1221
+ break;
1222
+ }
1223
+ i = text.indexOf("\x1B", end);
1224
+ continue;
1225
+ }
1053
1226
  if (next === 61)
1054
1227
  track.modes.applicationKeypad = true;
1055
1228
  else if (next === 62)
@@ -1096,6 +1269,23 @@ function terminalModePreamble(modes) {
1096
1269
  out += "\x1B[4h";
1097
1270
  return out;
1098
1271
  }
1272
+ function replayStart(track, ring) {
1273
+ if (!track.inString)
1274
+ return 0;
1275
+ const text = track.carry + ring.toString("latin1");
1276
+ const end = stringEnd(text, 0, track.inString);
1277
+ return end < 0 ? ring.byteLength : Math.max(0, end - track.carry.length);
1278
+ }
1279
+ var STRING_INTRODUCERS = { _: "st", P: "st", "^": "st", X: "st", "]": "osc" };
1280
+ function stringEnd(text, from, kind) {
1281
+ const esc = text.indexOf("\x1B", from);
1282
+ const bel = kind === "osc" ? text.indexOf("\x07", from) : -1;
1283
+ if (bel !== -1 && (esc === -1 || bel < esc))
1284
+ return bel + 1;
1285
+ if (esc === -1 || esc + 1 >= text.length)
1286
+ return -1;
1287
+ return text[esc + 1] === "\\" ? esc + 2 : esc;
1288
+ }
1099
1289
  function csiEnd(text, from) {
1100
1290
  for (let j = from;j < text.length; j++) {
1101
1291
  const c = text.charCodeAt(j);
@@ -1263,6 +1453,7 @@ function ansiModeValue(modes, mode) {
1263
1453
  // ../rove-daemon/src/daemon/pty-freeze-store.ts
1264
1454
  var FREEZE_VERSION = 1;
1265
1455
  function freezeSession(session, now = new Date) {
1456
+ const ring = Buffer.concat(session.chunks);
1266
1457
  return {
1267
1458
  v: FREEZE_VERSION,
1268
1459
  key: session.key,
@@ -1273,7 +1464,7 @@ function freezeSession(session, now = new Date) {
1273
1464
  title: session.title,
1274
1465
  totalBytes: session.totalBytes,
1275
1466
  exit: session.exit,
1276
- ringB64: Buffer.concat(session.chunks).toString("base64"),
1467
+ ringB64: ring.subarray(session.ringModes ? replayStart(session.ringModes, ring) : 0).toString("base64"),
1277
1468
  ...session.ringModes ? { ringModes: session.ringModes.modes } : {},
1278
1469
  updatedAt: now.toISOString()
1279
1470
  };
@@ -1318,12 +1509,13 @@ function thawSession(record, cap) {
1318
1509
  defaultColors: DEFAULT_TERMINAL_COLORS,
1319
1510
  modes,
1320
1511
  ringModes: ring.ringModes,
1512
+ kitty: new KittyTransmits,
1321
1513
  sinks: new Map,
1322
1514
  emulatorSinks: new Set,
1323
1515
  parked: false,
1324
1516
  parkedScreenBytes: 0,
1325
1517
  exit: record.exit,
1326
- restored: true,
1518
+ restored: record.exit === null,
1327
1519
  lastFreezeAtMs: 0
1328
1520
  };
1329
1521
  }
@@ -1606,7 +1798,10 @@ function scanOscSignals(signals, bytes, now = Date.now(), onRootChange) {
1606
1798
  }
1607
1799
 
1608
1800
  // ../rove-daemon/src/daemon/pty-child-controller.ts
1801
+ import { spawn } from "node:child_process";
1609
1802
  import { randomUUID as randomUUID6 } from "node:crypto";
1803
+ import { readFileSync as readFileSync4 } from "node:fs";
1804
+ import path from "node:path";
1610
1805
 
1611
1806
  // ../rove-daemon/src/daemon/platform-shell.js
1612
1807
  import { existsSync as existsSync6 } from "node:fs";
@@ -1693,6 +1888,7 @@ function embeddedTerminalEnv(base, overrides = {}) {
1693
1888
  // ../rove-daemon/src/daemon/pty-host-types.ts
1694
1889
  import { randomUUID as randomUUID5 } from "node:crypto";
1695
1890
  import { StringDecoder as StringDecoder3 } from "node:string_decoder";
1891
+ var LAUNCH_PREFIX_FILE = ".rove-launch.json";
1696
1892
  function freshSessionState(key, spec, argv) {
1697
1893
  return {
1698
1894
  key,
@@ -1713,6 +1909,7 @@ function freshSessionState(key, spec, argv) {
1713
1909
  defaultColors: parseTerminalDefaultColors(spec.defaultColors) ?? DEFAULT_TERMINAL_COLORS,
1714
1910
  modes: freshModeTrack(),
1715
1911
  ringModes: freshModeTrack(),
1912
+ kitty: new KittyTransmits,
1716
1913
  sinks: new Map,
1717
1914
  emulatorSinks: new Set,
1718
1915
  parked: false,
@@ -1895,8 +2092,9 @@ class PtyChildController {
1895
2092
  session.programStatusEvent = undefined;
1896
2093
  this.reportStatus(session, null);
1897
2094
  try {
2095
+ const launch = launchWrapper(session.cwd, session.generation);
1898
2096
  session.proc = (this.deps.driver ?? bunTerminalDriver())({
1899
- argv: [...session.command],
2097
+ argv: [...launch.prefix, ...session.command],
1900
2098
  cwd: session.cwd,
1901
2099
  env: embeddedTerminalEnv(process.env, {
1902
2100
  TERM: "xterm-256color",
@@ -1911,7 +2109,11 @@ class PtyChildController {
1911
2109
  onData: (data) => this.onData(session, data)
1912
2110
  });
1913
2111
  session.alive = true;
1914
- session.proc.exited.then((exit) => this.markExited(session, exit), () => this.markExited(session));
2112
+ const reap = launch.reap;
2113
+ session.proc.exited.then((exit) => this.markExited(session, exit), () => this.markExited(session)).then(() => {
2114
+ if (reap.length > 0)
2115
+ spawn(reap[0], reap.slice(1), { detached: true, stdio: "ignore" }).unref();
2116
+ });
1915
2117
  } catch (err) {
1916
2118
  session.alive = false;
1917
2119
  this.deps.log?.("pty", `spawn failed for ${session.key}: ${err instanceof Error ? err.message : String(err)}`);
@@ -1978,6 +2180,7 @@ class PtyChildController {
1978
2180
  } catch {}
1979
2181
  }
1980
2182
  scanOscTitle(session, buf);
2183
+ session.kitty.push(buf);
1981
2184
  session.chunks.push(buf);
1982
2185
  session.bytes += buf.byteLength;
1983
2186
  session.totalBytes += buf.byteLength;
@@ -1991,6 +2194,24 @@ class PtyChildController {
1991
2194
  this.deps.onOutput?.(session, buf);
1992
2195
  }
1993
2196
  }
2197
+ function launchWrapper(cwd, id) {
2198
+ let raw;
2199
+ try {
2200
+ raw = readFileSync4(path.join(cwd, LAUNCH_PREFIX_FILE), "utf8");
2201
+ } catch {
2202
+ return { prefix: [], reap: [] };
2203
+ }
2204
+ const file = JSON.parse(raw);
2205
+ const argv = (field, name) => {
2206
+ if (field === undefined && name === "reap")
2207
+ return [];
2208
+ if (!Array.isArray(field) || !field.every((a) => typeof a === "string")) {
2209
+ throw new Error(`${LAUNCH_PREFIX_FILE} in ${cwd}: "${name}" is not a string array`);
2210
+ }
2211
+ return field.map((a) => a.replaceAll("{launch}", id));
2212
+ };
2213
+ return { prefix: argv(file.prefix, "prefix"), reap: argv(file.reap, "reap") };
2214
+ }
1994
2215
 
1995
2216
  // ../rove-daemon/src/daemon/pty-freeze-policy.ts
1996
2217
  var FREEZE_INTERVAL_MS = 5000;
@@ -2063,11 +2284,19 @@ class WarmSpare {
2063
2284
  var LOGGED_WRITE_BYTES = 1024;
2064
2285
  var DEFAULT_SCROLLBACK_CAP = 512 * 1024;
2065
2286
  var EXIT_TAIL_BYTES = 16 * 1024;
2287
+ function fullReplay(session, ring) {
2288
+ return Buffer.concat([
2289
+ Buffer.from(terminalModePreamble(session.ringModes.modes), "latin1"),
2290
+ session.kitty.replay(),
2291
+ ring.subarray(replayStart(session.ringModes, ring))
2292
+ ]);
2293
+ }
2066
2294
 
2067
2295
  class PtyHost {
2068
2296
  sessions = new Map;
2069
2297
  opts;
2070
2298
  scrollbackCap;
2299
+ shuttingDown = false;
2071
2300
  parkRestoreDeltas = 0;
2072
2301
  parkRestoreFallbacks = 0;
2073
2302
  childController;
@@ -2167,7 +2396,7 @@ class PtyHost {
2167
2396
  this.parkRestoreFallbacks++;
2168
2397
  }
2169
2398
  if (!sinceValid)
2170
- replay = Buffer.concat([Buffer.from(terminalModePreamble(session.ringModes.modes), "latin1"), replay]);
2399
+ replay = fullReplay(session, replay);
2171
2400
  return {
2172
2401
  replay: replay.toString("base64"),
2173
2402
  alive: session.alive,
@@ -2270,8 +2499,7 @@ class PtyHost {
2270
2499
  const peek = peekRing(session, sinceOffset);
2271
2500
  if (!preamble || !session || sinceOffset !== undefined)
2272
2501
  return peek;
2273
- const modes = Buffer.from(terminalModePreamble(session.ringModes.modes), "latin1");
2274
- return { ...peek, data: Buffer.concat([modes, Buffer.from(peek.data, "base64")]).toString("base64") };
2502
+ return { ...peek, data: fullReplay(session, Buffer.from(peek.data, "base64")).toString("base64") };
2275
2503
  }
2276
2504
  stats() {
2277
2505
  return hostStats(this.sessions.values(), this.scrollbackCap, this.parkRestoreDeltas, this.parkRestoreFallbacks);
@@ -2283,6 +2511,7 @@ class PtyHost {
2283
2511
  }
2284
2512
  async shutdown() {
2285
2513
  this.flushFrozen();
2514
+ this.shuttingDown = true;
2286
2515
  const endings = Array.from(this.sessions.values(), (session) => this.childController.endChild(session));
2287
2516
  endings.push(this.warmSpare.end());
2288
2517
  await Promise.all(endings);
@@ -2324,7 +2553,7 @@ class PtyHost {
2324
2553
  const freeze = this.opts.freeze;
2325
2554
  if (!freeze || session.key.startsWith("::"))
2326
2555
  return;
2327
- if (session.closedByRequest)
2556
+ if (session.closedByRequest || this.shuttingDown)
2328
2557
  return;
2329
2558
  const now = Date.now();
2330
2559
  if (!force && !shouldFreeze(session, now))
@@ -2343,7 +2572,7 @@ class PtyHost {
2343
2572
  }
2344
2573
 
2345
2574
  // ../rove-daemon/src/client/detached-spawn.ts
2346
- import { spawn as spawn2 } from "node:child_process";
2575
+ import { spawn as spawn3 } from "node:child_process";
2347
2576
  import { appendFileSync, closeSync, mkdirSync as mkdirSync5, openSync } from "node:fs";
2348
2577
  import { dirname as dirname7 } from "node:path";
2349
2578
 
@@ -2381,24 +2610,24 @@ function warnOnce() {
2381
2610
  } catch {}
2382
2611
  }
2383
2612
  var writeChain = Promise.resolve();
2384
- async function rotateClientLogIfNeeded(path) {
2613
+ async function rotateClientLogIfNeeded(path2) {
2385
2614
  try {
2386
- const { size } = await stat(path);
2615
+ const { size } = await stat(path2);
2387
2616
  if (!shouldRotateLog(size, DEFAULT_LOG_ROTATE_CAP_BYTES))
2388
2617
  return;
2389
- await rename2(path, `${path}.old`);
2618
+ await rename2(path2, `${path2}.old`);
2390
2619
  } catch {}
2391
2620
  }
2392
2621
  function append(line, logPath) {
2393
- const path = logPath ?? defaultClientLogPath();
2622
+ const path2 = logPath ?? defaultClientLogPath();
2394
2623
  writeChain = writeChain.then(async () => {
2395
- await rotateClientLogIfNeeded(path);
2624
+ await rotateClientLogIfNeeded(path2);
2396
2625
  try {
2397
- await appendFile(path, line);
2626
+ await appendFile(path2, line);
2398
2627
  } catch (err) {
2399
2628
  if (err?.code === "ENOENT") {
2400
- await mkdir3(dirname6(path), { recursive: true });
2401
- await appendFile(path, line);
2629
+ await mkdir3(dirname6(path2), { recursive: true });
2630
+ await appendFile(path2, line);
2402
2631
  } else {
2403
2632
  throw err;
2404
2633
  }
@@ -2574,20 +2803,20 @@ class RoveDaemonClient {
2574
2803
  } catch (err) {
2575
2804
  if (!(err instanceof Error) || !("code" in err) || !["ENOENT", "ECONNREFUSED"].includes(String(err.code)))
2576
2805
  throw err;
2577
- for (const path of preRenameRuntimePaths(this.socketPath)) {
2806
+ for (const path2 of preRenameRuntimePaths(this.socketPath)) {
2578
2807
  if (this.disposed)
2579
2808
  throw err;
2580
2809
  try {
2581
- await this.openSocket(path);
2810
+ await this.openSocket(path2);
2582
2811
  return;
2583
2812
  } catch {}
2584
2813
  }
2585
2814
  throw err;
2586
2815
  }
2587
2816
  }
2588
- openSocket(path) {
2817
+ openSocket(path2) {
2589
2818
  return new Promise((resolve2, reject) => {
2590
- const socket = connect(path);
2819
+ const socket = connect(path2);
2591
2820
  this.socket = socket;
2592
2821
  const timeoutMs = connectTimeoutMs();
2593
2822
  let timer;
@@ -2702,7 +2931,7 @@ class RoveDaemonClient {
2702
2931
  }
2703
2932
 
2704
2933
  // ../rove-daemon/src/client/win-detached-launch.ts
2705
- import { spawn } from "node:child_process";
2934
+ import { spawn as spawn2 } from "node:child_process";
2706
2935
  import { existsSync as existsSync7 } from "node:fs";
2707
2936
  import { join as join8 } from "node:path";
2708
2937
  var LAUNCH_CMD_ENV = "ROVE_LAUNCH_CMD";
@@ -2801,7 +3030,7 @@ function windowsDetachedLauncherArgs() {
2801
3030
  encodePowershellCommand(WIN_DETACHED_LAUNCHER_PS)
2802
3031
  ];
2803
3032
  }
2804
- function spawnWindowsDetached(command, args, env, logPath, spawnImpl = spawn) {
3033
+ function spawnWindowsDetached(command, args, env, logPath, spawnImpl = spawn2) {
2805
3034
  const child = spawnImpl(windowsPowershellPath(env), windowsDetachedLauncherArgs(), {
2806
3035
  windowsHide: true,
2807
3036
  stdio: "ignore",
@@ -2878,7 +3107,7 @@ function spawnDirect(command, args, env, logPath, platform) {
2878
3107
  } catch {
2879
3108
  stdio = "ignore";
2880
3109
  }
2881
- const child = spawn2(command, [...args], { ...detachOptions(platform), stdio, env });
3110
+ const child = spawn3(command, [...args], { ...detachOptions(platform), stdio, env });
2882
3111
  child.unref();
2883
3112
  if (logFd !== undefined) {
2884
3113
  try {
@@ -3081,7 +3310,7 @@ async function startPtyHostServer(options = {}) {
3081
3310
  }
3082
3311
  let owner;
3083
3312
  try {
3084
- owner = readFileSync4(pidPath, "utf8").trim();
3313
+ owner = readFileSync5(pidPath, "utf8").trim();
3085
3314
  } catch {
3086
3315
  return `pidfile ${pidPath} is gone`;
3087
3316
  }
@@ -1,3 +1,3 @@
1
1
  #!/usr/bin/env bun
2
2
  // @bun
3
- import{isObject}from"./chunk-7ghwdjdc.js";import{migrateRoveClientStateLayout}from"./chunk-8t7qbr1e.js";import{updateStateFile}from"./chunk-32j6y5d1.js";import"./chunk-bejhca6z.js";import{kvStatePath}from"./chunk-z1nj22va.js";import"./chunk-br8r72bf.js";import"./chunk-zt7wfnva.js";import"./chunk-yt15y085.js";import"./chunk-eqdbfgq5.js";import"./chunk-f8gg8cqh.js";import"./chunk-nc46gddg.js";import{__require}from"./chunk-91sykzqq.js";import{readFileSync}from"fs";var RENAMED_KEY_PREFIXES=[{from:"autoEffort.",to:"autoRouting."}],NOTHING={moved:0,superseded:0};function legacyRename(key){for(let{from,to}of RENAMED_KEY_PREFIXES)if(key.startsWith(from))return`${to}${key.slice(from.length)}`;return}function isStateObject(text){try{let parsed=JSON.parse(text);return isObject(parsed)}catch{return!1}}function migrateRenamedStateKeys(){let text;try{text=readFileSync(kvStatePath(),"utf8")}catch{return NOTHING}if(!RENAMED_KEY_PREFIXES.some(({from})=>text.includes(`"${from}`)))return NOTHING;if(!isStateObject(text))return NOTHING;let moved=0,superseded=0;try{updateStateFile((state)=>{for(let[key,value]of Object.entries(state)){let renamed=legacyRename(key);if(renamed===void 0)continue;if(renamed in state)superseded+=1;else state[renamed]=value,moved+=1;delete state[key]}return moved+superseded>0})}catch{return NOTHING}return{moved,superseded}}function prepareCliStateLayout(env=process.env){let result=migrateRoveClientStateLayout(env);for(let warning of result.warnings)console.error(`[rove] state migration will retry: ${warning}. Check the source/destination permissions, then relaunch Rove.`);migrateRenamedStateKeys()}prepareCliStateLayout();await import("./index.js");
3
+ import{updateStateFile}from"./chunk-32j6y5d1.js";import{isObject}from"./chunk-7ghwdjdc.js";import{migrateRoveClientStateLayout}from"./chunk-8t7qbr1e.js";import"./chunk-bejhca6z.js";import{kvStatePath}from"./chunk-z1nj22va.js";import"./chunk-br8r72bf.js";import"./chunk-zt7wfnva.js";import"./chunk-yt15y085.js";import"./chunk-eqdbfgq5.js";import"./chunk-f8gg8cqh.js";import"./chunk-nc46gddg.js";import{__require}from"./chunk-91sykzqq.js";import{readFileSync}from"fs";var RENAMED_KEY_PREFIXES=[{from:"autoEffort.",to:"autoRouting."}],NOTHING={moved:0,superseded:0};function legacyRename(key){for(let{from,to}of RENAMED_KEY_PREFIXES)if(key.startsWith(from))return`${to}${key.slice(from.length)}`;return}function isStateObject(text){try{let parsed=JSON.parse(text);return isObject(parsed)}catch{return!1}}function migrateRenamedStateKeys(){let text;try{text=readFileSync(kvStatePath(),"utf8")}catch{return NOTHING}if(!RENAMED_KEY_PREFIXES.some(({from})=>text.includes(`"${from}`)))return NOTHING;if(!isStateObject(text))return NOTHING;let moved=0,superseded=0;try{updateStateFile((state)=>{for(let[key,value]of Object.entries(state)){let renamed=legacyRename(key);if(renamed===void 0)continue;if(renamed in state)superseded+=1;else state[renamed]=value,moved+=1;delete state[key]}return moved+superseded>0})}catch{return NOTHING}return{moved,superseded}}function prepareCliStateLayout(env=process.env){let result=migrateRoveClientStateLayout(env);for(let warning of result.warnings)console.error(`[rove] state migration will retry: ${warning}. Check the source/destination permissions, then relaunch Rove.`);migrateRenamedStateKeys()}prepareCliStateLayout();await import("./index.js");
package/dist/cli/rove.js CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import{join as l}from"node:path";import{createInterface as a}from"node:readline/promises";import{pathToFileURL as ss}from"node:url";import{spawnSync as Q}from"node:child_process";import{constants as e,accessSync as V}from"node:fs";import{homedir as R}from"node:os";import{basename as o,delimiter as I,dirname as U,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.274",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:{rove:"dist/cli/rove.js"},files:["dist/cli","dist/completions","dist/web","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:mock":"ROVE_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":"ROVE_INCLUDE_SOCKET=1 vitest run test/daemon --pool forks --minWorkers=1 --maxWorkers=4 --passWithNoTests","test:socket:coverage":"ROVE_INCLUDE_SOCKET=1 ROVE_COVERAGE_DAEMON=1 vitest run test/daemon --coverage --pool forks --minWorkers=1 --maxWorkers=4 --passWithNoTests","test:behavior":"ROVE_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",react:"^19.2.8","smol-toml":"^1.7.1",ws:"^8.21.3"},optionalDependencies:{"node-pty":"^1.1.0"},devDependencies:{"@biomejs/biome":"1.9.4","@sma1lboy/rove-daemon":"0.7.23","@tsconfig/bun":"1.0.11","@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","rove-bridge":"0.0.35","rove-weixin":"0.0.35",typescript:"5.8.2",vitest:"2.1.9"},trustedDependencies:[]};var q="rove";var k=q;var z="ROVE_BUN",_="ROVE_NO_BUN_BOOTSTRAP",F="ROVE_SKIP_BUN_CHECK",$=H.engines.bun.match(/\d+\.\d+\.\d+/)?.[0]??"0.0.0",L=(s)=>{try{return V(s,e.X_OK),!0}catch{return!1}},B=(s)=>s==="win32"?"bun.exe":"bun",f=(s)=>{let t=Q(s,["--version"],{encoding:"utf8",timeout:5000});if(t.error||t.status!==0)return null;return t.stdout?.split(`
2
+ import{join as l}from"node:path";import{createInterface as a}from"node:readline/promises";import{pathToFileURL as ss}from"node:url";import{spawnSync as Q}from"node:child_process";import{constants as e,accessSync as V}from"node:fs";import{homedir as R}from"node:os";import{basename as o,delimiter as I,dirname as U,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.276",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:{rove:"dist/cli/rove.js"},files:["dist/cli","dist/completions","dist/web","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:mock":"ROVE_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":"ROVE_INCLUDE_SOCKET=1 vitest run test/daemon --pool forks --minWorkers=1 --maxWorkers=4 --passWithNoTests","test:socket:coverage":"ROVE_INCLUDE_SOCKET=1 ROVE_COVERAGE_DAEMON=1 vitest run test/daemon --coverage --pool forks --minWorkers=1 --maxWorkers=4 --passWithNoTests","test:behavior":"ROVE_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",react:"^19.2.8","smol-toml":"^1.7.1",ws:"^8.21.3"},optionalDependencies:{"node-pty":"^1.1.0"},devDependencies:{"@biomejs/biome":"1.9.4","@sma1lboy/rove-daemon":"0.7.23","@tsconfig/bun":"1.0.11","@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","rove-bridge":"0.0.37","rove-weixin":"0.0.37",typescript:"5.8.2",vitest:"2.1.9"},trustedDependencies:[]};var q="rove";var k=q;var z="ROVE_BUN",_="ROVE_NO_BUN_BOOTSTRAP",F="ROVE_SKIP_BUN_CHECK",$=H.engines.bun.match(/\d+\.\d+\.\d+/)?.[0]??"0.0.0",L=(s)=>{try{return V(s,e.X_OK),!0}catch{return!1}},B=(s)=>s==="win32"?"bun.exe":"bun",f=(s)=>{let t=Q(s,["--version"],{encoding:"utf8",timeout:5000});if(t.error||t.status!==0)return null;return t.stdout?.split(`
3
3
  `)[0]?.trim()??""};function J(s){return s.trim().match(/^v?(\d+\.\d+\.\d+)/)?.[1]??null}function X(s,t=$){let c=J(s),W=J(t);if(!c||!W)return!0;let b=c.split(".").map(Number),g=W.split(".").map(Number);for(let p=0;p<3;p++){let r=b[p]??0,i=g[p]??0;if(r!==i)return r>i}return!0}function Y(s=process.env){return s[F]==="1"}function A(s={}){let t=s.env??process.env,c=s.platform??process.platform,W=s.home??t.HOME??t.USERPROFILE??R(),b=B(c),g=[],p=t[z]?.trim();if(p)g.push(p);for(let G of(t.PATH??t.Path??"").split(I))if(G)g.push(y(G,b));let r=t.BUN_INSTALL?.trim();if(r)g.push(y(r,"bin",b));if(W)g.push(y(W,".bun","bin",b));let i=s.launcherDir;if(i)g.push(y(i,"..","..","node_modules","bun","bin",b)),g.push(y(i,"..","..","..","bun","bin",b));return g}function N(s={}){let t=s.isExecutable??L;return A(s).find((c)=>t(c))??null}function Z(s={}){let t=s.isExecutable??L,c=s.bunVersionOf??f;if(Y(s.env??process.env))return{bun:N(s),stale:null,unusable:null};let W=null,b=null;for(let g of A(s)){if(!t(g))continue;let p=c(g);if(p===null){b??=g;continue}if(X(p))return{bun:g,stale:W,unusable:b};W??={path:g,version:J(p)??p}}return{bun:null,stale:W,unusable:b}}function h(s){return U(T(s))}function C(s){return o(T(s)).replace(/\.[cm]?[jt]s$/,"")}function n(s=process.platform){return s==="win32"?["powershell","-NoProfile","-Command","irm bun.sh/install.ps1 | iex"]:["bash","-c","curl -fsSL https://bun.sh/install | bash"]}function D(s=k,t=process.platform){let c=t==="win32"?'powershell -c "irm bun.sh/install.ps1 | iex"':"curl -fsSL https://bun.sh/install | bash";return[`${s}: Rove runs on the Bun runtime, and no Bun was found on this machine.`,"","Install Bun, then run this command again:",` ${c}`," 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: ${z}=/path/to/bun`,""].join(`
4
4
  `)}function j(s,t,c=k){return[`${c}: this machine's Bun is too old for Rove — found ${t} at ${s}, need ${$} 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: ${z}=/path/to/bun`,`Run on this one anyway (unsupported, terminals will be blank): ${F}=1`,""].join(`
5
5
  `)}function v(s,t=k){return[`${t}: the Bun at ${s} could not be run — \`${s} --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: ${z}=/path/to/bun`,""].join(`
@@ -12,12 +12,12 @@ _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 ports viewers review-comments worktree-files worktree-diff worktree-diff-file repo-match repo-list publish pr-attach deliveries should-run add spawn send dispatch interrupt note note-list note-delete pane-open pane-close pane-graphics tab-close tab-new tab-split tab-revive panel-show notify prompt engine-report row-token set-active report attention-dismiss gate-raise gate-answer gate-withdraw gates feedback issue-list issue-create issue-update issue-delete routine-list routine-create routine-update routine-delete routine-run-now routine-respond routine-runs workitem-list workitem-start update land sync delete archive unarchive ensure-worktree remove-worktree worktree-usage discover-adoptable adopt github-status github-login github-logout github-sync github-apply" -- "${cur}") ) ;;
15
+ api) COMPREPLY=( $(compgen -W "schema engine-list list get-task pty-list collect context digest agent-turns inspect read-output queue-list search watch ports viewers review-comments worktree-files worktree-diff worktree-diff-file repo-match repo-list publish pr-attach deliveries should-run add send dispatch interrupt queue-edit queue-cancel note note-list note-delete pane-open pane-close pane-graphics tab-close tab-new tab-split tab-revive panel-show notify prompt engine-report row-token set-active report attention-dismiss gate-raise gate-answer gate-withdraw gates feedback issue-list issue-create issue-update issue-delete routine-list routine-create routine-update routine-delete routine-run-now routine-respond routine-runs workitem-list workitem-start update land sync delete archive unarchive ensure-worktree remove-worktree checkpoint-list checkpoint rewind export-branch worktree-usage discover-adoptable adopt github-status github-login github-logout github-sync github-apply" -- "${cur}") ) ;;
16
16
  daemon) COMPREPLY=( $(compgen -W "status start stop restart relay" -- "${cur}") ) ;;
17
17
  machine) COMPREPLY=( $(compgen -W "add doctor 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}") ) ;;
19
19
  repo) COMPREPLY=( $(compgen -W "show set unset" -- "${cur}") ) ;;
20
- skill) COMPREPLY=( $(compgen -W "install status command print" -- "${cur}") ) ;;
20
+ skill) COMPREPLY=( $(compgen -W "install status print" -- "${cur}") ) ;;
21
21
  theme) COMPREPLY=( $(compgen -W "list add remove" -- "${cur}") ) ;;
22
22
  weixin) COMPREPLY=( $(compgen -W "login logout status allow deny send agent" -- "${cur}") ) ;;
23
23
  esac
@@ -19,11 +19,11 @@ complete -c rove -f -n __fish_use_subcommand -a skill
19
19
  complete -c rove -f -n __fish_use_subcommand -a plugin
20
20
  complete -c rove -f -n __fish_use_subcommand -a feedback
21
21
  complete -c rove -f -n __fish_use_subcommand -a update
22
- 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 ports viewers review-comments worktree-files worktree-diff worktree-diff-file repo-match repo-list publish pr-attach deliveries should-run add spawn send dispatch interrupt note note-list note-delete pane-open pane-close pane-graphics tab-close tab-new tab-split tab-revive panel-show notify prompt engine-report row-token set-active report attention-dismiss gate-raise gate-answer gate-withdraw gates feedback issue-list issue-create issue-update issue-delete routine-list routine-create routine-update routine-delete routine-run-now routine-respond routine-runs workitem-list workitem-start update land sync delete archive unarchive ensure-worktree remove-worktree worktree-usage discover-adoptable adopt github-status github-login github-logout github-sync github-apply"
22
+ 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 queue-list search watch ports viewers review-comments worktree-files worktree-diff worktree-diff-file repo-match repo-list publish pr-attach deliveries should-run add send dispatch interrupt queue-edit queue-cancel note note-list note-delete pane-open pane-close pane-graphics tab-close tab-new tab-split tab-revive panel-show notify prompt engine-report row-token set-active report attention-dismiss gate-raise gate-answer gate-withdraw gates feedback issue-list issue-create issue-update issue-delete routine-list routine-create routine-update routine-delete routine-run-now routine-respond routine-runs workitem-list workitem-start update land sync delete archive unarchive ensure-worktree remove-worktree checkpoint-list checkpoint rewind export-branch worktree-usage discover-adoptable adopt github-status github-login github-logout github-sync github-apply"
23
23
  complete -c rove -f -n "__fish_seen_subcommand_from daemon" -a "status start stop restart relay"
24
24
  complete -c rove -f -n "__fish_seen_subcommand_from machine" -a "add doctor remove list"
25
25
  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"
26
26
  complete -c rove -f -n "__fish_seen_subcommand_from repo" -a "show set unset"
27
- complete -c rove -f -n "__fish_seen_subcommand_from skill" -a "install status command print"
27
+ complete -c rove -f -n "__fish_seen_subcommand_from skill" -a "install status print"
28
28
  complete -c rove -f -n "__fish_seen_subcommand_from theme" -a "list add remove"
29
29
  complete -c rove -f -n "__fish_seen_subcommand_from weixin" -a "login logout status allow deny send agent"
@@ -13,12 +13,12 @@ _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" "ports" "viewers" "review-comments" "worktree-files" "worktree-diff" "worktree-diff-file" "repo-match" "repo-list" "publish" "pr-attach" "deliveries" "should-run" "add" "spawn" "send" "dispatch" "interrupt" "note" "note-list" "note-delete" "pane-open" "pane-close" "pane-graphics" "tab-close" "tab-new" "tab-split" "tab-revive" "panel-show" "notify" "prompt" "engine-report" "row-token" "set-active" "report" "attention-dismiss" "gate-raise" "gate-answer" "gate-withdraw" "gates" "feedback" "issue-list" "issue-create" "issue-update" "issue-delete" "routine-list" "routine-create" "routine-update" "routine-delete" "routine-run-now" "routine-respond" "routine-runs" "workitem-list" "workitem-start" "update" "land" "sync" "delete" "archive" "unarchive" "ensure-worktree" "remove-worktree" "worktree-usage" "discover-adoptable" "adopt" "github-status" "github-login" "github-logout" "github-sync" "github-apply") ;;
16
+ api) verbs=("schema" "engine-list" "list" "get-task" "pty-list" "collect" "context" "digest" "agent-turns" "inspect" "read-output" "queue-list" "search" "watch" "ports" "viewers" "review-comments" "worktree-files" "worktree-diff" "worktree-diff-file" "repo-match" "repo-list" "publish" "pr-attach" "deliveries" "should-run" "add" "send" "dispatch" "interrupt" "queue-edit" "queue-cancel" "note" "note-list" "note-delete" "pane-open" "pane-close" "pane-graphics" "tab-close" "tab-new" "tab-split" "tab-revive" "panel-show" "notify" "prompt" "engine-report" "row-token" "set-active" "report" "attention-dismiss" "gate-raise" "gate-answer" "gate-withdraw" "gates" "feedback" "issue-list" "issue-create" "issue-update" "issue-delete" "routine-list" "routine-create" "routine-update" "routine-delete" "routine-run-now" "routine-respond" "routine-runs" "workitem-list" "workitem-start" "update" "land" "sync" "delete" "archive" "unarchive" "ensure-worktree" "remove-worktree" "checkpoint-list" "checkpoint" "rewind" "export-branch" "worktree-usage" "discover-adoptable" "adopt" "github-status" "github-login" "github-logout" "github-sync" "github-apply") ;;
17
17
  daemon) verbs=("status" "start" "stop" "restart" "relay") ;;
18
18
  machine) verbs=("add" "doctor" "remove" "list") ;;
19
19
  plugin) verbs=("install" "link" "list" "search" "outdated" "update" "enable" "disable" "unlink" "uninstall" "config-dir" "log" "action" "pane") ;;
20
20
  repo) verbs=("show" "set" "unset") ;;
21
- skill) verbs=("install" "status" "command" "print") ;;
21
+ skill) verbs=("install" "status" "print") ;;
22
22
  theme) verbs=("list" "add" "remove") ;;
23
23
  weixin) verbs=("login" "logout" "status" "allow" "deny" "send" "agent") ;;
24
24
  esac