aimux-cli 0.1.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 (207) hide show
  1. package/README.md +743 -0
  2. package/bin/aimux +2 -0
  3. package/dist/agent-events.d.ts +20 -0
  4. package/dist/agent-events.js +2 -0
  5. package/dist/agent-events.js.map +1 -0
  6. package/dist/agent-message-parts.d.ts +17 -0
  7. package/dist/agent-message-parts.js +31 -0
  8. package/dist/agent-message-parts.js.map +1 -0
  9. package/dist/agent-output-parser.d.ts +16 -0
  10. package/dist/agent-output-parser.js +229 -0
  11. package/dist/agent-output-parser.js.map +1 -0
  12. package/dist/agent-tracker.d.ts +9 -0
  13. package/dist/agent-tracker.js +144 -0
  14. package/dist/agent-tracker.js.map +1 -0
  15. package/dist/agent-watcher.d.ts +15 -0
  16. package/dist/agent-watcher.js +2 -0
  17. package/dist/agent-watcher.js.map +1 -0
  18. package/dist/attachment-store.d.ts +35 -0
  19. package/dist/attachment-store.js +129 -0
  20. package/dist/attachment-store.js.map +1 -0
  21. package/dist/builtin-metadata-watchers.d.ts +2 -0
  22. package/dist/builtin-metadata-watchers.js +275 -0
  23. package/dist/builtin-metadata-watchers.js.map +1 -0
  24. package/dist/claude-hooks.d.ts +29 -0
  25. package/dist/claude-hooks.js +106 -0
  26. package/dist/claude-hooks.js.map +1 -0
  27. package/dist/config.d.ts +78 -0
  28. package/dist/config.js +172 -0
  29. package/dist/config.js.map +1 -0
  30. package/dist/context/compactor.d.ts +20 -0
  31. package/dist/context/compactor.js +212 -0
  32. package/dist/context/compactor.js.map +1 -0
  33. package/dist/context/context-bridge.d.ts +67 -0
  34. package/dist/context/context-bridge.js +471 -0
  35. package/dist/context/context-bridge.js.map +1 -0
  36. package/dist/context/context-file.d.ts +11 -0
  37. package/dist/context/context-file.js +93 -0
  38. package/dist/context/context-file.js.map +1 -0
  39. package/dist/context/history.d.ts +40 -0
  40. package/dist/context/history.js +108 -0
  41. package/dist/context/history.js.map +1 -0
  42. package/dist/daemon.d.ts +39 -0
  43. package/dist/daemon.js +344 -0
  44. package/dist/daemon.js.map +1 -0
  45. package/dist/dashboard-session-registry.d.ts +47 -0
  46. package/dist/dashboard-session-registry.js +161 -0
  47. package/dist/dashboard-session-registry.js.map +1 -0
  48. package/dist/dashboard-state.d.ts +18 -0
  49. package/dist/dashboard-state.js +26 -0
  50. package/dist/dashboard-state.js.map +1 -0
  51. package/dist/dashboard.d.ts +118 -0
  52. package/dist/dashboard.js +91 -0
  53. package/dist/dashboard.js.map +1 -0
  54. package/dist/debug.d.ts +7 -0
  55. package/dist/debug.js +41 -0
  56. package/dist/debug.js.map +1 -0
  57. package/dist/fast-control.d.ts +45 -0
  58. package/dist/fast-control.js +174 -0
  59. package/dist/fast-control.js.map +1 -0
  60. package/dist/hotkeys.d.ts +44 -0
  61. package/dist/hotkeys.js +118 -0
  62. package/dist/hotkeys.js.map +1 -0
  63. package/dist/http-client.d.ts +10 -0
  64. package/dist/http-client.js +54 -0
  65. package/dist/http-client.js.map +1 -0
  66. package/dist/instance-directory.d.ts +32 -0
  67. package/dist/instance-directory.js +82 -0
  68. package/dist/instance-directory.js.map +1 -0
  69. package/dist/instance-registry.d.ts +38 -0
  70. package/dist/instance-registry.js +208 -0
  71. package/dist/instance-registry.js.map +1 -0
  72. package/dist/key-parser.d.ts +30 -0
  73. package/dist/key-parser.js +272 -0
  74. package/dist/key-parser.js.map +1 -0
  75. package/dist/last-used.d.ts +31 -0
  76. package/dist/last-used.js +93 -0
  77. package/dist/last-used.js.map +1 -0
  78. package/dist/main.d.ts +1 -0
  79. package/dist/main.js +2483 -0
  80. package/dist/main.js.map +1 -0
  81. package/dist/metadata-server.d.ts +268 -0
  82. package/dist/metadata-server.js +1379 -0
  83. package/dist/metadata-server.js.map +1 -0
  84. package/dist/metadata-store.d.ts +80 -0
  85. package/dist/metadata-store.js +87 -0
  86. package/dist/metadata-store.js.map +1 -0
  87. package/dist/multiplexer.d.ts +471 -0
  88. package/dist/multiplexer.js +5714 -0
  89. package/dist/multiplexer.js.map +1 -0
  90. package/dist/notification-context.d.ts +18 -0
  91. package/dist/notification-context.js +68 -0
  92. package/dist/notification-context.js.map +1 -0
  93. package/dist/notifications.d.ts +38 -0
  94. package/dist/notifications.js +111 -0
  95. package/dist/notifications.js.map +1 -0
  96. package/dist/notify.d.ts +10 -0
  97. package/dist/notify.js +62 -0
  98. package/dist/notify.js.map +1 -0
  99. package/dist/orchestration-actions.d.ts +76 -0
  100. package/dist/orchestration-actions.js +310 -0
  101. package/dist/orchestration-actions.js.map +1 -0
  102. package/dist/orchestration-dispatcher.d.ts +22 -0
  103. package/dist/orchestration-dispatcher.js +49 -0
  104. package/dist/orchestration-dispatcher.js.map +1 -0
  105. package/dist/orchestration-routing.d.ts +20 -0
  106. package/dist/orchestration-routing.js +78 -0
  107. package/dist/orchestration-routing.js.map +1 -0
  108. package/dist/orchestration.d.ts +26 -0
  109. package/dist/orchestration.js +110 -0
  110. package/dist/orchestration.js.map +1 -0
  111. package/dist/osc-notifications.d.ts +15 -0
  112. package/dist/osc-notifications.js +180 -0
  113. package/dist/osc-notifications.js.map +1 -0
  114. package/dist/paths.d.ts +55 -0
  115. package/dist/paths.js +259 -0
  116. package/dist/paths.js.map +1 -0
  117. package/dist/plugin-runtime.d.ts +46 -0
  118. package/dist/plugin-runtime.js +180 -0
  119. package/dist/plugin-runtime.js.map +1 -0
  120. package/dist/project-events.d.ts +36 -0
  121. package/dist/project-events.js +63 -0
  122. package/dist/project-events.js.map +1 -0
  123. package/dist/project-scanner.d.ts +38 -0
  124. package/dist/project-scanner.js +243 -0
  125. package/dist/project-scanner.js.map +1 -0
  126. package/dist/project-service-manifest.d.ts +18 -0
  127. package/dist/project-service-manifest.js +56 -0
  128. package/dist/project-service-manifest.js.map +1 -0
  129. package/dist/recency.d.ts +2 -0
  130. package/dist/recency.js +34 -0
  131. package/dist/recency.js.map +1 -0
  132. package/dist/recorder.d.ts +14 -0
  133. package/dist/recorder.js +130 -0
  134. package/dist/recorder.js.map +1 -0
  135. package/dist/session-bootstrap.d.ts +45 -0
  136. package/dist/session-bootstrap.js +436 -0
  137. package/dist/session-bootstrap.js.map +1 -0
  138. package/dist/session-message-history.d.ts +27 -0
  139. package/dist/session-message-history.js +105 -0
  140. package/dist/session-message-history.js.map +1 -0
  141. package/dist/session-runtime.d.ts +44 -0
  142. package/dist/session-runtime.js +56 -0
  143. package/dist/session-runtime.js.map +1 -0
  144. package/dist/session-semantics.d.ts +35 -0
  145. package/dist/session-semantics.js +110 -0
  146. package/dist/session-semantics.js.map +1 -0
  147. package/dist/status-detector.d.ts +17 -0
  148. package/dist/status-detector.js +67 -0
  149. package/dist/status-detector.js.map +1 -0
  150. package/dist/statusline-model.d.ts +103 -0
  151. package/dist/statusline-model.js +177 -0
  152. package/dist/statusline-model.js.map +1 -0
  153. package/dist/task-dispatcher.d.ts +63 -0
  154. package/dist/task-dispatcher.js +210 -0
  155. package/dist/task-dispatcher.js.map +1 -0
  156. package/dist/task-workflow.d.ts +13 -0
  157. package/dist/task-workflow.js +153 -0
  158. package/dist/task-workflow.js.map +1 -0
  159. package/dist/tasks.d.ts +60 -0
  160. package/dist/tasks.js +120 -0
  161. package/dist/tasks.js.map +1 -0
  162. package/dist/team.d.ts +28 -0
  163. package/dist/team.js +91 -0
  164. package/dist/team.js.map +1 -0
  165. package/dist/terminal-host.d.ts +10 -0
  166. package/dist/terminal-host.js +52 -0
  167. package/dist/terminal-host.js.map +1 -0
  168. package/dist/threads.d.ts +61 -0
  169. package/dist/threads.js +200 -0
  170. package/dist/threads.js.map +1 -0
  171. package/dist/tmux-doctor.d.ts +47 -0
  172. package/dist/tmux-doctor.js +112 -0
  173. package/dist/tmux-doctor.js.map +1 -0
  174. package/dist/tmux-runtime-manager.d.ts +164 -0
  175. package/dist/tmux-runtime-manager.js +794 -0
  176. package/dist/tmux-runtime-manager.js.map +1 -0
  177. package/dist/tmux-session-transport.d.ts +31 -0
  178. package/dist/tmux-session-transport.js +115 -0
  179. package/dist/tmux-session-transport.js.map +1 -0
  180. package/dist/tmux-statusline.d.ts +17 -0
  181. package/dist/tmux-statusline.js +166 -0
  182. package/dist/tmux-statusline.js.map +1 -0
  183. package/dist/tool-output-watchers.d.ts +10 -0
  184. package/dist/tool-output-watchers.js +190 -0
  185. package/dist/tool-output-watchers.js.map +1 -0
  186. package/dist/tui/render/box.d.ts +1 -0
  187. package/dist/tui/render/box.js +20 -0
  188. package/dist/tui/render/box.js.map +1 -0
  189. package/dist/tui/render/text.d.ts +8 -0
  190. package/dist/tui/render/text.js +92 -0
  191. package/dist/tui/render/text.js.map +1 -0
  192. package/dist/tui/screens/dashboard-renderers.d.ts +23 -0
  193. package/dist/tui/screens/dashboard-renderers.js +411 -0
  194. package/dist/tui/screens/dashboard-renderers.js.map +1 -0
  195. package/dist/tui/screens/overlay-renderers.d.ts +10 -0
  196. package/dist/tui/screens/overlay-renderers.js +274 -0
  197. package/dist/tui/screens/overlay-renderers.js.map +1 -0
  198. package/dist/tui/screens/subscreen-renderers.d.ts +9 -0
  199. package/dist/tui/screens/subscreen-renderers.js +327 -0
  200. package/dist/tui/screens/subscreen-renderers.js.map +1 -0
  201. package/dist/workflow.d.ts +19 -0
  202. package/dist/workflow.js +111 -0
  203. package/dist/workflow.js.map +1 -0
  204. package/dist/worktree.d.ts +23 -0
  205. package/dist/worktree.js +101 -0
  206. package/dist/worktree.js.map +1 -0
  207. package/package.json +70 -0
