tmux-ide 2.6.0 → 2.7.0

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 (271) hide show
  1. package/README.md +14 -9
  2. package/bin/cli.js +1024 -519
  3. package/bin/cli.ts +63 -6
  4. package/bunfig.toml +4 -0
  5. package/package.json +18 -7
  6. package/packages/contracts/package.json +22 -0
  7. package/packages/contracts/src/__tests__/ide-config.test.ts +46 -0
  8. package/packages/contracts/src/__tests__/terminals.test.ts +87 -0
  9. package/packages/contracts/src/actions-contract.ts +310 -0
  10. package/packages/contracts/src/actions-errors.ts +41 -0
  11. package/packages/contracts/src/domain.ts +36 -0
  12. package/packages/contracts/src/ide-config.ts +170 -0
  13. package/packages/contracts/src/index.ts +24 -0
  14. package/packages/contracts/src/lib-internal/auth.ts +13 -0
  15. package/packages/contracts/src/lib-internal/hq.ts +38 -0
  16. package/packages/contracts/src/terminals.ts +116 -0
  17. package/packages/contracts/src/tmux.ts +60 -0
  18. package/packages/contracts/src/workspace.ts +67 -0
  19. package/packages/daemon/dist/agent-explain.d.ts +8 -1
  20. package/packages/daemon/dist/agent-explain.js +19 -3
  21. package/packages/daemon/dist/lib/tui-binary.d.ts +57 -0
  22. package/packages/daemon/dist/lib/tui-binary.js +130 -0
  23. package/packages/daemon/dist/widgets/explorer/breadcrumbs.d.ts +1 -1
  24. package/packages/daemon/dist/widgets/explorer/footer.d.ts +1 -1
  25. package/packages/daemon/dist/widgets/explorer/tree.d.ts +1 -1
  26. package/packages/daemon/dist/widgets/lib/help-overlay.d.ts +1 -1
  27. package/packages/daemon/dist/widgets/setup/agent-naming.d.ts +1 -1
  28. package/packages/daemon/dist/widgets/setup/config-tree.d.ts +1 -1
  29. package/packages/daemon/dist/widgets/setup/detect-panel.d.ts +1 -1
  30. package/packages/daemon/dist/widgets/setup/field-editor.d.ts +1 -1
  31. package/packages/daemon/dist/widgets/setup/footer.d.ts +1 -1
  32. package/packages/daemon/dist/widgets/setup/layout-picker.d.ts +1 -1
  33. package/packages/daemon/src/agent-explain.ts +298 -0
  34. package/packages/daemon/src/attach.ts +20 -0
  35. package/packages/daemon/src/bin.ts +4 -0
  36. package/packages/daemon/src/canonical.ts +7 -0
  37. package/packages/daemon/src/cli.ts +499 -0
  38. package/packages/daemon/src/command-center/actions/contract.ts +2 -0
  39. package/packages/daemon/src/command-center/actions/dispatcher.ts +137 -0
  40. package/packages/daemon/src/command-center/actions/errors.ts +105 -0
  41. package/packages/daemon/src/command-center/actions/handlers/_project-context.ts +30 -0
  42. package/packages/daemon/src/command-center/actions/handlers/_resolve-project.ts +78 -0
  43. package/packages/daemon/src/command-center/actions/handlers/app-set-remote-access.ts +118 -0
  44. package/packages/daemon/src/command-center/actions/handlers/config-actions.ts +113 -0
  45. package/packages/daemon/src/command-center/actions/handlers/daemon-shutdown.ts +38 -0
  46. package/packages/daemon/src/command-center/actions/handlers/project-activate.ts +30 -0
  47. package/packages/daemon/src/command-center/actions/handlers/project-launch.ts +70 -0
  48. package/packages/daemon/src/command-center/actions/handlers/project-open-terminal.ts +87 -0
  49. package/packages/daemon/src/command-center/actions/handlers/project-restart.ts +38 -0
  50. package/packages/daemon/src/command-center/actions/handlers/project-stop.ts +62 -0
  51. package/packages/daemon/src/command-center/actions/handlers/terminal-respawn.ts +119 -0
  52. package/packages/daemon/src/command-center/actions/handlers/terminal-stop.ts +35 -0
  53. package/packages/daemon/src/command-center/actions/registry.ts +149 -0
  54. package/packages/daemon/src/command-center/discovery.ts +96 -0
  55. package/packages/daemon/src/command-center/index.ts +31 -0
  56. package/packages/daemon/src/command-center/schemas.ts +85 -0
  57. package/packages/daemon/src/command-center/server.ts +1260 -0
  58. package/packages/daemon/src/command-center/ws-events.ts +316 -0
  59. package/packages/daemon/src/config.ts +549 -0
  60. package/packages/daemon/src/detect.ts +248 -0
  61. package/packages/daemon/src/doctor.ts +242 -0
  62. package/packages/daemon/src/embed.ts +5 -0
  63. package/packages/daemon/src/index.ts +12 -0
  64. package/packages/daemon/src/init.ts +211 -0
  65. package/packages/daemon/src/inspect.ts +178 -0
  66. package/packages/daemon/src/js-yaml.d.ts +10 -0
  67. package/packages/daemon/src/launch.ts +349 -0
  68. package/packages/daemon/src/lib/active-projects.ts +49 -0
  69. package/packages/daemon/src/lib/agent-discovery.ts +121 -0
  70. package/packages/daemon/src/lib/app-config.ts +427 -0
  71. package/packages/daemon/src/lib/app-settings.ts +53 -0
  72. package/packages/daemon/src/lib/auth/auth-service.ts +227 -0
  73. package/packages/daemon/src/lib/auth/middleware.ts +56 -0
  74. package/packages/daemon/src/lib/auth/types.ts +2 -0
  75. package/packages/daemon/src/lib/auth-token.ts +5 -0
  76. package/packages/daemon/src/lib/authorship.ts +280 -0
  77. package/packages/daemon/src/lib/canonical-daemon.ts +122 -0
  78. package/packages/daemon/src/lib/cli-action-bridge.ts +216 -0
  79. package/packages/daemon/src/lib/daemon-embed.ts +782 -0
  80. package/packages/daemon/src/lib/daemon-watchdog.ts +111 -0
  81. package/packages/daemon/src/lib/daemon.ts +79 -0
  82. package/packages/daemon/src/lib/dot-path.ts +17 -0
  83. package/packages/daemon/src/lib/errors.ts +67 -0
  84. package/packages/daemon/src/lib/filesystem-browser.ts +292 -0
  85. package/packages/daemon/src/lib/launch-plan.ts +90 -0
  86. package/packages/daemon/src/lib/log.ts +134 -0
  87. package/packages/daemon/src/lib/output.ts +76 -0
  88. package/packages/daemon/src/lib/project-init-runner.ts +150 -0
  89. package/packages/daemon/src/lib/project-inspect.ts +80 -0
  90. package/packages/daemon/src/lib/project-onboard.ts +149 -0
  91. package/packages/daemon/src/lib/project-probe.ts +92 -0
  92. package/packages/daemon/src/lib/project-registry.ts +296 -0
  93. package/packages/daemon/src/lib/session-monitor.ts +122 -0
  94. package/packages/daemon/src/lib/session-options.ts +100 -0
  95. package/packages/daemon/src/lib/shell.ts +8 -0
  96. package/packages/daemon/src/lib/sizes.ts +36 -0
  97. package/packages/daemon/src/lib/skill-sync.ts +155 -0
  98. package/packages/daemon/src/lib/slugify.ts +10 -0
  99. package/packages/daemon/src/lib/terminals-store.ts +125 -0
  100. package/packages/daemon/src/lib/tui-binary.ts +165 -0
  101. package/packages/daemon/src/lib/update-check.ts +298 -0
  102. package/packages/daemon/src/lib/update.ts +158 -0
  103. package/packages/daemon/src/lib/workspace-registry.ts +229 -0
  104. package/packages/daemon/src/lib/worktree.ts +289 -0
  105. package/packages/daemon/src/lib/yaml-io.ts +27 -0
  106. package/packages/daemon/src/ls.ts +40 -0
  107. package/packages/daemon/src/restart.ts +24 -0
  108. package/packages/daemon/src/restore.ts +514 -0
  109. package/packages/daemon/src/schemas/domain.ts +2 -0
  110. package/packages/daemon/src/schemas/filesystem.ts +34 -0
  111. package/packages/daemon/src/schemas/ide-config.ts +2 -0
  112. package/packages/daemon/src/schemas/index.ts +59 -0
  113. package/packages/daemon/src/schemas/inspect.ts +67 -0
  114. package/packages/daemon/src/schemas/registry.ts +55 -0
  115. package/packages/daemon/src/schemas/ws-events.ts +135 -0
  116. package/packages/daemon/src/send.ts +171 -0
  117. package/packages/daemon/src/server/README.md +15 -0
  118. package/packages/daemon/src/server/index.ts +74 -0
  119. package/packages/daemon/src/server/pty-bridge.ts +532 -0
  120. package/packages/daemon/src/server/standalone.ts +18 -0
  121. package/packages/daemon/src/server/ws-route.ts +483 -0
  122. package/packages/daemon/src/status.ts +59 -0
  123. package/packages/daemon/src/stop.ts +28 -0
  124. package/packages/daemon/src/terminal/NodePtyAdapter.ts +271 -0
  125. package/packages/daemon/src/terminal/PtyAdapter.ts +140 -0
  126. package/packages/daemon/src/terminal/README.md +92 -0
  127. package/packages/daemon/src/tui/chrome/cheatsheet.ts +260 -0
  128. package/packages/daemon/src/tui/chrome/chip.ts +30 -0
  129. package/packages/daemon/src/tui/chrome/events.ts +119 -0
  130. package/packages/daemon/src/tui/chrome/kitty-keys.ts +55 -0
  131. package/packages/daemon/src/tui/chrome/menu.ts +289 -0
  132. package/packages/daemon/src/tui/chrome/notify.ts +382 -0
  133. package/packages/daemon/src/tui/chrome/panels.ts +111 -0
  134. package/packages/daemon/src/tui/chrome/sidebar.ts +222 -0
  135. package/packages/daemon/src/tui/chrome/snapshot.ts +425 -0
  136. package/packages/daemon/src/tui/chrome/statusline.ts +595 -0
  137. package/packages/daemon/src/tui/chrome/updater.ts +510 -0
  138. package/packages/daemon/src/tui/chrome/welcome.ts +124 -0
  139. package/packages/daemon/src/tui/compiled.ts +121 -0
  140. package/packages/daemon/src/tui/detect/classify.ts +208 -0
  141. package/packages/daemon/src/tui/detect/manifest-loader.ts +193 -0
  142. package/packages/daemon/src/tui/detect/manifest.ts +199 -0
  143. package/packages/daemon/src/tui/detect/manifests.ts +354 -0
  144. package/packages/daemon/src/tui/detect/process-tree.ts +217 -0
  145. package/packages/daemon/src/tui/detect/snapshot.ts +70 -0
  146. package/packages/daemon/src/tui/integrations/claude.ts +176 -0
  147. package/packages/daemon/src/tui/integrations/offer.ts +145 -0
  148. package/packages/daemon/src/tui/main.ts +82 -0
  149. package/packages/daemon/src/tui/mirror/ack-writer.ts +77 -0
  150. package/packages/daemon/src/tui/mirror/agent-chip.ts +97 -0
  151. package/packages/daemon/src/tui/mirror/agent-rows.ts +133 -0
  152. package/packages/daemon/src/tui/mirror/app-state.ts +179 -0
  153. package/packages/daemon/src/tui/mirror/app.tsx +5265 -0
  154. package/packages/daemon/src/tui/mirror/blit.ts +186 -0
  155. package/packages/daemon/src/tui/mirror/control-client.ts +214 -0
  156. package/packages/daemon/src/tui/mirror/control.ts +97 -0
  157. package/packages/daemon/src/tui/mirror/dialog-model.ts +298 -0
  158. package/packages/daemon/src/tui/mirror/dialog-stack.ts +354 -0
  159. package/packages/daemon/src/tui/mirror/diff-model.ts +112 -0
  160. package/packages/daemon/src/tui/mirror/editor-buffer.ts +117 -0
  161. package/packages/daemon/src/tui/mirror/file-tree.ts +97 -0
  162. package/packages/daemon/src/tui/mirror/focus-border.ts +57 -0
  163. package/packages/daemon/src/tui/mirror/folder-picker.ts +124 -0
  164. package/packages/daemon/src/tui/mirror/home-model.ts +174 -0
  165. package/packages/daemon/src/tui/mirror/input-coalescer.ts +105 -0
  166. package/packages/daemon/src/tui/mirror/menu-model.ts +187 -0
  167. package/packages/daemon/src/tui/mirror/palette.ts +274 -0
  168. package/packages/daemon/src/tui/mirror/pane-mirror.ts +561 -0
  169. package/packages/daemon/src/tui/mirror/pane-surface.tsx +415 -0
  170. package/packages/daemon/src/tui/mirror/perf-tap.ts +160 -0
  171. package/packages/daemon/src/tui/mirror/resize-model.ts +85 -0
  172. package/packages/daemon/src/tui/mirror/scrollbar-model.ts +88 -0
  173. package/packages/daemon/src/tui/mirror/search-model.ts +70 -0
  174. package/packages/daemon/src/tui/mirror/selection.ts +262 -0
  175. package/packages/daemon/src/tui/mirror/session-mirror.ts +443 -0
  176. package/packages/daemon/src/tui/mirror/settings-model.ts +345 -0
  177. package/packages/daemon/src/tui/mirror/size-truth.ts +77 -0
  178. package/packages/daemon/src/tui/mirror/spans.ts +46 -0
  179. package/packages/daemon/src/tui/mirror/status-grammar.ts +32 -0
  180. package/packages/daemon/src/tui/team/CONTROL.md +50 -0
  181. package/packages/daemon/src/tui/team/entry.ts +38 -0
  182. package/packages/daemon/src/tui/team/fuzzy.ts +133 -0
  183. package/packages/daemon/src/tui/team/home.ts +170 -0
  184. package/packages/daemon/src/tui/team/index.tsx +1521 -0
  185. package/packages/daemon/src/tui/team/input.ts +34 -0
  186. package/packages/daemon/src/tui/team/keymap.ts +127 -0
  187. package/packages/daemon/src/tui/team/mouse.ts +29 -0
  188. package/packages/daemon/src/tui/team/nav.ts +31 -0
  189. package/packages/daemon/src/tui/team/preview.ts +34 -0
  190. package/packages/daemon/src/tui/team/projects.ts +191 -0
  191. package/packages/daemon/src/tui/team/report.ts +83 -0
  192. package/packages/daemon/src/tui/team/sessions.ts +433 -0
  193. package/packages/daemon/src/tui/team/tree.ts +62 -0
  194. package/packages/daemon/src/types.ts +13 -0
  195. package/packages/daemon/src/ui/index.ts +32 -0
  196. package/packages/daemon/src/ui/terminal/index.ts +9 -0
  197. package/packages/daemon/src/ui/types.ts +91 -0
  198. package/packages/daemon/src/ui/web/base.css +80 -0
  199. package/packages/daemon/src/ui/web/components/Box.tsx +59 -0
  200. package/packages/daemon/src/ui/web/components/Input.tsx +32 -0
  201. package/packages/daemon/src/ui/web/components/ScrollBox.tsx +60 -0
  202. package/packages/daemon/src/ui/web/components/Text.tsx +28 -0
  203. package/packages/daemon/src/ui/web/hooks.ts +106 -0
  204. package/packages/daemon/src/ui/web/index.ts +27 -0
  205. package/packages/daemon/src/ui/web/render.ts +77 -0
  206. package/packages/daemon/src/ui/web/utils/color.ts +27 -0
  207. package/packages/daemon/src/validate.ts +217 -0
  208. package/packages/daemon/src/widgets/changes/README.md +3 -0
  209. package/packages/daemon/src/widgets/changes/index.tsx +691 -0
  210. package/packages/daemon/src/widgets/config/README.md +3 -0
  211. package/packages/daemon/src/widgets/config/index.tsx +481 -0
  212. package/packages/daemon/src/widgets/explorer/README.md +3 -0
  213. package/packages/daemon/src/widgets/explorer/breadcrumbs.tsx +77 -0
  214. package/packages/daemon/src/widgets/explorer/footer.tsx +20 -0
  215. package/packages/daemon/src/widgets/explorer/header.tsx +23 -0
  216. package/packages/daemon/src/widgets/explorer/index.tsx +456 -0
  217. package/packages/daemon/src/widgets/explorer/tree-model.ts +103 -0
  218. package/packages/daemon/src/widgets/explorer/tree.tsx +165 -0
  219. package/packages/daemon/src/widgets/lib/config-model.ts +116 -0
  220. package/packages/daemon/src/widgets/lib/files.ts +88 -0
  221. package/packages/daemon/src/widgets/lib/git.ts +88 -0
  222. package/packages/daemon/src/widgets/lib/grammar.ts +126 -0
  223. package/packages/daemon/src/widgets/lib/help-overlay.tsx +101 -0
  224. package/packages/daemon/src/widgets/lib/pane-comms.ts +209 -0
  225. package/packages/daemon/src/widgets/lib/theme.ts +194 -0
  226. package/packages/daemon/src/widgets/lib/watcher.ts +132 -0
  227. package/packages/daemon/src/widgets/preview/README.md +3 -0
  228. package/packages/daemon/src/widgets/preview/index.tsx +416 -0
  229. package/packages/daemon/src/widgets/resolve.ts +121 -0
  230. package/packages/daemon/src/widgets/setup/README.md +3 -0
  231. package/packages/daemon/src/widgets/setup/agent-naming.tsx +112 -0
  232. package/packages/daemon/src/widgets/setup/config-tree.tsx +246 -0
  233. package/packages/daemon/src/widgets/setup/detect-panel.tsx +72 -0
  234. package/packages/daemon/src/widgets/setup/field-editor.tsx +265 -0
  235. package/packages/daemon/src/widgets/setup/footer.tsx +107 -0
  236. package/packages/daemon/src/widgets/setup/index.tsx +341 -0
  237. package/packages/daemon/src/widgets/setup/layout-picker.tsx +96 -0
  238. package/packages/daemon/src/widgets/setup/orchestrator-panel.tsx +200 -0
  239. package/packages/daemon/src/widgets/setup/review-panel.tsx +140 -0
  240. package/packages/daemon/src/widgets/setup/setup-model.ts +188 -0
  241. package/packages/daemon/src/widgets/sidebar/index.tsx +527 -0
  242. package/packages/tmux-bridge/package.json +22 -0
  243. package/packages/tmux-bridge/src/errors.ts +28 -0
  244. package/packages/tmux-bridge/src/index.ts +31 -0
  245. package/packages/tmux-bridge/src/monitor.ts +77 -0
  246. package/packages/tmux-bridge/src/panes.ts +136 -0
  247. package/packages/tmux-bridge/src/runner.test.ts +501 -0
  248. package/packages/tmux-bridge/src/runner.ts +91 -0
  249. package/packages/tmux-bridge/src/sessions.ts +126 -0
  250. package/packages/tmux-bridge/src/targeting.test.ts +107 -0
  251. package/packages/tmux-bridge/src/targeting.ts +90 -0
  252. package/scripts/build-tui.mjs +11 -4
  253. package/scripts/perf-mirror.mjs +313 -0
  254. package/scripts/postinstall.js +26 -2
  255. package/skill/SKILL.md +22 -0
  256. package/templates/AGENTS.md +14 -7
  257. package/templates/agent-team-monorepo.yml +8 -0
  258. package/templates/agent-team-nextjs.yml +8 -0
  259. package/templates/agent-team.yml +10 -0
  260. package/templates/convex.yml +2 -0
  261. package/templates/default.yml +11 -5
  262. package/templates/go.yml +4 -0
  263. package/templates/missions.yml +6 -0
  264. package/templates/nextjs.yml +4 -0
  265. package/templates/python.yml +4 -0
  266. package/templates/skills/backend.md +5 -12
  267. package/templates/skills/frontend.md +5 -12
  268. package/templates/skills/general-worker.md +5 -12
  269. package/templates/skills/researcher.md +7 -12
  270. package/templates/skills/reviewer.md +7 -16
  271. package/templates/vite.yml +4 -0
