tmux-ide 2.7.0 → 2.8.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 (101) hide show
  1. package/README.md +22 -5
  2. package/bin/cli.js +3532 -1090
  3. package/bin/cli.ts +368 -71
  4. package/package.json +2 -1
  5. package/packages/contracts/src/__tests__/control.test.ts +154 -0
  6. package/packages/contracts/src/control.ts +217 -0
  7. package/packages/contracts/src/index.ts +1 -0
  8. package/packages/daemon/dist/control/client.d.ts +23 -0
  9. package/packages/daemon/dist/control/client.js +105 -0
  10. package/packages/daemon/dist/control/dispatch.d.ts +34 -0
  11. package/packages/daemon/dist/control/dispatch.js +83 -0
  12. package/packages/daemon/dist/control/fanout.d.ts +19 -0
  13. package/packages/daemon/dist/control/fanout.js +37 -0
  14. package/packages/daemon/dist/control/frames.d.ts +23 -0
  15. package/packages/daemon/dist/control/frames.js +37 -0
  16. package/packages/daemon/dist/control/lifecycle.d.ts +45 -0
  17. package/packages/daemon/dist/control/lifecycle.js +114 -0
  18. package/packages/daemon/dist/control/server.d.ts +16 -0
  19. package/packages/daemon/dist/control/server.js +214 -0
  20. package/packages/daemon/dist/control/verbs.d.ts +11 -0
  21. package/packages/daemon/dist/control/verbs.js +91 -0
  22. package/packages/daemon/dist/doctor.d.ts +18 -0
  23. package/packages/daemon/dist/doctor.js +105 -15
  24. package/packages/daemon/dist/lib/agent-discovery.d.ts +27 -2
  25. package/packages/daemon/dist/lib/agent-discovery.js +29 -14
  26. package/packages/daemon/dist/lib/app-config.d.ts +106 -0
  27. package/packages/daemon/dist/lib/app-config.js +104 -5
  28. package/packages/daemon/dist/lib/manifest-pack.d.ts +79 -0
  29. package/packages/daemon/dist/lib/manifest-pack.js +232 -0
  30. package/packages/daemon/dist/lib/state-home.d.ts +2 -0
  31. package/packages/daemon/dist/lib/state-home.js +12 -0
  32. package/packages/daemon/dist/lib/update-check.js +5 -0
  33. package/packages/daemon/dist/native/TmuxIdeNotifier.app/Contents/Info.plist +34 -0
  34. package/packages/daemon/dist/native/TmuxIdeNotifier.app/Contents/MacOS/tmux-ide-notifier +0 -0
  35. package/packages/daemon/dist/native/TmuxIdeNotifier.app/Contents/PkgInfo +1 -0
  36. package/packages/daemon/dist/native/TmuxIdeNotifier.app/Contents/Resources/AppIcon.icns +0 -0
  37. package/packages/daemon/dist/native/TmuxIdeNotifier.app/Contents/Resources/Assets.car +0 -0
  38. package/packages/daemon/dist/native/TmuxIdeNotifier.app/Contents/_CodeSignature/CodeResources +139 -0
  39. package/packages/daemon/dist/restore.d.ts +35 -8
  40. package/packages/daemon/dist/restore.js +52 -15
  41. package/packages/daemon/dist/send.d.ts +33 -1
  42. package/packages/daemon/dist/send.js +32 -19
  43. package/packages/daemon/src/control/client.ts +128 -0
  44. package/packages/daemon/src/control/dispatch.ts +107 -0
  45. package/packages/daemon/src/control/fanout.ts +44 -0
  46. package/packages/daemon/src/control/frames.ts +40 -0
  47. package/packages/daemon/src/control/lifecycle.ts +151 -0
  48. package/packages/daemon/src/control/server.ts +237 -0
  49. package/packages/daemon/src/control/verbs.ts +118 -0
  50. package/packages/daemon/src/doctor.ts +113 -28
  51. package/packages/daemon/src/lib/agent-discovery.ts +53 -13
  52. package/packages/daemon/src/lib/app-config.ts +103 -5
  53. package/packages/daemon/src/lib/manifest-pack.ts +255 -0
  54. package/packages/daemon/src/lib/state-home.ts +13 -0
  55. package/packages/daemon/src/lib/update-check.ts +5 -0
  56. package/packages/daemon/src/restore.ts +53 -15
  57. package/packages/daemon/src/send.ts +55 -21
  58. package/packages/daemon/src/tui/chrome/events.ts +4 -4
  59. package/packages/daemon/src/tui/chrome/front-door.ts +39 -0
  60. package/packages/daemon/src/tui/chrome/notify-prefs.ts +58 -0
  61. package/packages/daemon/src/tui/chrome/notify-state.ts +76 -0
  62. package/packages/daemon/src/tui/chrome/notify.ts +582 -84
  63. package/packages/daemon/src/tui/chrome/updater.ts +268 -62
  64. package/packages/daemon/src/tui/detect/classify.ts +34 -0
  65. package/packages/daemon/src/tui/detect/manifest-loader.ts +54 -5
  66. package/packages/daemon/src/tui/detect/manifest.ts +24 -3
  67. package/packages/daemon/src/tui/detect/manifests.ts +240 -6
  68. package/packages/daemon/src/tui/detect/process-tree.ts +13 -3
  69. package/packages/daemon/src/tui/detect/session-id.ts +503 -0
  70. package/packages/daemon/src/tui/integrations/opencode.ts +121 -0
  71. package/packages/daemon/src/tui/mirror/agent-chip.ts +40 -11
  72. package/packages/daemon/src/tui/mirror/agent-lifecycle.ts +437 -0
  73. package/packages/daemon/src/tui/mirror/agent-rows.ts +27 -5
  74. package/packages/daemon/src/tui/mirror/app-state.ts +171 -8
  75. package/packages/daemon/src/tui/mirror/app.tsx +2182 -399
  76. package/packages/daemon/src/tui/mirror/attention.ts +110 -0
  77. package/packages/daemon/src/tui/mirror/dialog-stack.ts +17 -4
  78. package/packages/daemon/src/tui/mirror/diff-model.ts +279 -4
  79. package/packages/daemon/src/tui/mirror/file-tree.ts +231 -6
  80. package/packages/daemon/src/tui/mirror/host-terminal.ts +49 -0
  81. package/packages/daemon/src/tui/mirror/hosted.ts +205 -0
  82. package/packages/daemon/src/tui/mirror/layout-parse.ts +154 -0
  83. package/packages/daemon/src/tui/mirror/menu-model.ts +27 -4
  84. package/packages/daemon/src/tui/mirror/palette.ts +299 -9
  85. package/packages/daemon/src/tui/mirror/pane-mirror.ts +82 -4
  86. package/packages/daemon/src/tui/mirror/pane-surface.tsx +18 -11
  87. package/packages/daemon/src/tui/mirror/perf-tap.ts +29 -3
  88. package/packages/daemon/src/tui/mirror/selection.ts +122 -8
  89. package/packages/daemon/src/tui/mirror/session-mirror.ts +349 -68
  90. package/packages/daemon/src/tui/mirror/settings-model.ts +96 -16
  91. package/packages/daemon/src/tui/mirror/sidebar.tsx +218 -0
  92. package/packages/daemon/src/tui/mirror/size-truth.ts +53 -0
  93. package/packages/daemon/src/tui/mirror/theme.ts +45 -0
  94. package/packages/daemon/src/tui/team/fuzzy.ts +20 -0
  95. package/packages/daemon/src/tui/team/sessions.ts +85 -7
  96. package/packages/daemon/src/tui/team/wait.ts +144 -0
  97. package/scripts/build-macos-notifier.mjs +160 -0
  98. package/scripts/postinstall.js +8 -1
  99. package/scripts/prepublish-check.mjs +37 -1
  100. package/scripts/publish-tap.sh +55 -0
  101. package/skill/SKILL.md +88 -2