package/README.md ADDED
@@ -0,0 +1,743 @@
1
+ # aimux
2
+
3
+ Native CLI agent multiplexer — run multiple AI coding tools side-by-side with their native TUIs intact.
4
+
5
+ aimux uses `tmux` as its terminal runtime substrate. Each project gets its own managed tmux runtime session, each terminal gets its own dashboard client session/window, and each agent runs in its own tmux window while aimux keeps orchestration, worktrees, plans, and metadata on top.
6
+
7
+ ## Features
8
+
9
+ - **tmux-backed runtime** — real scrollback, attach/detach, repaint, and terminal compatibility come from tmux instead of a custom multiplexer
10
+ - **Dashboard clients** — each terminal gets its own dashboard tmux client session/window while agent runtime stays shared per project
11
+ - **Agent windows** — each agent gets its own tmux window with its native TUI intact
12
+ - **tmux status integration** — the native tmux status line shows aimux session, task, headline, and metadata state
13
+ - **Metadata API** — scripts and agents can push status, progress, logs, and notifications into the tmux status line
14
+ - **Plugin/watcher seam** — local plugins can watch files or external tools and publish metadata without patching aimux core
15
+ - **Leader key switching in dashboard** — `Ctrl+A` prefix for dashboard actions like create/kill/switch while you are in the aimux dashboard window
16
+ - **Dashboard view** — see all running, offline, and remote agents at a glance
17
+ - **Multi-instance** — run aimux in multiple terminal tabs; agents from other instances appear inline and can be taken over
18
+ - **Agent lifecycle** — two-step kill (`[x]` stops → offline, `[x]` again → graveyard), with `aimux graveyard resurrect` for recovery
19
+ - **Task delegation** — agents can delegate work to each other via `.aimux/tasks/`, with automatic dispatch, completion notifications, and dashboard badges
20
+ - **Threaded orchestration** — direct messages, handoffs, and task assignment all flow through durable `.aimux/threads/` state with queued delivery when recipients are busy
21
+ - **Dashboard orchestration actions** — from the main dashboard, use `S` to send a message, `H` to send a handoff, `T` to assign a task, `o` to jump to the most relevant thread, and `R` to reply when something is waiting on you
22
+ - **Workflow view** — a dedicated workflow screen groups related task/review/revision chains, supports actionable filters, and exposes explicit accept/block/complete/reopen/review controls
23
+ - **Next-action guidance** — dashboard rows and details surface `on me`, `blocked`, family-chain pressure, and the single most relevant next orchestration step
24
+ - **Context sharing** — agents can read each other's conversation history via `.aimux/context/`
25
+ - **Session resume** — resume previous sessions using each tool's native resume (`--resume`) or injected history (`--restore`)
26
+ - **Git worktree support** — first-class worktree management for parallel feature work, with per-worktree agent isolation
27
+ - **Fully config-driven** — all tool behavior (prompt detection, session capture, resume, compaction) is declarative config, not code
28
+ - **Configurable** — global (`~/.aimux/config.json`) and project-level (`.aimux/config.json`) configuration with deep merge
29
+ - **Notifications** — cross-platform notifications (macOS, Linux, Windows) when agents need attention or complete tasks
30
+ - **Project event stream** — each project service exposes an SSE stream for ephemeral alerts and other live GUI/web events
31
+ - **Custom instructions** — `~/AIMUX.md` (global) and `./AIMUX.md` (project) are injected into every agent's preamble
32
+
33
+ ## Install
34
+
35
+ ```bash
36
+ # Clone and build
37
+ git clone https://github.com/TraderSamwise/aimux.git
38
+ cd aimux
39
+ yarn install
40
+ yarn build
41
+
42
+ # Link globally
43
+ yarn link
44
+ ```
45
+
46
+ Requires Node.js >= 18 and `tmux` in `PATH`.
47
+
48
+ ## Quick Start
49
+
50
+ ```bash
51
+ # Launch dashboard for this terminal client
52
+ aimux
53
+
54
+ # Launch a specific tool in a new tmux agent window
55
+ aimux claude
56
+ aimux codex
57
+ aimux aider
58
+
59
+ # Resume all offline sessions
60
+ aimux --resume
61
+ ```
62
+
63
+ The per-project tmux session is the long-lived runtime substrate. Aimux no longer tries to build its own PTY multiplexer on top of native TUIs.
64
+
65
+ ## Architecture
66
+
67
+ Aimux now distinguishes between:
68
+
69
+ - `tmux` runtime
70
+ - global aimux control-plane daemon
71
+ - daemon-managed project services
72
+ - terminal/desktop/service clients
73
+
74
+ `tmux` still owns the actual agent runtime:
75
+
76
+ - agent windows
77
+ - PTYs
78
+ - scrollback
79
+ - attach/detach
80
+
81
+ The global daemon owns shared control-plane responsibilities:
82
+
83
+ - project discovery and activation
84
+ - supervision of daemon-managed project services
85
+ - desktop/service-facing project discovery
86
+
87
+ Each active project may have one daemon-managed project service. That project service owns:
88
+
89
+ - metadata API lifecycle
90
+ - plugin runtime
91
+ - project `statusline.json` writing
92
+ - project-scoped control-plane sidecars
93
+
94
+ There is no per-project host election anymore. Dashboard processes are clients, not control-plane owners.
95
+
96
+ Desktop/Tauri now talks to the live control plane directly:
97
+
98
+ - daemon HTTP is used for project discovery / service discovery
99
+ - project-service HTTP is used for live project state and awaited lifecycle actions
100
+ - `statusline.json` remains a derived artifact for tmux/status/debugging, not the desktop's primary transport
101
+ - desktop loading state should clear on heartbeat reconciliation of the expected state change, not on HTTP return alone
102
+
103
+ Terminal clients are isolated from each other:
104
+
105
+ - the shared per-project tmux runtime session owns agent windows
106
+ - each terminal gets its own tmux client session and dashboard window
107
+ - dashboard tab, pointer, and load state are terminal-local
108
+ - orchestration, metadata, and plugin sidecars are project-scoped through the daemon-managed project service
109
+
110
+ Useful commands:
111
+
112
+ ```bash
113
+ aimux daemon ensure
114
+ aimux daemon status --json
115
+ aimux daemon projects --json
116
+ aimux daemon project-ensure --project /abs/path/to/repo
117
+
118
+ # Compatibility wrapper: ensure the current project's control service
119
+ aimux serve
120
+ ```
121
+
122
+ Orchestration commands:
123
+
124
+ ```bash
125
+ aimux message send "Need UI review on the login flow" --assignee ui --worktree /abs/path/to/worktree
126
+ aimux handoff send "Take over the sidebar polish from here" --tool claude
127
+ aimux task assign "Audit the websocket reconnect path" --assignee reviewer
128
+ aimux handoff accept <threadId>
129
+ aimux handoff complete <threadId>
130
+ aimux task accept <taskId>
131
+ aimux task block <taskId> --reason "Waiting on API decision"
132
+ aimux task complete <taskId>
133
+ aimux task reopen <taskId>
134
+ aimux review approve <taskId>
135
+ aimux review request-changes <taskId> --body "Handle reconnect backoff edge cases"
136
+ aimux thread list
137
+ ```
138
+
139
+ GUI-facing lifecycle commands:
140
+
141
+ ```bash
142
+ # Fresh agent using the same spawn flow as the dashboard
143
+ aimux spawn --tool claude --project /abs/path/to/repo --worktree /abs/path/to/worktree --json
144
+
145
+ # Fork an existing live agent with handed-off context
146
+ aimux fork <sessionId> --tool codex --project /abs/path/to/repo --worktree /abs/path/to/worktree --json
147
+
148
+ # Match the dashboard lifecycle
149
+ aimux stop <sessionId> --project /abs/path/to/repo --json
150
+ aimux rename <sessionId> --label "Backend reviewer" --project /abs/path/to/repo --json
151
+ aimux migrate <sessionId> --worktree /abs/path/to/worktree --project /abs/path/to/repo --json
152
+ aimux kill <sessionId> --project /abs/path/to/repo --json
153
+ aimux graveyard send <sessionId> --project /abs/path/to/repo --json
154
+ aimux graveyard resurrect <sessionId> --project /abs/path/to/repo --json
155
+
156
+ # Project-scoped worktree helpers
157
+ aimux worktree list --project /abs/path/to/repo --json
158
+ aimux worktree create feature-x --project /abs/path/to/repo --json
159
+
160
+ # Focus a live agent in tmux
161
+ desktop terminal focus now uses the thin tmux fast-control entrypoint via the project service and terminal client tty
162
+ ```
163
+
164
+ HTTP-backed agent I/O helpers:
165
+
166
+ ```bash
167
+ # Send raw input to a running agent through the project service
168
+ aimux host agent-send <sessionId> "hello\r"
169
+ printf 'hello\r' | aimux host agent-send <sessionId> --stdin
170
+
171
+ # Read a tmux pane snapshot for a running agent
172
+ aimux host agent-read <sessionId> --start-line -80
173
+
174
+ # Stream live pane output over SSE through the project service
175
+ aimux host agent-stream <sessionId> --start-line -80 --interval-ms 250
176
+ ```
177
+
178
+ Ephemeral project events:
179
+
180
+ ```bash
181
+ # Subscribe to per-project alerts/events over SSE
182
+ curl -N http://127.0.0.1:<project-service-port>/events
183
+ ```
184
+
185
+ These commands are additive control-plane helpers on top of the existing `aimux -> tmux -> codex/claude` runtime. They do not replace the native TUI path; they reuse the same session write path and tmux pane capture path through the project HTTP service.
186
+
187
+ For desktop / GUI callers, prefer explicit `--project` usage instead of relying on launcher cwd.
188
+
189
+ Structured message parts:
190
+
191
+ - `POST /agents/input` accepts either plain `data` or ordered `parts`.
192
+ - `parts` currently supports:
193
+ - `{ "type": "text", "text": "..." }`
194
+ - `{ "type": "image", "path": "/abs/path.png", "alt": "..." }`
195
+ - `{ "type": "image", "url": "https://...", "alt": "..." }`
196
+ - `{ "type": "image", "attachmentId": "att_123", "alt": "..." }`
197
+ - Parts preserve inline ordering for GUI / HTTP callers.
198
+ - Today, tmux-backed agent sessions still receive image parts as explicit inline image descriptors in the prompt text. This preserves message structure now, but it is not yet binary image upload/attachment transport.
199
+
200
+ Example:
201
+
202
+ ```json
203
+ {
204
+ "sessionId": "claude-1",
205
+ "parts": [
206
+ { "type": "text", "text": "Compare these two layouts." },
207
+ { "type": "image", "url": "https://example.com/a.png", "alt": "first screenshot" },
208
+ { "type": "text", "text": "The spacing issue is around the header." }
209
+ ],
210
+ "submit": true
211
+ }
212
+ ```
213
+
214
+ Control-plane health:
215
+
216
+ - The desktop UI now surfaces daemon / project-service health and exposes a `Restart control` action.
217
+ - The tmux statusline shows `ctl ok`, `ctl daemon↓`, or `ctl stale`.
218
+ - `ctl stale` means the project-service `statusline.json` snapshot has stopped updating, which usually means the project service died.
219
+ - Manual recovery is still:
220
+
221
+ ```bash
222
+ aimux daemon restart
223
+ cd /abs/path/to/repo
224
+ aimux host restart --serve
225
+ ```
226
+
227
+ Daemon rebuild quirk:
228
+
229
+ - The global daemon and each project service run from the built `dist/` output, not directly from `src/`.
230
+ - If you change project-service HTTP behavior, rebuild first with `yarn build`.
231
+ - If a daemon is already running, restart the daemon too, not just the project service, or the old daemon will keep spawning old project-service code.
232
+
233
+ ```bash
234
+ yarn build
235
+ aimux daemon restart
236
+ cd /abs/path/to/repo
237
+ aimux host restart --serve
238
+ ```
239
+
240
+ The desktop app now exposes these flows directly over daemon/project-service HTTP:
241
+
242
+ - dashboard worktree/agent management
243
+ - spawn, fork, rename, migrate, stop, kill
244
+ - graveyard browse + resurrect
245
+ - worktree create + remove
246
+ - activity, workflow, threads, plans, and graveyard secondary screens
247
+ - direct message compose, handoff send/accept/complete, and task/review workflow actions
248
+ - thread state updates and per-message delivery visibility
249
+
250
+ For the current source of truth, see [docs/current-architecture.md](docs/current-architecture.md).
251
+ For desktop UI integration details, see [docs/desktop-ui-contract.md](docs/desktop-ui-contract.md).
252
+ For the migration rationale, see [docs/global-control-plane-rfc.md](docs/global-control-plane-rfc.md).
253
+
254
+ ## Tmux Compatibility
255
+
256
+ Aimux treats tmux as a managed runtime, not a transparent pass-through. For aimux-owned tmux sessions, aimux applies a fixed compatibility contract instead of inheriting whatever ambient tmux defaults happen to exist on the machine.
257
+
258
+ Managed session policy today:
259
+
260
+ - `prefix = C-a`
261
+ - `prefix2 = C-b`
262
+ - `mouse = on` so tmux can own wheel events and enter pane scrollback reliably
263
+ - `extended-keys = always`
264
+ - `extended-keys-format = csi-u`
265
+ - `terminal-features` includes `xterm*:extkeys`
266
+ - `terminal-features` includes `xterm*:hyperlinks`
267
+ - managed Claude/Codex windows get `allow-passthrough = on`
268
+ - managed Claude/Codex windows get scoped modified-enter bindings for multiline input compatibility
269
+ - managed Claude/Codex windows remap wheel-up into tmux copy-mode scrollback instead of forwarding it into the app
270
+
271
+ This is why aimux can support features like `Ctrl+J`, `Shift+Enter`, and reliable tmux-native wheel scrollback inside managed tmux sessions without depending on user-specific tmux configuration.
272
+
273
+ To inspect the live state for the current project:
274
+
275
+ ```bash
276
+ aimux doctor tmux
277
+ aimux doctor tmux --json
278
+ ```
279
+
280
+ That reports:
281
+
282
+ - terminal environment like `TERM` and `TERM_PROGRAM`
283
+ - tmux version and current client session
284
+ - observed managed-session options versus expected values
285
+ - required terminal features such as `extkeys` and `hyperlinks`
286
+ - active-window state including `@aimux-tool` and `allow-passthrough`
287
+
288
+ ## Hotkeys
289
+
290
+ Hotkey latency note:
291
+
292
+ - dynamic tmux hotkeys now use a small shell transport that prefers local tmux resolution and falls back to project-service control helpers when needed
293
+ - the final window switch still happens in tmux
294
+ - this avoids spawning the heavyweight operator CLI for normal `n/p/s/u/d` navigation
295
+ - dashboard client sessions are kept alive for reuse; exiting a managed dashboard leaves the client instead of destroying the reusable dashboard window
296
+ - stale dashboard artifacts are pruned automatically before open/reload so broken `cat`/`tail` dashboard panes do not poison future attaches
297
+ - the broader latency architecture plan is documented in [docs/latency-architecture-rfc.md](docs/latency-architecture-rfc.md)
298
+ - the current entrypoint split is documented in [docs/latency-entrypoints.md](docs/latency-entrypoints.md)
299
+
300
+ Dashboard hotkeys use the `Ctrl+A` leader prefix:
301
+
302
+ | Key | Action |
303
+ |---|---|
304
+ | `Ctrl+A c` | Create new agent |
305
+ | `Ctrl+A x` | Stop agent (→ offline) or kill offline agent (→ graveyard) |
306
+ | `Ctrl+A w` | Create new worktree |
307
+ | `Ctrl+A W` | Worktree management |
308
+ | `Ctrl+A v` | Request code review for active agent |
309
+ | `Ctrl+A 1-9` | Focus agent by number from the dashboard |
310
+ | `Ctrl+A d` | Return to dashboard window |
311
+ | `Ctrl+A Ctrl+A` | Send literal Ctrl+A inside the dashboard |
312
+
313
+ When you are inside an agent window, tmux owns the terminal. Use normal tmux window navigation or run `aimux` again to return to the dashboard window.
314
+
315
+ Main dashboard orchestration shortcuts:
316
+
317
+ | Key | Action |
318
+ |---|---|
319
+ | `S` | Send direct message from the selected agent row |
320
+ | `H` | Send handoff from the selected agent row |
321
+ | `T` | Assign task from the selected agent row |
322
+ | `o` | Jump to the most relevant thread for the selected agent |
323
+ | `R` | Open quick reply when that agent has something waiting on you |
324
+
325
+ Workflow screen shortcuts:
326
+
327
+ | Key | Action |
328
+ |---|---|
329
+ | `f` | Cycle workflow filters: all / waiting on me / blocked / families |
330
+ | `a` | Accept selected handoff |
331
+ | `c` | Complete selected handoff |
332
+ | `b` | Mark selected thread blocked |
333
+ | `x` | Mark selected thread done |
334
+ | `P` | Approve selected review |
335
+ | `J` | Request changes on selected review |
336
+ | `E` | Reopen selected task chain |
337
+
338
+ Recommended tmux mental model:
339
+
340
+ - the shared project runtime session owns agent windows
341
+ - each terminal gets its own dashboard client session/window
342
+ - aimux metadata, plans, worktrees, and task orchestration sit on top of that runtime
343
+
344
+ For normal tmux users outside aimux, the equivalent setup usually lives in `~/.tmux.conf`. Aimux just codifies that policy inside its own managed sessions so behavior is stable across projects and terminals.
345
+
346
+ ## Tmux Status Line
347
+
348
+ Aimux now uses tmux's native status bar instead of an in-terminal custom footer.
349
+
350
+ The managed tmux session config renders:
351
+
352
+ - **left**: aimux project identity
353
+ - **middle**: native tmux window list
354
+ - **right**: aimux session/task/headline/flash metadata
355
+
356
+ This keeps the terminal surface fully tmux-native while still surfacing the old footer's useful information.
357
+
358
+ Status rendering has two practical data paths that must stay visually aligned:
359
+
360
+ - the rich path from `statusline.json` written by the daemon-managed project service
361
+ - the fallback path from live tmux window metadata
362
+
363
+ When extending the footer/status UI, treat both as first-class render sources. The fallback path must carry enough metadata to render the same identity, role, and activity state as the richer dashboard-written path, otherwise the status bar will visibly flicker between styles during updates.
364
+
365
+ For future tool wiring and continuity expectations, see [docs/tool-integration.md](docs/tool-integration.md).
366
+
367
+ ## Metadata API
368
+
369
+ Inspired by opensessions, aimux exposes a small project-local metadata API from the daemon-managed project service. The tmux status line reads this state and shows it for the active session.
370
+
371
+ CLI helpers:
372
+
373
+ ```bash
374
+ aimux metadata endpoint
375
+ aimux metadata set-status <session> "Deploying" --tone warn
376
+ aimux metadata set-progress <session> 3 10 --label services
377
+ aimux metadata log <session> "Tests passed" --source ci --tone success
378
+ aimux metadata clear-log <session>
379
+ ```
380
+
381
+ The project-service HTTP API also exposes:
382
+
383
+ - `GET /health`
384
+ - `GET /state`
385
+ - `POST /set-status`
386
+ - `POST /set-progress`
387
+ - `POST /log`
388
+ - `POST /clear-log`
389
+ - `POST /notify`
390
+
391
+ Use `aimux metadata endpoint` to get the local base URL for the current project service.
392
+
393
+ ## Plugins And Watchers
394
+
395
+ Aimux can load local metadata plugins from:
396
+
397
+ - `~/.aimux/plugins/*.js|*.mjs`
398
+ - `.aimux/plugins/*.js|*.mjs`
399
+
400
+ Each plugin default-exports a factory:
401
+
402
+ ```js
403
+ export default function (api) {
404
+ return {
405
+ start() {
406
+ api.metadata.setStatus("codex-abc123", "Watching", "info");
407
+ },
408
+ stop() {}
409
+ };
410
+ }
411
+ ```
412
+
413
+ Available API today:
414
+
415
+ - `api.projectRoot`
416
+ - `api.projectId`
417
+ - `api.serverHost`
418
+ - `api.serverPort`
419
+ - `api.metadata.setStatus(session, text, tone?)`
420
+ - `api.metadata.setProgress(session, current, total, label?)`
421
+ - `api.metadata.log(session, message, { source?, tone? })`
422
+ - `api.metadata.clearLog(session)`
423
+
424
+ Built-in watchers already publish:
425
+
426
+ - `.aimux/status/{session-id}.md` first-line headline as metadata status
427
+ - `.aimux/plans/{session-id}.md` checkbox completion as metadata progress
428
+
429
+ ## Dashboard
430
+
431
+ When you run `aimux` without arguments, aimux ensures the project tmux session exists and switches you to the dashboard window showing all agents across all states:
432
+
433
+ ```
434
+ aimux — agent multiplexer
435
+ ──────────────────────────────────────
436
+
437
+ ● [1] claude — running ←
438
+ ● [2] codex — idle
439
+ ○ [3] claude — offline
440
+ ◈ [4] claude — other tab (PID 54321)
441
+
442
+ ──────────────────────────────────────
443
+ ↑↓ select Enter focus [c] new [x] stop [q] quit
444
+ ```
445
+
446
+ - **Enter** on a running agent switches to that agent's tmux window
447
+ - **Enter** on an offline agent resumes it
448
+ - **Enter** on a remote agent (other tab) takes it over
449
+ - **`[x]`** on running → stops to offline; **`[x]`** on offline → sends to graveyard
450
+
451
+ With worktrees, agents are grouped:
452
+
453
+ ```
454
+ (main) — active
455
+ ● [1] claude — running ←
456
+
457
+ fix-auth (fix-auth) — active
458
+ ● [2] claude — running
459
+ ○ [3] codex — offline
460
+
461
+ ──────────────────────────────────────
462
+ ↑↓ worktrees Enter step in [c] new [w] worktree [q] quit
463
+ ```
464
+
465
+ ## Context System
466
+
467
+ aimux records each agent's conversation and makes it available to other agents:
468
+
469
+ - **`.aimux/context/{session-id}/live.md`** — rolling window of recent turns
470
+ - **`.aimux/context/{session-id}/summary.md`** — compacted history
471
+ - **`.aimux/context/{session-id}/summary.meta.json`** — summary provenance (source range + digest)
472
+ - **`.aimux/context/{session-id}/summary.checkpoints.jsonl`** — append-only compaction checkpoints
473
+ - **`.aimux/history/{session-id}.jsonl`** — full raw conversation log
474
+ - **`.aimux/plans/{session-id}.md`** — canonical shared plan for that agent
475
+ - **`.aimux/sessions.json`** — all running agents (so agents can discover each other)
476
+
477
+ Agents are told about these files in their startup preamble.
478
+
479
+ These are the canonical agent-facing paths. Runtime-private state stays under `~/.aimux/projects/<project-id>/...` and is not part of the agent contract.
480
+
481
+ In tmux mode, live terminal state comes from tmux itself. `~/.aimux/projects/<project-id>/state.json` is mainly for offline/resume metadata, not live screen ownership.
482
+
483
+ Memory roles are explicit:
484
+
485
+ - `history/*.jsonl` is append-only audit history and is never compacted away
486
+ - `context/*/live.md` is bounded runtime scratch state maintained by aimux from tmux pane snapshots
487
+ - `context/*/summary.md` is a derived, lossy summary for long-horizon memory
488
+ - `summary.meta.json` and `summary.checkpoints.jsonl` preserve compaction provenance so summaries can be traced back to the underlying raw history
489
+
490
+ ## Fork And Migrate Semantics
491
+
492
+ Aimux treats `fork` and `migrate` as related but distinct operations:
493
+
494
+ - `fork`
495
+ - always creates a new session id
496
+ - seeds the new session with carried-over `.aimux/context/`, `.aimux/history/`, `.aimux/plans/`, and `.aimux/status/` artifacts
497
+ - opens a handoff thread between source and target
498
+ - `migrate`
499
+ - preserves the same aimux session id
500
+ - prefers native backend resume when the tool truly supports it
501
+ - otherwise falls back to aimux-owned continuity injection from history/live context
502
+
503
+ Tool behavior differs:
504
+
505
+ - `Claude`
506
+ - supports clean preamble injection
507
+ - does **not** support backend-session-id resume in the way aimux originally assumed
508
+ - so `fork` and fallback `migrate` rely on aimux-owned continuity artifacts
509
+ - `Codex`
510
+ - supports backend-session-id resume, so `migrate` usually takes the native resume path
511
+ - does **not** currently have a clean startup handoff flag, so `fork` uses seeded files plus an auto-submitted first-turn kickoff
512
+
513
+ For deeper details, see [docs/tool-integration.md](docs/tool-integration.md).
514
+
515
+ ## Shared Plans
516
+
517
+ Aimux standardizes planning per agent/session:
518
+
519
+ - **Canonical path:** `.aimux/plans/{session-id}.md`
520
+ - **Primary key:** session ID, not worktree
521
+ - **Purpose:** lets agents read, audit, annotate, and continue each other's plans without main-checkout/worktree edge cases
522
+
523
+ Each new session gets a stub plan file. Agents are instructed to keep it current using:
524
+
525
+ - `Goal`
526
+ - `Current Status`
527
+ - `Steps`
528
+ - `Notes`
529
+
530
+ ## Task Delegation
531
+
532
+ Agents can delegate work to each other through the aimux task system. This is a file-based protocol — agents create task files, aimux dispatches them, and agents report results.
533
+
534
+ ### How it works
535
+
536
+ 1. **Agent A** creates a task file in `.aimux/tasks/`:
537
+ ```json
538
+ {
539
+ "id": "add-login-form",
540
+ "status": "pending",
541
+ "assignedBy": "claude-abc123",
542
+ "description": "Add a login form component",
543
+ "prompt": "Create a React login form at src/components/LoginForm.tsx with email and password fields, validation, and submit handler.",
544
+ "createdAt": "2025-01-15T10:30:00Z",
545
+ "updatedAt": "2025-01-15T10:30:00Z"
546
+ }
547
+ ```
548
+
549
+ 2. **Aimux detects** the pending task (checks every 2s) and finds an idle agent to handle it
550
+
551
+ 3. **The task prompt is injected** into the target agent's stdin — the agent sees it as input and starts working
552
+
553
+ 4. **The agent completes the work** and updates the task file with `"status": "done"` and a `"result"` summary
554
+
555
+ 5. **Aimux notifies** the original agent that the task is complete
556
+
557
+ ### Targeting
558
+
559
+ Tasks can be targeted in three ways:
560
+
561
+ - **Specific agent**: set `assignedTo` to a session ID from `.aimux/sessions.json`
562
+ - **By tool type**: set `tool` to `"claude"`, `"codex"`, or `"aider"` — dispatched to the first idle agent of that type
563
+ - **Any idle agent**: omit both fields — dispatched to any available idle agent
564
+
565
+ ### Dashboard indicators
566
+
567
+ - Sessions with active tasks show a purple `⧫` badge with the task description
568
+ - The dashboard footer shows task counts: `[T:2p/1a]` (2 pending, 1 assigned)
569
+ - Flash notifications appear when tasks are assigned, completed, or failed
570
+
571
+ ### Using it
572
+
573
+ Just ask your agent to delegate. The preamble tells agents exactly how the protocol works. For example:
574
+
575
+ > "Delegate the test writing to another agent"
576
+
577
+ > "Hand off the CSS cleanup to the codex agent"
578
+
579
+ The agent will create the task file, and aimux handles the rest. This is separate from any native task system in the underlying tools (like Claude Code's internal tasks).
580
+
581
+ ## Custom Instructions
582
+
583
+ Create an `AIMUX.md` file to inject instructions into every agent:
584
+
585
+ - **`~/AIMUX.md`** — global instructions (applied to all projects)
586
+ - **`./AIMUX.md`** — project-specific instructions
587
+
588
+ Both are read and appended to the preamble (global first, then project).
589
+
590
+ ## Configuration
591
+
592
+ Initialize project config:
593
+
594
+ ```bash
595
+ aimux init
596
+ ```
597
+
598
+ This creates `.aimux/config.json`. You can also create a global config at `~/.aimux/config.json`. Project config overrides global, which overrides defaults.
599
+
600
+ ```json
601
+ {
602
+ "defaultTool": "claude",
603
+ "runtime": {
604
+ "tmux": {
605
+ "sessionPrefix": "aimux"
606
+ }
607
+ },
608
+ "notifications": {
609
+ "enabled": true,
610
+ "onPrompt": true,
611
+ "onError": true,
612
+ "onComplete": true
613
+ },
614
+ "tools": {
615
+ "claude": {
616
+ "command": "claude",
617
+ "args": ["--dangerously-skip-permissions"],
618
+ "enabled": true
619
+ }
620
+ }
621
+ }
622
+ ```
623
+
624
+ Tmux runtime:
625
+
626
+ - `sessionPrefix` — deterministic prefix used for managed per-project tmux sessions
627
+
628
+ ### Tool Configuration
629
+
630
+ All tool behavior is config-driven. No tool-specific code exists in the multiplexer — adding or customizing a tool only requires config:
631
+
632
+ ```json
633
+ {
634
+ "tools": {
635
+ "my-tool": {
636
+ "command": "my-tool",
637
+ "args": ["--some-flag"],
638
+ "enabled": true,
639
+ "preambleFlag": ["--system-prompt"],
640
+ "resumeArgs": ["--resume", "{sessionId}"],
641
+ "resumeFallback": ["--continue"],
642
+ "sessionIdFlag": ["--session-id", "{sessionId}"],
643
+ "sessionCapture": {
644
+ "dir": "{home}/.my-tool/sessions/{yyyy}/{mm}/{dd}",
645
+ "pattern": "([0-9a-f-]+)\\.json$",
646
+ "delayMs": 2000
647
+ },
648
+ "promptPatterns": ["^> $", "^\\$ $"],
649
+ "turnPatterns": ["^[>❯]\\s*(.+)"],
650
+ "compactCommand": "claude --print --output-format text",
651
+ "instructionsFile": "AGENTS.md"
652
+ }
653
+ }
654
+ }
655
+ ```
656
+
657
+ | Field | Purpose |
658
+ |---|---|
659
+ | `preambleFlag` | Flag to inject system prompt (e.g. `["--append-system-prompt"]`) |
660
+ | `resumeArgs` | Args to resume a session, with `{sessionId}` placeholder |
661
+ | `resumeFallback` | Fallback resume args when session ID is unavailable |
662
+ | `sessionIdFlag` | Flag to set session ID at spawn time |
663
+ | `sessionCapture` | Filesystem-based session ID capture (dir, regex pattern, delay) |
664
+ | `promptPatterns` | Regex patterns for idle/prompt detection in status bar |
665
+ | `turnPatterns` | Regex patterns for extracting conversation turns from output |
666
+ | `compactCommand` | Shell command for LLM-powered history compaction |
667
+ | `instructionsFile` | File to write preamble to (for tools without system prompt flags) |
668
+
669
+ ## Multi-Instance
670
+
671
+ Run aimux in multiple terminal tabs for the same project. Each instance registers in `.aimux/instances.json` with a heartbeat. Agents from other instances appear inline in the dashboard with a `◈` icon.
672
+
673
+ - **Enter** on a remote agent takes it over (resumes in your instance)
674
+ - `--resume` skips agents already owned by another live instance
675
+ - When an instance exits, its agents become offline and visible to other instances
676
+ - Dead instances are auto-pruned via PID checks and heartbeat staleness
677
+
678
+ ## Agent Lifecycle
679
+
680
+ Agents have three states: **running**, **offline**, and **graveyarded**.
681
+
682
+ ```
683
+ running ──[x]──▶ offline ──[x]──▶ graveyard
684
+ │ │
685
+ ◀──Enter── ◀── aimux graveyard resurrect
686
+ ```
687
+
688
+ ```bash
689
+ # List agents in the graveyard
690
+ aimux graveyard list
691
+
692
+ # Stop to offline
693
+ aimux stop <sessionId>
694
+
695
+ # Send directly to graveyard
696
+ aimux kill <sessionId>
697
+
698
+ # Resurrect an agent back to offline state
699
+ aimux graveyard resurrect <id>
700
+ ```
701
+
702
+ Context files (`.aimux/context/`, `.aimux/history/`) are never deleted — only the agent's state changes.
703
+
704
+ ## Worktrees
705
+
706
+ aimux manages git worktrees and, by default, creates them inside `.aimux/worktrees/` in the main repo:
707
+
708
+ ```bash
709
+ # Spawn a fresh agent
710
+ aimux spawn --tool claude
711
+
712
+ # Fork a live agent into a worktree
713
+ aimux fork <sessionId> --tool codex --worktree /abs/path/to/repo/.aimux/worktrees/fix-auth
714
+
715
+ # Create a worktree
716
+ aimux worktree create fix-auth
717
+
718
+ # List worktrees
719
+ aimux worktree list
720
+ ```
721
+
722
+ The create location is configurable via `.aimux/config.json` or `~/.aimux/config.json`:
723
+
724
+ ```json
725
+ {
726
+ "worktrees": {
727
+ "baseDir": ".aimux/worktrees"
728
+ }
729
+ }
730
+ ```
731
+
732
+ Relative `baseDir` values are resolved from the main repo root. Absolute paths are also supported.
733
+
734
+ ## Requirements
735
+
736
+ - macOS (Linux support planned)
737
+ - Node.js >= 18
738
+ - At least one supported AI tool installed: `claude`, `codex`, or `aider`
739
+ - Notifications work out of the box on macOS, Linux, and Windows
740
+
741
+ ## License
742
+
743
+ MIT