@@ -0,0 +1,313 @@
1
+ #!/usr/bin/env bun
2
+ /**
3
+ * perf-mirror — the M21 baseline harness.
4
+ *
5
+ * Drives the real unified app (`tmux-ide app`) against a scripted tmux session
6
+ * on the default socket, exercising the three mirror-pipeline taps that gate
7
+ * behind TMUX_IDE_ZZ_PERF, then prints a p50/p95 table for:
8
+ * - feed-parse ms per stdout chunk (/tmp/zz-feed.log, control-client)
9
+ * - snapshot ms per 8ms paint tick (/tmp/zz-perf.log, app.tsx)
10
+ * - input-echo ms keystroke→echo→paint (/tmp/zz-input.log, perf-tap)
11
+ * across three scenarios: IDLE, FLOOD (scrolling), ALT (alt-screen redraw).
12
+ *
13
+ * Everything it creates is `zz-perf-*` on the default socket and is killed on
14
+ * exit (success OR failure). It NEVER touches any other session. Run it from
15
+ * the repo root: bun scripts/perf-mirror.mjs
16
+ *
17
+ * Env knobs (all optional): PERF_FLOOD_MS, PERF_ALT_MS, PERF_IDLE_MS,
18
+ * PERF_KEYS (input samples), PERF_KEY_GAP_MS, PERF_WARMUP_MS.
19
+ */
20
+ import { execFileSync } from "node:child_process";
21
+ import { readFileSync, writeFileSync, existsSync } from "node:fs";
22
+ import { fileURLToPath } from "node:url";
23
+ import { dirname, resolve } from "node:path";
24
+ import os from "node:os";
25
+ import { summarize } from "../packages/daemon/src/tui/mirror/perf-tap.ts";
26
+
27
+ const REPO = resolve(dirname(fileURLToPath(import.meta.url)), "..");
28
+ const APP = "packages/daemon/src/tui/mirror/app.tsx";
29
+ const TARGET = "zz-perf-target";
30
+ const HOST = "zz-perf-host";
31
+ const FEED_LOG = "/tmp/zz-feed.log";
32
+ const SNAP_LOG = "/tmp/zz-perf.log";
33
+ const INPUT_LOG = "/tmp/zz-input.log";
34
+
35
+ const cfg = {
36
+ floodMs: num(process.env.PERF_FLOOD_MS, 6000),
37
+ altMs: num(process.env.PERF_ALT_MS, 6000),
38
+ idleMs: num(process.env.PERF_IDLE_MS, 4000),
39
+ keys: num(process.env.PERF_KEYS, 50),
40
+ keyGapMs: num(process.env.PERF_KEY_GAP_MS, 90),
41
+ warmupMs: num(process.env.PERF_WARMUP_MS, 5000),
42
+ };
43
+
44
+ function num(v, d) {
45
+ const n = Number(v);
46
+ return Number.isFinite(n) && n > 0 ? n : d;
47
+ }
48
+
49
+ /** tmux on the DEFAULT socket, un-nested (TMUX/TMUX_TMPDIR cleared) — the socket
50
+ * the app's control client attaches to and where the user's real sessions live.
51
+ * We only ever name zz-perf-* targets. */
52
+ function tmux(args, opts = {}) {
53
+ return execFileSync("tmux", args, {
54
+ env: { ...process.env, TMUX: "", TMUX_TMPDIR: "" },
55
+ encoding: "utf8",
56
+ stdio: opts.inherit ? "inherit" : ["ignore", "pipe", "pipe"],
57
+ ...opts,
58
+ });
59
+ }
60
+ function tmuxQuiet(args) {
61
+ try {
62
+ return tmux(args);
63
+ } catch {
64
+ return "";
65
+ }
66
+ }
67
+ function sessionExists(name) {
68
+ try {
69
+ tmux(["has-session", "-t", name]);
70
+ return true;
71
+ } catch {
72
+ return false;
73
+ }
74
+ }
75
+ const sleep = (ms) => new Promise((r) => setTimeout(r, ms));
76
+ const truncate = (p) => writeFileSync(p, "");
77
+ function readCol(path, col) {
78
+ if (!existsSync(path)) return [];
79
+ return readFileSync(path, "utf8")
80
+ .split("\n")
81
+ .filter(Boolean)
82
+ .map((l) => Number(l.trim().split(/\s+/)[col]))
83
+ .filter((n) => Number.isFinite(n));
84
+ }
85
+
86
+ // ── keystroke / flood injection ─────────────────────────────────────────────
87
+
88
+ /** Type into the HOST (the app), which forwards to the focused target pane. */
89
+ const sendHostKey = (key) => tmuxQuiet(["send-keys", "-t", HOST, key]);
90
+ const sendHostChar = (ch) => tmuxQuiet(["send-keys", "-t", HOST, "-l", ch]);
91
+ /** Run a command directly in the TARGET pane (bypasses the app — pure output). */
92
+ function runInTarget(line) {
93
+ tmuxQuiet(["send-keys", "-t", TARGET, "-l", line]);
94
+ tmuxQuiet(["send-keys", "-t", TARGET, "Enter"]);
95
+ }
96
+ /** Interrupt whatever the target pane is running, back to a clean prompt. */
97
+ function calmTarget() {
98
+ tmuxQuiet(["send-keys", "-t", TARGET, "C-c"]);
99
+ tmuxQuiet(["send-keys", "-t", TARGET, "-l", "printf '\\033[?1049l'"]);
100
+ tmuxQuiet(["send-keys", "-t", TARGET, "Enter"]);
101
+ tmuxQuiet(["send-keys", "-t", TARGET, "-l", "clear"]);
102
+ tmuxQuiet(["send-keys", "-t", TARGET, "Enter"]);
103
+ }
104
+
105
+ // ── lifecycle ───────────────────────────────────────────────────────────────
106
+
107
+ function cleanup() {
108
+ for (const s of [HOST, TARGET]) {
109
+ if (sessionExists(s)) tmuxQuiet(["kill-session", "-t", s]);
110
+ }
111
+ }
112
+
113
+ async function setup() {
114
+ cleanup(); // clear any leftovers from a crashed prior run
115
+ truncate(FEED_LOG);
116
+ truncate(SNAP_LOG);
117
+ truncate(INPUT_LOG);
118
+
119
+ // Target: a plain shell on the default socket. The app mirrors this session;
120
+ // its control client (`tmux -C attach`, TMUX="") reaches the default socket.
121
+ tmux(["new-session", "-d", "-s", TARGET, "-x", "200", "-y", "50"]);
122
+ // A generous host so the app has room and never wraps the flood oddly.
123
+ tmux([
124
+ "new-session",
125
+ "-d",
126
+ "-s",
127
+ HOST,
128
+ "-x",
129
+ "220",
130
+ "-y",
131
+ "60",
132
+ // Forward TMUX_IDE_FB_PANES verbatim so the default incremental blit path
133
+ // (M21.4) and the `=0` StyledRun kill switch can be measured on the same
134
+ // harness/taps. Unset → the app's default (blit).
135
+ `cd ${REPO} && TMUX_IDE_ZZ_PERF=1 ${process.env.TMUX_IDE_FB_PANES !== undefined ? `TMUX_IDE_FB_PANES=${process.env.TMUX_IDE_FB_PANES} ` : ""}exec bun ${APP} --target=${TARGET}`,
136
+ ]);
137
+
138
+ process.stdout.write(` warming up (${cfg.warmupMs}ms) — app attaching + seeding…\n`);
139
+ await sleep(cfg.warmupMs);
140
+ sendHostKey("F2"); // force the Terminal surface (pane-forward keyboard path)
141
+ await sleep(400);
142
+ }
143
+
144
+ /** Assert the mirror is actually live: a brief flood must grow the feed log. */
145
+ async function assertLive() {
146
+ truncate(FEED_LOG);
147
+ runInTarget("for i in 1 2 3 4 5; do echo probe-$i; done");
148
+ await sleep(800);
149
+ const n = readCol(FEED_LOG, 1).length;
150
+ if (n === 0) {
151
+ const pane = tmuxQuiet(["capture-pane", "-t", HOST, "-p"]).slice(0, 800);
152
+ throw new Error(
153
+ `mirror never went live — no %output feed after a probe.\n--- host pane ---\n${pane}`,
154
+ );
155
+ }
156
+ calmTarget();
157
+ await sleep(500);
158
+ }
159
+
160
+ // ── scenarios ────────────────────────────────────────────────────────────────
161
+
162
+ /** Idle: quiet pane; capture the low-water feed/snapshot floor. */
163
+ async function scenarioIdle() {
164
+ calmTarget();
165
+ await sleep(600);
166
+ truncate(FEED_LOG);
167
+ truncate(SNAP_LOG);
168
+ await sleep(cfg.idleMs);
169
+ return { feed: readCol(FEED_LOG, 1), snap: readCol(SNAP_LOG, 0) };
170
+ }
171
+
172
+ /** Flood: a steady stream of new lines (scrollback growth + re-snapshot). */
173
+ async function scenarioFlood() {
174
+ calmTarget();
175
+ await sleep(500);
176
+ truncate(FEED_LOG);
177
+ truncate(SNAP_LOG);
178
+ // ~200 lines/sec — a busy build/test log, not a fork bomb.
179
+ runInTarget(
180
+ 'i=0; while true; do echo "flood line $i $(date +%s%N)"; i=$((i+1)); sleep 0.005; done',
181
+ );
182
+ await sleep(cfg.floodMs);
183
+ const out = { feed: readCol(FEED_LOG, 1), snap: readCol(SNAP_LOG, 0) };
184
+ calmTarget();
185
+ await sleep(500);
186
+ return out;
187
+ }
188
+
189
+ /** Alt-screen: an app that repaints in place (cursor addressing, no scrollback). */
190
+ async function scenarioAlt() {
191
+ calmTarget();
192
+ await sleep(500);
193
+ truncate(FEED_LOG);
194
+ truncate(SNAP_LOG);
195
+ runInTarget(
196
+ "printf '\\033[?1049h'; while true; do printf '\\033[H\\033[2J'; date +%s.%N; seq 1 30; sleep 0.05; done",
197
+ );
198
+ await sleep(cfg.altMs);
199
+ const out = { feed: readCol(FEED_LOG, 1), snap: readCol(SNAP_LOG, 0) };
200
+ calmTarget();
201
+ await sleep(500);
202
+ return out;
203
+ }
204
+
205
+ /** Input latency: type single chars into the app at a shell prompt; each echoes. */
206
+ async function scenarioInput() {
207
+ calmTarget();
208
+ await sleep(600);
209
+ truncate(INPUT_LOG);
210
+ const glyphs = "abcdefghijklmnopqrstuvwxyz0123456789";
211
+ for (let k = 0; k < cfg.keys; k++) {
212
+ sendHostChar(glyphs[k % glyphs.length]);
213
+ await sleep(cfg.keyGapMs);
214
+ }
215
+ await sleep(400);
216
+ const out = { echo: readCol(INPUT_LOG, 1), paint: readCol(INPUT_LOG, 2) };
217
+ // Drop the half-typed line by interrupting the TARGET pane directly. NEVER
218
+ // send C-c to the host: the app exits on ctrl-c, which would kill the mirror
219
+ // and silence every later scenario.
220
+ tmuxQuiet(["send-keys", "-t", TARGET, "C-c"]);
221
+ return out;
222
+ }
223
+
224
+ // ── reporting ────────────────────────────────────────────────────────────────
225
+
226
+ function fmt(n) {
227
+ return n.toFixed(2).padStart(8);
228
+ }
229
+ function row(label, s) {
230
+ return ` ${label.padEnd(26)} ${String(s.count).padStart(6)} ${fmt(s.p50)} ${fmt(s.p95)} ${fmt(s.max)} ${fmt(s.mean)}`;
231
+ }
232
+ function table(rows) {
233
+ const head = ` ${"metric".padEnd(26)} ${"n".padStart(6)} ${"p50".padStart(8)} ${"p95".padStart(8)} ${"max".padStart(8)} ${"mean".padStart(8)}`;
234
+ return [head, " " + "-".repeat(head.length - 2), ...rows].join("\n");
235
+ }
236
+
237
+ function machineInfo() {
238
+ const cpu = os.cpus()[0]?.model ?? "unknown";
239
+ let tmuxV = "unknown";
240
+ try {
241
+ tmuxV = tmux(["-V"]).trim();
242
+ } catch {
243
+ /* ignore */
244
+ }
245
+ let opentui = "unknown";
246
+ try {
247
+ const pkg = JSON.parse(readFileSync(resolve(REPO, "packages/daemon/package.json"), "utf8"));
248
+ opentui =
249
+ pkg.dependencies?.["@opentui/core"] ?? pkg.dependencies?.["@opentui/solid"] ?? "unknown";
250
+ } catch {
251
+ /* ignore */
252
+ }
253
+ return {
254
+ date: new Date().toISOString(),
255
+ platform: `${os.platform()} ${os.release()} (${os.arch()})`,
256
+ cpu: `${cpu} × ${os.cpus().length}`,
257
+ mem: `${(os.totalmem() / 1024 ** 3).toFixed(0)} GB`,
258
+ bun: process.versions.bun ?? "n/a",
259
+ node: process.versions.node,
260
+ tmux: tmuxV,
261
+ opentui,
262
+ };
263
+ }
264
+
265
+ async function main() {
266
+ const info = machineInfo();
267
+ process.stdout.write("perf-mirror — M21 baseline harness\n");
268
+ process.stdout.write(
269
+ ` ${info.platform} · ${info.cpu} · bun ${info.bun} · ${info.tmux} · @opentui ${info.opentui}\n\n`,
270
+ );
271
+
272
+ await setup();
273
+ await assertLive();
274
+
275
+ process.stdout.write(" running IDLE…\n");
276
+ const idle = await scenarioIdle();
277
+ process.stdout.write(" running INPUT…\n");
278
+ const input = await scenarioInput();
279
+ process.stdout.write(" running FLOOD…\n");
280
+ const flood = await scenarioFlood();
281
+ process.stdout.write(" running ALT-SCREEN…\n\n");
282
+ const alt = await scenarioAlt();
283
+
284
+ const rows = [
285
+ row("feed-parse ms/chunk [idle]", summarize(idle.feed)),
286
+ row("feed-parse ms/chunk [flood]", summarize(flood.feed)),
287
+ row("feed-parse ms/chunk [alt]", summarize(alt.feed)),
288
+ row("snapshot ms/tick [idle]", summarize(idle.snap)),
289
+ row("snapshot ms/tick [flood]", summarize(flood.snap)),
290
+ row("snapshot ms/tick [alt]", summarize(alt.snap)),
291
+ row("input echo ms (t1-t0)", summarize(input.echo)),
292
+ row("input paint ms (t2-t0)", summarize(input.paint)),
293
+ ];
294
+ process.stdout.write(table(rows) + "\n");
295
+
296
+ return { info, rows };
297
+ }
298
+
299
+ let exitCode = 0;
300
+ try {
301
+ await main();
302
+ } catch (err) {
303
+ exitCode = 1;
304
+ process.stderr.write(`\nperf-mirror FAILED: ${err?.stack ?? err}\n`);
305
+ } finally {
306
+ cleanup();
307
+ // Best-effort confirmation the zz-perf-* sessions are gone.
308
+ const leftover = [HOST, TARGET].filter(sessionExists);
309
+ if (leftover.length)
310
+ process.stderr.write(` WARNING leftover sessions: ${leftover.join(", ")}\n`);
311
+ else process.stdout.write("\n cleanup: zz-perf-* sessions removed.\n");
312
+ }
313
+ process.exit(exitCode);
@@ -1,7 +1,31 @@
1
- import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
2
- import { resolve, dirname } from "node:path";
1
+ import { existsSync, mkdirSync, readFileSync, writeFileSync, symlinkSync } from "node:fs";
2
+ import { resolve, dirname, relative } from "node:path";
3
3
  import { homedir } from "node:os";