package/skill/SKILL.md CHANGED
@@ -34,10 +34,26 @@ minutes is treated as stale (the detector falls back to Layer 2), so long-runnin
34
34
  agents should re-stamp periodically. Two optional companions:
35
35
 
36
36
  ```bash
37
- tmux set-option -p @agent_session_id "<id>" # your Claude session id — powers restore --resume-agents
37
+ tmux set-option -p @agent_session_id "<id>" # your own session id — powers restore --resume-agents
38
38
  tmux set-option -p @agent_hint claude # force which agent manifest Layer 2 uses for this pane
39
39
  ```
40
40
 
41
+ **Display metadata** — say WHAT you're doing and WHO you are, right in the
42
+ fleet UI. Two more optional pane-local options:
43
+
44
+ ```bash
45
+ tmux set-option -p @agent_status_text "refactoring auth" # one-liner, ≤32 chars — shows in the pane chip ("● claude · refactoring auth")
46
+ tmux set-option -p @agent_display_name "reviewer" # your name — replaces the detected kind in sidebar rows & chips
47
+ ```
48
+
49
+ Plain text only (control characters are stripped, tabs break the line for your
50
+ pane — don't stamp them; anything past 32 chars is ellipsized). Both surface in
51
+ `tmux-ide team --json` (per-pane `statusText` / `displayName`), the unified
52
+ app's pane chips, and the sidebar agent rows. They follow the SAME staleness
53
+ rules as `@agent_state`: they only show while your state stamp is fresh, so
54
+ re-stamp `@agent_state` alongside — update the text whenever your focus
55
+ changes, and it disappears with a stale/cleared state instead of lying.
56
+
41
57
  **Claude Code users get this for free** — `tmux-ide integration install claude`
42
58
  writes a POSIX hook into `~/.claude/settings.json` that stamps `@agent_state` on
43
59
  every lifecycle event (UserPromptSubmit/PreToolUse → working, Notification →
@@ -45,6 +61,13 @@ blocked, Stop → done, SessionEnd → idle) and records `@agent_session_id`. It
45
61
  takes effect for **new** Claude Code sessions; the merge is reversible
46
62
  (`integration uninstall claude`).
47
63
 
64
+ **Session-id capture for other kinds** (what `restore --resume-agents` resumes
65
+ from): codex and cursor-agent panes are stamped **automatically** — the chrome
66
+ updater reads each CLI's own on-disk session state; opencode gets a plugin via
67
+ `tmux-ide integration install opencode`. `tmux-ide integration status` shows
68
+ what's active. Kinds without a verified resume story (gemini, aider, copilot, …)
69
+ can self-report the id as above.
70
+
48
71
  **How detection layers work:** Layer 1 is the authority above — a fresh
49
72
  `@agent_state` option is ground truth. When none is present, Layer 2 resolves the
50
73
  agent from the pane's process tree and reads the visible screen against
@@ -91,7 +114,7 @@ tmux-ide adopt --all # adopt every live session
91
114
  tmux-ide unadopt <session> # remove the dock — sessions keep running as plain tmux
92
115
 
93
116
  tmux-ide restore --dry-run --json # preview rebuilding the fleet from the last snapshot
94
- tmux-ide restore --resume-agents # rebuild after a tmux crash; revive Claude convos via claude --resume
117
+ tmux-ide restore --resume-agents # rebuild after a tmux crash; revive agent convos (claude/codex/cursor/opencode)
95
118
 
96
119
  tmux-ide worktree create <branch> --from <ref> # git worktree on a new branch + a session in it
97
120
  tmux-ide worktree open <branch> # open/switch to an existing worktree's session
@@ -102,6 +125,69 @@ tmux-ide update --dry-run # detect install method (dev checkout
102
125
  tmux-ide doctor # system + integration health (tmux version, TUI surfaces, skill freshness)
103
126
  ```
104
127
 
128
+ ## Drive tmux-ide over the socket (agent loops)
129
+
130
+ The CLI above spawns a process per call. If you are driving the fleet in a
131
+ loop — polling status, waiting on agents, reacting to transitions — start the
132
+ control server once and keep ONE connection open instead:
133
+
134
+ ```bash
135
+ tmux-ide serve & # local Unix socket at ~/.tmux-ide/control.sock (0600, this user only)
136
+ ```
137
+
138
+ **Frame format:** newline-delimited JSON, one object per line. Send
139
+ `{"v":1,"id":<any>,"verb":"<verb>","params":{…}}`; you get back
140
+ `{"v":1,"id":<same>,"ok":true,"data":…}` or
141
+ `{"v":1,"id":<same>,"ok":false,"error":{"code","message"}}`. Responses
142
+ correlate by `id` (they may arrive out of order — a long `wait` doesn't block
143
+ other verbs on the same connection). After the `subscribe` verb the server
144
+ also PUSHES unsolicited `{"v":1,"event":"agent-status","data":{ts,session,from,to}}`
145
+ frames the moment its detection tick sees a session change state — no polling.
146
+
147
+ **Verbs:** `fleet` (the `team --json` payload) · `agents` (per-pane entries,
148
+ optional `{session}`) · `send` (`{session,target,message,noEnter?,dir?}`) ·
149
+ `wait` (`{kind:"agent-status",session,status,timeoutMs?}` or
150
+ `{kind:"output",target,match,timeoutMs?}`; a timeout is an error response with
151
+ code `timeout`) · `spawn` (`{kind|command, session?|sessionName, dir?,
152
+ placement?, paneId?}` → the new `paneId`) · `restart-agent` / `stop-agent`
153
+ (`{paneId, kind|command}`) · `explain` (`{target}`) · `subscribe`.
154
+
155
+ One-shot from a shell (nc keeps the pipe open for the response):
156
+
157
+ ```bash
158
+ printf '{"v":1,"id":1,"verb":"fleet"}\n' | nc -U ~/.tmux-ide/control.sock | head -1
159
+ ```
160
+
161
+ A subscribe loop from node:
162
+
163
+ ```js
164
+ const net = require("node:net");
165
+ const os = require("node:os");
166
+ const sock = net.connect(`${os.homedir()}/.tmux-ide/control.sock`);
167
+ let buf = "";
168
+ sock.on("data", (chunk) => {
169
+ buf += chunk;
170
+ const lines = buf.split("\n");
171
+ buf = lines.pop();
172
+ for (const line of lines.filter(Boolean)) {
173
+ const frame = JSON.parse(line);
174
+ if (frame.event === "agent-status") console.log(frame.data); // react here
175
+ }
176
+ });
177
+ sock.write('{"v":1,"id":1,"verb":"subscribe"}\n');
178
+ ```
179
+
180
+ Right after `subscribe`, the first tick reports every session once with
181
+ `from:null` (a snapshot of where the fleet stands); real transitions follow.
182
+
183
+ **Socket vs CLI:** prefer the socket for anything event-driven or repeated
184
+ (subscribe replaces an `events --follow` poll; a server-held `wait` costs no
185
+ spawn-per-poll). Prefer the CLI for one-shot reads and anything a human might
186
+ re-run — it needs no server. With a server running, `tmux-ide events --follow
187
+ --socket` and `tmux-ide wait … --socket` use it automatically and fall back to
188
+ polling silently when it's gone. The server is local-only by design: no
189
+ network listener, no tokens — filesystem permissions are the auth.
190
+
105
191
  ## Keys & surfaces to tell USERS about
106
192
 
107
193
  Once a session is adopted, the whole UI is a keystroke away. **Lead with the