4
4
 
5
+ // ---------------------------------------------------------------------------
6
+ // Workspace-package links — MUST run before the Claude gate below.
7
+ //
8
+ // The TUI sources (packages/daemon/src/**, run via bun) import the workspace
9
+ // packages @tmux-ide/tmux-bridge and @tmux-ide/contracts. In a dev checkout
10
+ // pnpm symlinks them into node_modules; an npm install has no such links, so
11
+ // recreate them (their package.json mains point at shipped src/index.ts,
12
+ // which bun runs directly). Best-effort: never fail an install.
13
+ // ---------------------------------------------------------------------------
14
+ try {
15
+ const pkgRoot = dirname(import.meta.dirname);
16
+ const scopeDir = resolve(pkgRoot, "node_modules", "@tmux-ide");
17
+ for (const name of ["tmux-bridge", "contracts"]) {
18
+ const target = resolve(pkgRoot, "packages", name);
19
+ const link = resolve(scopeDir, name);
20
+ if (!existsSync(target) || existsSync(link)) continue;
21
+ mkdirSync(scopeDir, { recursive: true });
22
+ // "junction" keeps Windows working without admin; ignored elsewhere.
23
+ symlinkSync(relative(scopeDir, target), link, "junction");
24
+ }
25
+ } catch {
26
+ // linking is best-effort; the CLI's TUI fallback message covers the gap
27
+ }
28
+
5
29
  const claudeDir = resolve(homedir(), ".claude");
6
30
  if (!shouldInstallClaudeIntegration() || !existsSync(claudeDir)) {
7
31
  process.exit(0);
package/skill/SKILL.md CHANGED
@@ -123,6 +123,28 @@ One interaction grammar everywhere: `j`/`k` move, `enter` opens, `/` filters,
123
123
  `esc` backs out, `?` asks. Bare `tmux-ide` with no `ide.yml` opens the **home
124
124
  cockpit** (the fleet home screen). `tmux-ide cheatsheet` prints the full sheet.
125
125
 
126
+ ## The app — `tmux-ide app` (the terminal IDE)
127
+
128
+ v2.7 adds a full-screen unified app: tmux stays the engine (PTYs, agents,
129
+ persistence); the app is the IDE around it. Launch `tmux-ide app` (bare = home
130
+ screen) or `tmux-ide app <session>`. Needs `bun`, or a downloaded binary:
131
+ `tmux-ide update --tui-binary`.
132
+
133
+ - **Tabs** `F1`–`F4`: Home (fleet, pick a session = set the workspace) ·
134
+ Terminal (the session mirrored live — it keeps streaming while you're on
135
+ other tabs) · Files (tree + built-in editor: `^s` save, `^z` undo, click to
136
+ place the cursor) · Diff (colored working-tree changes, `^e` opens the file
137
+ in the editor). `F5` = command palette (fuzzy everything).
138
+ - **Mouse-native**: hover highlights; right-click = context menus (split/zoom/
139
+ kill panes, layouts, synchronize-panes, kill/rename sessions & windows —
140
+ destructive actions confirm); drag pane borders to resize; drag-select text →
141
+ clipboard via OSC52 (works through ssh); scrollbars; clickable buttons.
142
+ - **tmux parity**: `[⛶]` zoom, window verbs, layout presets, `/` scrollback
143
+ search with `n`/`N`, paste-buffer picker. `^q` quits — the session is
144
+ untouched, like you were never there.
145
+ - State persists across launches (~/.tmux-ide/app-state.json): last tab,
146
+ session, open file.
147
+
126
148
  ## ide.yml (optional)
127
149
 
128
150
  Adopt works on any session. If you'd rather have tmux-ide build the layout, describe
@@ -5,16 +5,23 @@
5
5
  ## Boundaries
6
6
 
7
7
  - Stay within the scope of your assigned task
8
- - Report out-of-scope issues via --discovered-issues
8
+ - Surface out-of-scope issues to the lead instead of silently expanding scope
9
9
  - Do not modify files outside your task scope without coordination
10
10
 
11
11
  ## Conventions
12
12
 
13
- - Run tests before marking tasks done
14
- - Use the project existing code style
15
- - Commit messages should reference the task ID
13
+ - Run tests before reporting your work done
14
+ - Use the project's existing code style
15
+ - Reference the task or branch in commit messages
16
16
 
17
- ## Completion Protocol
17
+ ## Status & Reporting
18
18
 
19
- - tmux-ide task done <ID> --proof "summary" --summary "key learnings"
20
- - Report issues: include --discovered-issues for anything out of scope
19
+ Report your state so the fleet tabs show ground truth. Claude Code does this
20
+ automatically once `tmux-ide integration install claude` is run; any agent can
21
+ self-report the same way:
22
+
23
+ tmux set-option -p @agent_state "working:$(date +%s)" # working|blocked|done|idle
24
+
25
+ Coordinate with the lead or a teammate pane:
26
+
27
+ tmux-ide send <session-or-pane> "what changed, how you verified it, follow-ups"
@@ -1,8 +1,16 @@
1
1
  name: my-monorepo
2
2
 
3
+ # Ground-truth agent status (working/blocked/done glyphs on the fleet tabs)
4
+ # comes from Claude Code's lifecycle hooks. Wire them once with:
5
+ # tmux-ide integration install claude
6
+
3
7
  team:
4
8
  name: my-monorepo
5
9
 
10
+ sidebar: true # fleet nav column — jump between agents (toggle: prefix b)
11
+
12
+ before: pnpm install
13
+
6
14
  rows:
7
15
  - size: 70%
8
16
  panes:
@@ -1,8 +1,14 @@
1
1
  name: my-app
2
2
 
3
+ # Ground-truth agent status (working/blocked/done glyphs on the fleet tabs)
4
+ # comes from Claude Code's lifecycle hooks. Wire them once with:
5
+ # tmux-ide integration install claude
6
+
3
7
  team:
4
8
  name: my-app
5
9
 
10
+ sidebar: true # fleet nav column — jump between agents (toggle: prefix b)
11
+
6
12
  before: pnpm install
7
13
 
8
14
  rows:
@@ -24,4 +30,6 @@ rows:
24
30
  - panes:
25
31
  - title: Next.js
26
32
  command: pnpm dev
33
+ - title: Changes
34
+ type: changes # live git changes widget
27
35
  - title: Shell
@@ -1,8 +1,16 @@
1
1
  name: my-project
2
2
 
3
+ # Ground-truth agent status (working/blocked/done glyphs on the fleet tabs)
4
+ # comes from Claude Code's lifecycle hooks. Wire them once with:
5
+ # tmux-ide integration install claude
6
+
3
7
  team:
4
8
  name: my-project
5
9
 
10
+ sidebar: true # fleet nav column — jump between agents (toggle: prefix b)
11
+
12
+ # before: npm install
13
+
6
14
  rows:
7
15
  - size: 70%
8
16
  panes:
@@ -18,6 +26,8 @@ rows:
18
26
  role: teammate
19
27
 
20
28
  - panes:
29
+ - title: Changes
30
+ type: changes # live git changes widget
21
31
  - title: Dev Server
22
32
  # command: npm run dev
23
33
  - title: Shell
@@ -1,5 +1,7 @@
1
1
  name: my-app
2
2
 
3
+ before: pnpm install
4
+
3
5
  rows:
4
6
  - size: 70%
5
7
  panes:
@@ -1,6 +1,8 @@
1
1
  name: my-project
2
2
 
3
- # before: npm install # optional pre-launch hook
3
+ # before: npm install # optional pre-launch hook (runs once, before panes start)
4
+
5
+ # sidebar: true # inject the fleet nav column (prefix b toggles it live)
4
6
 
5
7
  rows:
6
8
  - size: 70%
@@ -11,10 +13,14 @@ rows:
11
13
  command: claude
12
14
 
13
15
  - panes:
16
+ # Widget panes render native UI instead of a command:
17
+ # type: explorer | changes | preview | config | sidebar
18
+ - title: Changes
19
+ type: changes # live git changes — no command, tmux-ide draws it
14
20
  - title: Dev Server
15
21
  # command: npm run dev
16
- # dir: apps/web # per-pane working directory
17
- # env: # per-pane environment variables
18
- # PORT: 3000
22
+ # dir: apps/web # per-pane working directory
23
+ # env: # per-pane environment variables
24
+ # PORT: "3000"
19
25
  - title: Shell
20
- # focus: true # give this pane initial focus
26
+ focus: true # give this pane initial focus
package/templates/go.yml CHANGED
@@ -1,5 +1,7 @@
1
1
  name: my-app
2
2
 
3
+ before: go mod download
4
+
3
5
  rows:
4
6
  - size: 70%
5
7
  panes:
@@ -11,5 +13,7 @@ rows:
11
13
  - panes:
12
14
  - title: Go
13
15
  command: go run .
16
+ - title: Changes
17
+ type: changes # live git changes widget
14
18
  - title: Shell
15
19
  focus: true
@@ -1,8 +1,14 @@
1
1
  name: project-name
2
2
 
3
+ # Ground-truth agent status (working/blocked/done glyphs on the fleet tabs)
4
+ # comes from Claude Code's lifecycle hooks. Wire them once with:
5
+ # tmux-ide integration install claude
6
+
3
7
  team:
4
8
  name: missions
5
9
 
10
+ sidebar: true # fleet nav column — jump between agents (toggle: prefix b)
11
+
6
12
  rows:
7
13
  - size: 70%
8
14
  panes:
@@ -1,5 +1,7 @@
1
1
  name: my-app
2
2
 
3
+ before: pnpm install
4
+
3
5
  rows:
4
6
  - size: 70%
5
7
  panes:
@@ -13,5 +15,7 @@ rows:
13
15
  - panes:
14
16
  - title: Next.js
15
17
  command: pnpm dev
18
+ - title: Changes
19
+ type: changes # live git changes widget
16
20
  - title: Shell
17
21
  focus: true
@@ -1,5 +1,7 @@
1
1
  name: my-app
2
2
 
3
+ # before: pip install -r requirements.txt # or: uv sync / poetry install
4
+
3
5
  rows:
4
6
  - size: 70%
5
7
  panes:
@@ -11,5 +13,7 @@ rows:
11
13
  - panes:
12
14
  - title: Server
13
15
  # command: uvicorn main:app --reload
16
+ - title: Changes
17
+ type: changes # live git changes widget
14
18
  - title: Shell
15
19
  focus: true
@@ -25,19 +25,12 @@ You are a backend development specialist.
25
25
 
26
26
  Your dispatch prompt includes relevant excerpts from the knowledge library (.tmux-ide/library/) and AGENTS.md. Use these for architectural decisions.
27
27
 
28
- ## After Completion
28
+ ## Reporting
29
29
 
30
- When you finish, the orchestrator will:
30
+ Self-report your state — this drives the fleet status glyphs (see AGENTS.md):
31
31
 
32
- - Notify the lead with your proof and summary
33
- - Run any configured after-run hooks (e.g., linting)
34
- - Auto-dispatch the next available task
35
- - Append your summary to the learnings library
32
+ tmux set-option -p @agent_state "done:$(date +%s)" # working|blocked|done|idle
36
33
 
37
- ## Completion Protocol
34
+ Then report the result to the lead, and flag anything out of scope:
38
35
 
39
- When done, run:
40
- tmux-ide task done <TASK_ID> --proof "what changed and how you verified it" --summary "backend outcome"
41
-
42
- If you find out-of-scope issues, report them:
43
- tmux-ide task update <TASK_ID> --discovered-issues "description of issue"
36
+ tmux-ide send <lead-pane> "what changed, how you verified it, operational concerns"
@@ -25,19 +25,12 @@ You are a frontend development specialist.
25
25
 
26
26
  Your dispatch prompt includes relevant excerpts from the knowledge library (.tmux-ide/library/) and AGENTS.md. Use these for architectural decisions.
27
27
 
28
- ## After Completion
28
+ ## Reporting
29
29
 
30
- When you finish, the orchestrator will:
30
+ Self-report your state — this drives the fleet status glyphs (see AGENTS.md):
31
31
 
32
- - Notify the lead with your proof and summary
33
- - Run any configured after-run hooks (e.g., linting)
34
- - Auto-dispatch the next available task
35
- - Append your summary to the learnings library
32
+ tmux set-option -p @agent_state "done:$(date +%s)" # working|blocked|done|idle
36
33
 
37
- ## Completion Protocol
34
+ Then report the result to the lead, and flag anything out of scope:
38
35
 
39
- When done, run:
40
- tmux-ide task done <TASK_ID> --proof "what changed and how you verified it" --summary "frontend outcome"
41
-
42
- If you find out-of-scope issues, report them:
43
- tmux-ide task update <TASK_ID> --discovered-issues "description of issue"
36
+ tmux-ide send <lead-pane> "what changed, what you verified, any follow-up risks"
@@ -25,19 +25,12 @@ You are a general-purpose development agent.
25
25
 
26
26
  You are a general-purpose agent. Your dispatch prompt includes mission, goal, and task context along with relevant library excerpts. Follow the task description closely.
27
27
 
28
- ## After Completion
28
+ ## Reporting
29
29
 
30
- When you finish, the orchestrator will:
30
+ Self-report your state — this drives the fleet status glyphs (see AGENTS.md):
31
31
 
32
- - Notify the lead with your proof and summary
33
- - Run any configured after-run hooks (e.g., linting)
34
- - Auto-dispatch the next available task
35
- - Append your summary to the learnings library
32
+ tmux set-option -p @agent_state "done:$(date +%s)" # working|blocked|done|idle
36
33
 
37
- ## Completion Protocol
34
+ Then report the result to the lead, and flag anything out of scope:
38
35
 
39
- When done, run:
40
- tmux-ide task done <TASK_ID> --proof "what you accomplished" --summary "key learnings for future tasks"
41
-
42
- If you discover out-of-scope issues, note them:
43
- tmux-ide task update <TASK_ID> --discovered-issues "description of issue"
36
+ tmux-ide send <lead-pane> "what you accomplished, how you verified it, follow-ups"