@wastedcode/claudemux 0.2.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 (249) hide show
  1. package/CHANGELOG.md +257 -0
  2. package/LICENSE +21 -0
  3. package/README.md +493 -0
  4. package/bin/claudemux +6 -0
  5. package/dist/agents/claude.d.ts +3 -0
  6. package/dist/agents/claude.d.ts.map +1 -0
  7. package/dist/agents/claude.js +585 -0
  8. package/dist/agents/claude.js.map +1 -0
  9. package/dist/agents/index.d.ts +2 -0
  10. package/dist/agents/index.d.ts.map +1 -0
  11. package/dist/agents/index.js +2 -0
  12. package/dist/agents/index.js.map +1 -0
  13. package/dist/agents/types.d.ts +252 -0
  14. package/dist/agents/types.d.ts.map +1 -0
  15. package/dist/agents/types.js +2 -0
  16. package/dist/agents/types.js.map +1 -0
  17. package/dist/backends/tmux/capture.d.ts +25 -0
  18. package/dist/backends/tmux/capture.d.ts.map +1 -0
  19. package/dist/backends/tmux/capture.js +35 -0
  20. package/dist/backends/tmux/capture.js.map +1 -0
  21. package/dist/backends/tmux/exec.d.ts +105 -0
  22. package/dist/backends/tmux/exec.d.ts.map +1 -0
  23. package/dist/backends/tmux/exec.js +226 -0
  24. package/dist/backends/tmux/exec.js.map +1 -0
  25. package/dist/backends/tmux/index.d.ts +22 -0
  26. package/dist/backends/tmux/index.d.ts.map +1 -0
  27. package/dist/backends/tmux/index.js +108 -0
  28. package/dist/backends/tmux/index.js.map +1 -0
  29. package/dist/backends/tmux/keys.d.ts +38 -0
  30. package/dist/backends/tmux/keys.d.ts.map +1 -0
  31. package/dist/backends/tmux/keys.js +63 -0
  32. package/dist/backends/tmux/keys.js.map +1 -0
  33. package/dist/backends/tmux/options.d.ts +24 -0
  34. package/dist/backends/tmux/options.d.ts.map +1 -0
  35. package/dist/backends/tmux/options.js +84 -0
  36. package/dist/backends/tmux/options.js.map +1 -0
  37. package/dist/backends/tmux/sessions.d.ts +70 -0
  38. package/dist/backends/tmux/sessions.d.ts.map +1 -0
  39. package/dist/backends/tmux/sessions.js +156 -0
  40. package/dist/backends/tmux/sessions.js.map +1 -0
  41. package/dist/backends/tmux/socket.d.ts +26 -0
  42. package/dist/backends/tmux/socket.d.ts.map +1 -0
  43. package/dist/backends/tmux/socket.js +31 -0
  44. package/dist/backends/tmux/socket.js.map +1 -0
  45. package/dist/backends/types.d.ts +110 -0
  46. package/dist/backends/types.d.ts.map +1 -0
  47. package/dist/backends/types.js +24 -0
  48. package/dist/backends/types.js.map +1 -0
  49. package/dist/cli/ask.d.ts +11 -0
  50. package/dist/cli/ask.d.ts.map +1 -0
  51. package/dist/cli/ask.js +17 -0
  52. package/dist/cli/ask.js.map +1 -0
  53. package/dist/cli/capture.d.ts +8 -0
  54. package/dist/cli/capture.d.ts.map +1 -0
  55. package/dist/cli/capture.js +15 -0
  56. package/dist/cli/capture.js.map +1 -0
  57. package/dist/cli/context.d.ts +71 -0
  58. package/dist/cli/context.d.ts.map +1 -0
  59. package/dist/cli/context.js +82 -0
  60. package/dist/cli/context.js.map +1 -0
  61. package/dist/cli/exists.d.ts +7 -0
  62. package/dist/cli/exists.d.ts.map +1 -0
  63. package/dist/cli/exists.js +16 -0
  64. package/dist/cli/exists.js.map +1 -0
  65. package/dist/cli/interrupt.d.ts +10 -0
  66. package/dist/cli/interrupt.d.ts.map +1 -0
  67. package/dist/cli/interrupt.js +13 -0
  68. package/dist/cli/interrupt.js.map +1 -0
  69. package/dist/cli/kill.d.ts +7 -0
  70. package/dist/cli/kill.d.ts.map +1 -0
  71. package/dist/cli/kill.js +14 -0
  72. package/dist/cli/kill.js.map +1 -0
  73. package/dist/cli/list.d.ts +10 -0
  74. package/dist/cli/list.d.ts.map +1 -0
  75. package/dist/cli/list.js +19 -0
  76. package/dist/cli/list.js.map +1 -0
  77. package/dist/cli/main.d.ts +13 -0
  78. package/dist/cli/main.d.ts.map +1 -0
  79. package/dist/cli/main.js +143 -0
  80. package/dist/cli/main.js.map +1 -0
  81. package/dist/cli/messages.d.ts +9 -0
  82. package/dist/cli/messages.d.ts.map +1 -0
  83. package/dist/cli/messages.js +13 -0
  84. package/dist/cli/messages.js.map +1 -0
  85. package/dist/cli/respond.d.ts +10 -0
  86. package/dist/cli/respond.d.ts.map +1 -0
  87. package/dist/cli/respond.js +23 -0
  88. package/dist/cli/respond.js.map +1 -0
  89. package/dist/cli/resume.d.ts +12 -0
  90. package/dist/cli/resume.d.ts.map +1 -0
  91. package/dist/cli/resume.js +21 -0
  92. package/dist/cli/resume.js.map +1 -0
  93. package/dist/cli/send.d.ts +9 -0
  94. package/dist/cli/send.d.ts.map +1 -0
  95. package/dist/cli/send.js +16 -0
  96. package/dist/cli/send.js.map +1 -0
  97. package/dist/cli/spawn.d.ts +14 -0
  98. package/dist/cli/spawn.d.ts.map +1 -0
  99. package/dist/cli/spawn.js +21 -0
  100. package/dist/cli/spawn.js.map +1 -0
  101. package/dist/cli/state.d.ts +7 -0
  102. package/dist/cli/state.d.ts.map +1 -0
  103. package/dist/cli/state.js +11 -0
  104. package/dist/cli/state.js.map +1 -0
  105. package/dist/cli/turn-complete.d.ts +8 -0
  106. package/dist/cli/turn-complete.d.ts.map +1 -0
  107. package/dist/cli/turn-complete.js +14 -0
  108. package/dist/cli/turn-complete.js.map +1 -0
  109. package/dist/cli/wait.d.ts +13 -0
  110. package/dist/cli/wait.d.ts.map +1 -0
  111. package/dist/cli/wait.js +17 -0
  112. package/dist/cli/wait.js.map +1 -0
  113. package/dist/compose.d.ts +81 -0
  114. package/dist/compose.d.ts.map +1 -0
  115. package/dist/compose.js +64 -0
  116. package/dist/compose.js.map +1 -0
  117. package/dist/errors.d.ts +250 -0
  118. package/dist/errors.d.ts.map +1 -0
  119. package/dist/errors.js +300 -0
  120. package/dist/errors.js.map +1 -0
  121. package/dist/index.d.ts +22 -0
  122. package/dist/index.d.ts.map +1 -0
  123. package/dist/index.js +17 -0
  124. package/dist/index.js.map +1 -0
  125. package/dist/io/baseline.d.ts +53 -0
  126. package/dist/io/baseline.d.ts.map +1 -0
  127. package/dist/io/baseline.js +97 -0
  128. package/dist/io/baseline.js.map +1 -0
  129. package/dist/io/capture.d.ts +15 -0
  130. package/dist/io/capture.d.ts.map +1 -0
  131. package/dist/io/capture.js +13 -0
  132. package/dist/io/capture.js.map +1 -0
  133. package/dist/io/interrupt.d.ts +46 -0
  134. package/dist/io/interrupt.d.ts.map +1 -0
  135. package/dist/io/interrupt.js +60 -0
  136. package/dist/io/interrupt.js.map +1 -0
  137. package/dist/io/respond.d.ts +28 -0
  138. package/dist/io/respond.d.ts.map +1 -0
  139. package/dist/io/respond.js +33 -0
  140. package/dist/io/respond.js.map +1 -0
  141. package/dist/io/send.d.ts +44 -0
  142. package/dist/io/send.d.ts.map +1 -0
  143. package/dist/io/send.js +66 -0
  144. package/dist/io/send.js.map +1 -0
  145. package/dist/io/stabilize.d.ts +28 -0
  146. package/dist/io/stabilize.d.ts.map +1 -0
  147. package/dist/io/stabilize.js +20 -0
  148. package/dist/io/stabilize.js.map +1 -0
  149. package/dist/io/wait.d.ts +47 -0
  150. package/dist/io/wait.d.ts.map +1 -0
  151. package/dist/io/wait.js +117 -0
  152. package/dist/io/wait.js.map +1 -0
  153. package/dist/observe/incremental.d.ts +28 -0
  154. package/dist/observe/incremental.d.ts.map +1 -0
  155. package/dist/observe/incremental.js +57 -0
  156. package/dist/observe/incremental.js.map +1 -0
  157. package/dist/observe/observer.d.ts +86 -0
  158. package/dist/observe/observer.d.ts.map +1 -0
  159. package/dist/observe/observer.js +167 -0
  160. package/dist/observe/observer.js.map +1 -0
  161. package/dist/observe/session-observer.d.ts +49 -0
  162. package/dist/observe/session-observer.d.ts.map +1 -0
  163. package/dist/observe/session-observer.js +123 -0
  164. package/dist/observe/session-observer.js.map +1 -0
  165. package/dist/session/adopt.d.ts +52 -0
  166. package/dist/session/adopt.d.ts.map +1 -0
  167. package/dist/session/adopt.js +57 -0
  168. package/dist/session/adopt.js.map +1 -0
  169. package/dist/session/boot.d.ts +66 -0
  170. package/dist/session/boot.d.ts.map +1 -0
  171. package/dist/session/boot.js +216 -0
  172. package/dist/session/boot.js.map +1 -0
  173. package/dist/session/constants.d.ts +57 -0
  174. package/dist/session/constants.d.ts.map +1 -0
  175. package/dist/session/constants.js +54 -0
  176. package/dist/session/constants.js.map +1 -0
  177. package/dist/session/create.d.ts +88 -0
  178. package/dist/session/create.d.ts.map +1 -0
  179. package/dist/session/create.js +66 -0
  180. package/dist/session/create.js.map +1 -0
  181. package/dist/session/default-backend.d.ts +27 -0
  182. package/dist/session/default-backend.d.ts.map +1 -0
  183. package/dist/session/default-backend.js +58 -0
  184. package/dist/session/default-backend.js.map +1 -0
  185. package/dist/session/handle.d.ts +63 -0
  186. package/dist/session/handle.d.ts.map +1 -0
  187. package/dist/session/handle.js +284 -0
  188. package/dist/session/handle.js.map +1 -0
  189. package/dist/session/hooks.d.ts +37 -0
  190. package/dist/session/hooks.d.ts.map +1 -0
  191. package/dist/session/hooks.js +42 -0
  192. package/dist/session/hooks.js.map +1 -0
  193. package/dist/session/mutex.d.ts +15 -0
  194. package/dist/session/mutex.d.ts.map +1 -0
  195. package/dist/session/mutex.js +29 -0
  196. package/dist/session/mutex.js.map +1 -0
  197. package/dist/session/recover.d.ts +43 -0
  198. package/dist/session/recover.d.ts.map +1 -0
  199. package/dist/session/recover.js +45 -0
  200. package/dist/session/recover.js.map +1 -0
  201. package/dist/session/ref.d.ts +2 -0
  202. package/dist/session/ref.d.ts.map +1 -0
  203. package/dist/session/ref.js +5 -0
  204. package/dist/session/ref.js.map +1 -0
  205. package/dist/session/registry.d.ts +31 -0
  206. package/dist/session/registry.d.ts.map +1 -0
  207. package/dist/session/registry.js +32 -0
  208. package/dist/session/registry.js.map +1 -0
  209. package/dist/session/resolve.d.ts +30 -0
  210. package/dist/session/resolve.d.ts.map +1 -0
  211. package/dist/session/resolve.js +24 -0
  212. package/dist/session/resolve.js.map +1 -0
  213. package/dist/session/resume.d.ts +68 -0
  214. package/dist/session/resume.d.ts.map +1 -0
  215. package/dist/session/resume.js +54 -0
  216. package/dist/session/resume.js.map +1 -0
  217. package/dist/session/spawn-boot.d.ts +44 -0
  218. package/dist/session/spawn-boot.d.ts.map +1 -0
  219. package/dist/session/spawn-boot.js +87 -0
  220. package/dist/session/spawn-boot.js.map +1 -0
  221. package/dist/session/validate.d.ts +10 -0
  222. package/dist/session/validate.d.ts.map +1 -0
  223. package/dist/session/validate.js +0 -0
  224. package/dist/session/validate.js.map +1 -0
  225. package/dist/state/classifier.d.ts +29 -0
  226. package/dist/state/classifier.d.ts.map +1 -0
  227. package/dist/state/classifier.js +37 -0
  228. package/dist/state/classifier.js.map +1 -0
  229. package/dist/state/types.d.ts +32 -0
  230. package/dist/state/types.d.ts.map +1 -0
  231. package/dist/state/types.js +2 -0
  232. package/dist/state/types.js.map +1 -0
  233. package/dist/types.d.ts +401 -0
  234. package/dist/types.d.ts.map +1 -0
  235. package/dist/types.js +9 -0
  236. package/dist/types.js.map +1 -0
  237. package/dist/util/ansi.d.ts +14 -0
  238. package/dist/util/ansi.d.ts.map +1 -0
  239. package/dist/util/ansi.js +18 -0
  240. package/dist/util/ansi.js.map +1 -0
  241. package/dist/util/emitter.d.ts +17 -0
  242. package/dist/util/emitter.d.ts.map +1 -0
  243. package/dist/util/emitter.js +33 -0
  244. package/dist/util/emitter.js.map +1 -0
  245. package/dist/util/sleep.d.ts +8 -0
  246. package/dist/util/sleep.d.ts.map +1 -0
  247. package/dist/util/sleep.js +10 -0
  248. package/dist/util/sleep.js.map +1 -0
  249. package/package.json +50 -0
@@ -0,0 +1,401 @@
1
+ /**
2
+ * Public types for the claudemux substrate. Re-exported from {@link ./index}.
3
+ *
4
+ * The library is backend-neutral by design: nothing in this file mentions
5
+ * any concrete backend. The internal `Backend` seam lives in
6
+ * `src/backends/types.ts` and is **not** part of the public surface.
7
+ */
8
+ /**
9
+ * Coarse-grained pane states the classifier dispatches into.
10
+ *
11
+ * Dispatch order is locked in `src/state/classifier.ts` —
12
+ * `dialog → permission-prompt → working → idle → unknown`.
13
+ *
14
+ * @remarks
15
+ * `unknown` is a contractual "no predicate fired" return, not a soft idle.
16
+ * Consumers must not treat it as idle; the substrate never warns at runtime
17
+ * (no `console.log` in library code per the code-quality bar).
18
+ */
19
+ export type State = "working" | "idle" | "permission-prompt" | "dialog" | "unknown";
20
+ /**
21
+ * Refinement of {@link State} for callers that only care about whether the
22
+ * agent has stopped working. Returned by {@link SessionHandle.state}-adjacent
23
+ * helpers; superseded for `wait()` by {@link TurnOutcome}.
24
+ */
25
+ export type IdleState = Extract<State, "idle" | "permission-prompt" | "dialog">;
26
+ /**
27
+ * The terminal result of {@link SessionHandle.wait} — the single fused verdict
28
+ * for "the turn stopped, and why." `kind` is the stable discriminant; the nested
29
+ * axis (`on` / `reason`) is the open detail.
30
+ *
31
+ * **Compound ownership.** `wait()` is the *one* owner of this decision and it
32
+ * COMPOSES two atomic sub-owners without re-deriving their internals:
33
+ * - the **observe** sub-owner (the Observer's fused belief from hooks +
34
+ * transcript + pane) yields `completed` / `awaiting` / `aborted`;
35
+ * - the **policy** sub-owner — the **consumer's** patience, passed as
36
+ * {@link ReadyOpts} — yields `budget-exceeded`: `reason:"idle"` (no progress
37
+ * for `idleMs`) vs `"max"` (wall-clock `timeoutMs` elapsed). The library owns
38
+ * **no** patience of its own: with neither budget supplied, `wait()` never
39
+ * returns `budget-exceeded` — it waits for a terminal belief. "Time is the
40
+ * policy's."
41
+ *
42
+ * `completed` guarantees the reply is **readable**: the Observer closes the
43
+ * hook→transcript flush skew before reporting it, so a following
44
+ * `messagesSince(cursor)` is race-free. Content never rides on the outcome — it
45
+ * stays with `messagesSince` (the one content owner).
46
+ */
47
+ export type TurnOutcome = {
48
+ readonly kind: "completed";
49
+ } | {
50
+ readonly kind: "awaiting";
51
+ readonly on: "permission-prompt" | "dialog";
52
+ } | {
53
+ readonly kind: "aborted";
54
+ } | {
55
+ readonly kind: "budget-exceeded";
56
+ readonly reason: "idle" | "max";
57
+ };
58
+ /**
59
+ * A single conversation message, **backend-neutral** — never the agent's raw
60
+ * on-disk record shape. `parts` is the ordered content of one turn-side.
61
+ */
62
+ export interface Message {
63
+ /** Stable per-message id (addressable for streaming dedup / update-in-place). */
64
+ readonly id: string;
65
+ /**
66
+ * Id of this message's parent in the conversation thread, when the agent
67
+ * records one. Lets `messagesSince` follow causal order rather than file
68
+ * order — robust to the transcript flushing records slightly out of sequence.
69
+ */
70
+ readonly parentId?: string;
71
+ readonly role: "user" | "assistant";
72
+ readonly parts: readonly MessagePart[];
73
+ /** ISO timestamp, when the agent records one. */
74
+ readonly at?: string;
75
+ }
76
+ /**
77
+ * A neutral answer to an agent permission prompt (the tool-approval menu that
78
+ * `wait()` surfaces as `{ kind: "awaiting", on: "permission-prompt" }`). The
79
+ * three choices map to every agent's prompt regardless of its menu wording or
80
+ * option order — the agent owns the translation to a concrete keystroke
81
+ * ({@link SessionHandle.respond}). Backend-neutral by design: a consumer writes
82
+ * `respond("approve")`, never a digit.
83
+ *
84
+ * - `"approve"` — allow this one action (claude: option 1, "Yes").
85
+ * - `"approve-for-session"` — allow it and stop asking for the rest of the
86
+ * session (claude: option 2, "Yes, allow all … during this session"). An
87
+ * authority grant broader than a single action — the consumer's call.
88
+ * - `"deny"` — refuse (claude: option 3, "No"); the agent reports back to the
89
+ * model that the tool was rejected and continues the turn.
90
+ */
91
+ export type PromptChoice = "approve" | "approve-for-session" | "deny";
92
+ /**
93
+ * An opaque, serializable anchor into a session's message stream, returned by
94
+ * {@link SessionHandle.send}. Pass it to {@link SessionHandle.messagesSince} to
95
+ * read everything produced since that send. Durable across a process restart
96
+ * (the transcript is append-only — manual and auto compaction summarize the
97
+ * context window, never rewrite the on-disk log).
98
+ */
99
+ export type Cursor = string;
100
+ /** One piece of a {@link Message} — neutral, never a raw tool-call payload. */
101
+ export type MessagePart = {
102
+ readonly kind: "text";
103
+ readonly text: string;
104
+ } | {
105
+ readonly kind: "tool";
106
+ readonly tool: string;
107
+ readonly summary: string;
108
+ } | {
109
+ readonly kind: "tool-result";
110
+ readonly ok: boolean;
111
+ readonly summary: string;
112
+ };
113
+ /**
114
+ * A point-in-time snapshot of a session's progress, fused from the reliable
115
+ * observe signals (hook edges + transcript) — **never a verdict the consumer
116
+ * must treat as policy**. The consumer turns staleness of these into its own
117
+ * patience ("progress is the agent's, time is the policy's").
118
+ */
119
+ export interface Progress {
120
+ /**
121
+ * Turn phase, from the agent's hook edges (deterministic, not pane-scraped):
122
+ * `prompt` (turn submitted, pre-tool) · `tool` (a tool is in flight) ·
123
+ * `composing` (tool done, model composing) · `done` (turn ended) ·
124
+ * `unknown` (no hook signal — e.g. hooks off, observe degraded).
125
+ */
126
+ readonly phase: "prompt" | "tool" | "composing" | "done" | "unknown";
127
+ /** A tool is legitimately running (a `tool-start` with no matching `tool-end`). */
128
+ readonly toolInFlight: boolean;
129
+ /** Count of parsed transcript messages (a coarse, monotonic progress signal). */
130
+ readonly transcriptCount: number;
131
+ /**
132
+ * Whether the hook channel is delivering. `false` means observe has degraded
133
+ * to the best-effort pane fallback (hooks off, or no markers seen) — trust
134
+ * the reliable fields accordingly.
135
+ */
136
+ readonly hookChannelHealthy: boolean;
137
+ /**
138
+ * **Drift canary.** `false` when EVERY observe channel came up blind against a
139
+ * non-empty pane at once: the pane has real content, yet the classifier read no
140
+ * state (`unknown`), no hook edges arrived, and no transcript messages parsed.
141
+ * That triple-blind is the signature of the agent's output format having
142
+ * **drifted** from what the parsers expect (a Claude Code update moved the idle
143
+ * box / hook payload / record shape). Any single channel producing signal — a
144
+ * recognized state, an edge, a parsed message, a known interrupt — keeps it
145
+ * `true`. A point-in-time snapshot: a consumer treats *persistent* `false` as
146
+ * "my version assumptions broke," not a one-frame blip. Distinct from
147
+ * `hookChannelHealthy` (one channel, often legitimately off) — this fires only
148
+ * when ALL channels are blind together.
149
+ */
150
+ readonly agentChannelHealthy: boolean;
151
+ /** The fused state verdict. */
152
+ readonly state: State;
153
+ }
154
+ /**
155
+ * The consumer's **patience** for {@link SessionHandle.wait} — the policy
156
+ * sub-owner of {@link TurnOutcome}. The library imposes **no** patience of its
157
+ * own ("time is the policy's"): every field is optional with **no default**, and
158
+ * with none supplied `wait()` blocks until a terminal belief
159
+ * (`completed`/`awaiting`/`aborted`) — it never invents a deadline. Supply a
160
+ * bound to cap a turn that may never end; the matching `budget-exceeded.reason`
161
+ * tells you which bound tripped.
162
+ *
163
+ * @example
164
+ * ```ts
165
+ * await session.wait(); // no bound — wait for the turn
166
+ * await session.wait({ maxMs: 60_000 }); // give up after 60s wall-clock
167
+ * await session.wait({ idleMs: 30_000 }); // give up after 30s of no progress
168
+ * ```
169
+ */
170
+ export interface ReadyOpts {
171
+ /**
172
+ * Wall-clock cap (ms from the call). Exceeded ⇒ `budget-exceeded{reason:"max"}`.
173
+ * No default — omit to wait without a wall-clock bound.
174
+ */
175
+ maxMs?: number;
176
+ /**
177
+ * No-progress cap (ms): give up after this long with no observable progress AND
178
+ * the agent not in a known-working state (no spinner, no tool in flight). A
179
+ * progressing or working turn never trips it (its heartbeat keeps resetting),
180
+ * so this is "stuck too long," never "still working too long." Exceeded ⇒
181
+ * `budget-exceeded{reason:"idle"}`. No default.
182
+ */
183
+ idleMs?: number;
184
+ /**
185
+ * @deprecated Use {@link maxMs} instead. Kept as a source-compatible alias.
186
+ * (Previously defaulted to 300_000ms; that library-owned default is gone —
187
+ * patience is the consumer's.)
188
+ */
189
+ timeoutMs?: number;
190
+ }
191
+ /**
192
+ * The handle returned by {@link create} — the substrate's per-session
193
+ * vocabulary. Every method is mutex-gated so concurrent consumer calls
194
+ * cannot interleave bytes.
195
+ */
196
+ export interface SessionHandle {
197
+ /** The session name within the namespace. */
198
+ readonly name: string;
199
+ /** The namespace this session belongs to. */
200
+ readonly namespace: string;
201
+ /**
202
+ * The agent's own conversation id — opaque and **backend-neutral** (today
203
+ * claudemux assigns it as claude's `--session-id`; the field name keeps the
204
+ * API alive across a backend swap). The consumer uses it to resume the exact
205
+ * conversation (`create({ extraArgs: ["--resume", id] })`) and to locate the
206
+ * agent's transcript, without scraping for it.
207
+ *
208
+ * **Optional by truth, never fabricated.** claudemux now *always* mints and
209
+ * injects this id at {@link create} (a deliberate, stable surface — consumers
210
+ * may depend on its presence). But a session created by an older claudemux, a
211
+ * non-claudemux session, an {@link adopt} whose recovery cache missed, or a
212
+ * spawn that rode a bare `--resume`/`--fork-session` in `extraArgs` (where the
213
+ * id is claude's to pick and we cannot know it) reports `undefined` — the
214
+ * honest answer, not a guess. `undefined → string` later stays non-breaking;
215
+ * the reverse would not, which is why it is optional now.
216
+ *
217
+ * @remarks
218
+ * Persist `{ name, agentSessionId }` *together* in your own store for restart
219
+ * recovery: the session-option cache that backs {@link adopt}'s recovery only
220
+ * survives while the backend session is alive; recreating after a crash needs
221
+ * your stored id.
222
+ */
223
+ readonly agentSessionId?: string;
224
+ /**
225
+ * Deliver `text` as one logical user turn. Multi-line input is paste-safe
226
+ * by construction (the substrate has no `sendRawText` primitive).
227
+ *
228
+ * Blocks on **write delivery**, NOT on the agent's response. Returns a
229
+ * {@link Cursor} anchored at this send (the user record's id) — pass it to
230
+ * {@link messagesSince} to read what the turn produces.
231
+ *
232
+ * When no user record appears, returns one of two detectable sentinels instead
233
+ * of a fragile count (both resolve empty in `messagesSince`/`turnComplete`, so
234
+ * neither floods):
235
+ * - `DELIVERED_QUEUED` — the session was **busy** and the agent **queued**
236
+ * the message; it is accepted and will run after the in-flight turn. Do
237
+ * **not** re-send (that double-runs); `wait()` out the current turn, let the
238
+ * queued turn run, then read with a fresh cursor.
239
+ * - `DELIVERY_UNCONFIRMED` — no evidence the message landed (a lost Enter, a
240
+ * boot-race drop); safe to re-send.
241
+ *
242
+ * An **empty or whitespace-only** `text` is delivered but is a no-op turn —
243
+ * the agent ignores an empty submit, so no user record is written and the
244
+ * return is `DELIVERY_UNCONFIRMED` (there was nothing to anchor). Guard against
245
+ * empty sends in your own code if a no-op turn would confuse your loop.
246
+ */
247
+ send(text: string): Promise<Cursor>;
248
+ /**
249
+ * The messages produced since `cursor` (a value a prior {@link send}
250
+ * returned), as neutral {@link Message}s read from the session transcript.
251
+ *
252
+ * Returns **empty** for two *benign* reasons: there genuinely is nothing new
253
+ * after a resolvable cursor, or the cursor itself can't be resolved (the
254
+ * `DELIVERY_UNCONFIRMED`/`DELIVERED_QUEUED` sentinels, a stale/garbage value —
255
+ * an unresolvable cursor never returns the whole transcript).
256
+ *
257
+ * **Throws `TranscriptUnlocatable`** when the transcript can't be located at all
258
+ * — no recoverable {@link agentSessionId} and no hook-reported path (an
259
+ * {@link adopt} whose cache missed, a non-claudemux session, a fork before its
260
+ * first hook edge). That case is *blind reads*, not "nothing new"; conflating
261
+ * the two silently in a crash-recovery re-send path double-runs work, so it is a
262
+ * loud error rather than a deceptive `[]`. Gate on `agentSessionId !== undefined`
263
+ * (or catch the error) if you adopt sessions that may not be recoverable.
264
+ */
265
+ messagesSince(cursor: Cursor): Promise<Message[]>;
266
+ /**
267
+ * Did the turn anchored at `cursor` produce a reply? `true` iff an assistant
268
+ * message descends from it. The crash-recovery signal: after a resume, a
269
+ * `false` for your last-sent cursor means that turn was **lost** (the prompt
270
+ * is in the transcript with no reply) — re-send it. A *completed* turn is
271
+ * `true`; an in-flight or never-delivered one is `false`. Avoids hand-rolling a
272
+ * transcript scan to answer "what should I re-send?".
273
+ *
274
+ * Like {@link messagesSince}, it **throws `TranscriptUnlocatable`** when the
275
+ * transcript can't be located at all (no recoverable id, no hook path) — so a
276
+ * blind read in the re-send path surfaces loudly instead of a deceptive `false`
277
+ * that would re-send a turn that actually completed. A locatable-but-replyless
278
+ * turn is the honest `false`.
279
+ */
280
+ turnComplete(cursor: Cursor): Promise<boolean>;
281
+ /**
282
+ * A point-in-time {@link Progress} snapshot — turn phase and progress signals
283
+ * fused from the reliable hook + transcript channels (not pane-scraping).
284
+ * Policy-free: the consumer turns staleness into its own patience.
285
+ */
286
+ progress(): Promise<Progress>;
287
+ /**
288
+ * Answer a permission prompt — the tool-approval menu `wait()` reports as
289
+ * `{ kind: "awaiting", on: "permission-prompt" }`. Sends the single keystroke
290
+ * that selects {@link PromptChoice} in this agent's menu (the agent owns the
291
+ * option-order mapping, so the consumer never types a digit). The natural
292
+ * pairing: `wait()` → `awaiting{permission-prompt}` → `respond(choice)` →
293
+ * `wait()` again for the turn to actually finish — `respond` is to the prompt
294
+ * what `send` is to the composer.
295
+ *
296
+ * **Mechanism, not policy** (mirrors {@link interrupt}). It fires the keystroke
297
+ * *unconditionally* — it does not first confirm a prompt is showing. Unlike
298
+ * `interrupt`'s ESC, a stray digit is NOT harmless: sent when no prompt is up
299
+ * it lands in the composer as draft text that the next `send()` would prepend.
300
+ * So gate it on a permission-prompt reading taken in the SAME in-process
301
+ * sequence — and unlike an interrupt race, the prompt is stable (it waits for
302
+ * an answer; it will not resolve underfoot), so a tight `state()`/`wait()` →
303
+ * `respond()` is reliable. Choosing whether/how to approve is the consumer's
304
+ * authority, never the substrate's.
305
+ *
306
+ * Blocks on write delivery only — like `send`, not on what the turn does next.
307
+ * Throws {@link PromptResponseUnsupported} if the agent declares no
308
+ * permission-prompt handling (no menu mapping to translate the choice).
309
+ */
310
+ respond(choice: PromptChoice): Promise<void>;
311
+ /**
312
+ * Fire `Escape` at the pane — claude's own interrupt key — to stop a
313
+ * working agent.
314
+ *
315
+ * ESC is sent regardless of state; it is meaningful only when
316
+ * `state === working`. ESC on an idle claude is harmless — it clears the
317
+ * input box. The consumer gates on `state()` if they care.
318
+ *
319
+ * Blocks on write delivery plus a brief settle; it guarantees ESC was
320
+ * delivered, NOT that an in-flight abort has fully completed. It does exactly
321
+ * one thing — stop the turn — and bundles no follow-up.
322
+ *
323
+ * **After interrupt(): `state()` reads `unknown` and `wait()` resolves
324
+ * `{ kind: "aborted" }`.** The handle records the interrupt authoritatively (an
325
+ * interrupt fires no `stop` edge and leaves the spinner's "esc to interrupt"
326
+ * frozen in scrollback, so neither channel alone can tell aborted from
327
+ * working). The record clears on the next `send()`. Still do **not** naively
328
+ * `send()` a replacement right after — claude restores the cut text into the
329
+ * composer, so a paste lands onto it and submits the concatenation. Clean
330
+ * "interrupt and replace" clears the composer first — a consumer-composed,
331
+ * claude-specific recipe documented in the README, deliberately not folded
332
+ * into this agent-agnostic verb.
333
+ */
334
+ interrupt(): Promise<void>;
335
+ /**
336
+ * Block until the turn reaches a terminal {@link TurnOutcome} — "it stopped,
337
+ * and here's why." The single owner of the done-decision: it composes the
338
+ * Observer's fused belief (hooks + transcript + pane) with the patience budget,
339
+ * and **never throws on timeout** — a budget overrun returns
340
+ * `{ kind: "budget-exceeded" }`, not an exception.
341
+ *
342
+ * `completed` guarantees the reply is **readable** (the flush skew is closed),
343
+ * so a following `messagesSince(cursor)` is race-free. Content never rides on
344
+ * the outcome — read it with {@link messagesSince}.
345
+ *
346
+ * After {@link interrupt}, this resolves `{ kind: "aborted" }` (the pane shows
347
+ * the interrupted turn; no `stop` hook fires), so it is safe to call.
348
+ */
349
+ wait(opts?: ReadyOpts): Promise<TurnOutcome>;
350
+ /**
351
+ * Return the current fused {@link State} — the Observer's belief
352
+ * (hooks + transcript + pane), not a raw pane scrape; the same owner
353
+ * {@link wait} and {@link progress} defer to. Pure snapshot.
354
+ */
355
+ state(): Promise<State>;
356
+ /**
357
+ * Return the pane text. Default is the live visible region (no ANSI).
358
+ *
359
+ * @param opts.ansi — preserve escape sequences when `true`.
360
+ * @param opts.lines — return only the bottom-N lines.
361
+ */
362
+ capture(opts?: {
363
+ ansi?: boolean;
364
+ lines?: number;
365
+ }): Promise<string>;
366
+ /**
367
+ * Kill exactly this session. Idempotent (killing a gone session is success).
368
+ *
369
+ * **A hard stop, not a drain.** If a turn is in flight, its mid-stream reply is
370
+ * lost — the transcript keeps a dangling prompt (the same shape a crash leaves).
371
+ * To stop a turn but *keep* what it produced, `interrupt()` (or `wait()`) and
372
+ * read with `messagesSince` first, then `kill()`.
373
+ */
374
+ kill(): Promise<void>;
375
+ /**
376
+ * Register an observability hook. Fires for every backend command issued
377
+ * by the substrate, with its argv, duration, exit code, and streams.
378
+ *
379
+ * Returns an unsubscribe function.
380
+ */
381
+ onBackendCommand(handler: (event: BackendCommandEvent) => void): () => void;
382
+ }
383
+ /**
384
+ * The single observability event surface. Mirrors the internal `BackendEvent`
385
+ * shape with neutral names so consumers do not learn the backend's vocabulary.
386
+ */
387
+ export interface BackendCommandEvent {
388
+ /** Unix epoch milliseconds when the command was issued. */
389
+ ts: number;
390
+ /** The argv the substrate spawned. */
391
+ argv: string[];
392
+ /** Wall-clock milliseconds the command took. */
393
+ durationMs: number;
394
+ /** Process exit code. */
395
+ exit: number;
396
+ /** Captured stdout, if any. */
397
+ stdout?: string;
398
+ /** Captured stderr, if any. */
399
+ stderr?: string;
400
+ }
401
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
package/dist/types.js ADDED
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Public types for the claudemux substrate. Re-exported from {@link ./index}.
3
+ *
4
+ * The library is backend-neutral by design: nothing in this file mentions
5
+ * any concrete backend. The internal `Backend` seam lives in
6
+ * `src/backends/types.ts` and is **not** part of the public surface.
7
+ */
8
+ export {};
9
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG"}
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Tiny terminal-hygiene helpers. Generic (no agent vocabulary) — safe to use
3
+ * from agent-agnostic layers.
4
+ */
5
+ /**
6
+ * Strip SGR (color/style) escape sequences — `ESC [ … m` — from a string.
7
+ *
8
+ * Used by predicates that match *plain* pane substrings (dialog headers,
9
+ * `esc to interrupt`) so they keep working when the pane is captured with
10
+ * ANSI styling on (`capture -e`). The styling itself is only meaningful to the
11
+ * readiness check, which interprets it directly rather than stripping it.
12
+ */
13
+ export declare function stripSgr(s: string): string;
14
+ //# sourceMappingURL=ansi.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ansi.d.ts","sourceRoot":"","sources":["../../src/util/ansi.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAKH;;;;;;;GAOG;AACH,wBAAgB,QAAQ,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAE1C"}
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Tiny terminal-hygiene helpers. Generic (no agent vocabulary) — safe to use
3
+ * from agent-agnostic layers.
4
+ */
5
+ // biome-ignore lint/suspicious/noControlCharactersInRegex: SGR escapes are the point.
6
+ const SGR = /\x1b\[[0-9;]*m/g;
7
+ /**
8
+ * Strip SGR (color/style) escape sequences — `ESC [ … m` — from a string.
9
+ *
10
+ * Used by predicates that match *plain* pane substrings (dialog headers,
11
+ * `esc to interrupt`) so they keep working when the pane is captured with
12
+ * ANSI styling on (`capture -e`). The styling itself is only meaningful to the
13
+ * readiness check, which interprets it directly rather than stripping it.
14
+ */
15
+ export function stripSgr(s) {
16
+ return s.replace(SGR, "");
17
+ }
18
+ //# sourceMappingURL=ansi.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ansi.js","sourceRoot":"","sources":["../../src/util/ansi.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,sFAAsF;AACtF,MAAM,GAAG,GAAG,iBAAiB,CAAC;AAE9B;;;;;;;GAOG;AACH,MAAM,UAAU,QAAQ,CAAC,CAAS;IAChC,OAAO,CAAC,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;AAC5B,CAAC"}
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Tiny typed event emitter. One observable, many subscribers; subscribe
3
+ * returns an unsubscribe function (no `off()` needed).
4
+ *
5
+ * Subscriber errors are caught so a single broken handler cannot break
6
+ * the producer or sibling subscribers.
7
+ */
8
+ export declare class Emitter<T> {
9
+ #private;
10
+ /** Register a subscriber; returns an unsubscribe function. */
11
+ on(handler: (value: T) => void): () => void;
12
+ /** Synchronously fan-out `value` to every subscriber. */
13
+ emit(value: T): void;
14
+ /** Current subscriber count. Diagnostic only. */
15
+ get size(): number;
16
+ }
17
+ //# sourceMappingURL=emitter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"emitter.d.ts","sourceRoot":"","sources":["../../src/util/emitter.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,qBAAa,OAAO,CAAC,CAAC;;IAGpB,8DAA8D;IAC9D,EAAE,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,IAAI,GAAG,MAAM,IAAI;IAO3C,yDAAyD;IACzD,IAAI,CAAC,KAAK,EAAE,CAAC,GAAG,IAAI;IAUpB,iDAAiD;IACjD,IAAI,IAAI,IAAI,MAAM,CAEjB;CACF"}
@@ -0,0 +1,33 @@
1
+ /**
2
+ * Tiny typed event emitter. One observable, many subscribers; subscribe
3
+ * returns an unsubscribe function (no `off()` needed).
4
+ *
5
+ * Subscriber errors are caught so a single broken handler cannot break
6
+ * the producer or sibling subscribers.
7
+ */
8
+ export class Emitter {
9
+ #handlers = new Set();
10
+ /** Register a subscriber; returns an unsubscribe function. */
11
+ on(handler) {
12
+ this.#handlers.add(handler);
13
+ return () => {
14
+ this.#handlers.delete(handler);
15
+ };
16
+ }
17
+ /** Synchronously fan-out `value` to every subscriber. */
18
+ emit(value) {
19
+ for (const handler of this.#handlers) {
20
+ try {
21
+ handler(value);
22
+ }
23
+ catch {
24
+ // Subscriber errors must not affect the producer or other subscribers.
25
+ }
26
+ }
27
+ }
28
+ /** Current subscriber count. Diagnostic only. */
29
+ get size() {
30
+ return this.#handlers.size;
31
+ }
32
+ }
33
+ //# sourceMappingURL=emitter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"emitter.js","sourceRoot":"","sources":["../../src/util/emitter.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,MAAM,OAAO,OAAO;IAClB,SAAS,GAAG,IAAI,GAAG,EAAsB,CAAC;IAE1C,8DAA8D;IAC9D,EAAE,CAAC,OAA2B;QAC5B,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;QAC5B,OAAO,GAAG,EAAE;YACV,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;QACjC,CAAC,CAAC;IACJ,CAAC;IAED,yDAAyD;IACzD,IAAI,CAAC,KAAQ;QACX,KAAK,MAAM,OAAO,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;YACrC,IAAI,CAAC;gBACH,OAAO,CAAC,KAAK,CAAC,CAAC;YACjB,CAAC;YAAC,MAAM,CAAC;gBACP,uEAAuE;YACzE,CAAC;QACH,CAAC;IACH,CAAC;IAED,iDAAiD;IACjD,IAAI,IAAI;QACN,OAAO,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC;IAC7B,CAAC;CACF"}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Promise-based sleep helper. `new Promise(res => setTimeout(res, ms))`
3
+ * was repeated across boot.ts, wait.ts, stabilize.ts, and tests; this
4
+ * gives the polling loops one place to evolve (e.g. swapping in an
5
+ * AbortSignal later).
6
+ */
7
+ export declare function sleep(ms: number): Promise<void>;
8
+ //# sourceMappingURL=sleep.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sleep.d.ts","sourceRoot":"","sources":["../../src/util/sleep.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,wBAAgB,KAAK,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAE/C"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Promise-based sleep helper. `new Promise(res => setTimeout(res, ms))`
3
+ * was repeated across boot.ts, wait.ts, stabilize.ts, and tests; this
4
+ * gives the polling loops one place to evolve (e.g. swapping in an
5
+ * AbortSignal later).
6
+ */
7
+ export function sleep(ms) {
8
+ return new Promise((res) => setTimeout(res, ms));
9
+ }
10
+ //# sourceMappingURL=sleep.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sleep.js","sourceRoot":"","sources":["../../src/util/sleep.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,MAAM,UAAU,KAAK,CAAC,EAAU;IAC9B,OAAO,IAAI,OAAO,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,UAAU,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,CAAC;AACnD,CAAC"}
package/package.json ADDED
@@ -0,0 +1,50 @@
1
+ {
2
+ "name": "@wastedcode/claudemux",
3
+ "version": "0.2.0",
4
+ "description": "Drive long-lived Claude Code sessions from Node without writing tmux glue. await session.wait() actually returns when the agent is done.",
5
+ "license": "MIT",
6
+ "repository": {
7
+ "type": "git",
8
+ "url": "git+https://github.com/wastedcode/claudemux.git"
9
+ },
10
+ "homepage": "https://github.com/wastedcode/claudemux#readme",
11
+ "bugs": {
12
+ "url": "https://github.com/wastedcode/claudemux/issues"
13
+ },
14
+ "keywords": ["claude", "claude-code", "tmux", "agent", "cli", "substrate", "automation"],
15
+ "type": "module",
16
+ "main": "./dist/index.js",
17
+ "types": "./dist/index.d.ts",
18
+ "exports": {
19
+ ".": {
20
+ "types": "./dist/index.d.ts",
21
+ "import": "./dist/index.js"
22
+ }
23
+ },
24
+ "bin": {
25
+ "claudemux": "./bin/claudemux"
26
+ },
27
+ "files": ["dist/", "bin/", "README.md", "LICENSE", "CHANGELOG.md"],
28
+ "engines": {
29
+ "node": ">=20"
30
+ },
31
+ "scripts": {
32
+ "build": "tsc -p tsconfig.build.json",
33
+ "check": "biome check .",
34
+ "format": "biome format --write .",
35
+ "lint": "biome lint .",
36
+ "test": "vitest run",
37
+ "test:unit": "vitest run --dir src",
38
+ "test:integration": "vitest run --dir test",
39
+ "typecheck": "tsc --noEmit"
40
+ },
41
+ "dependencies": {
42
+ "commander": "^12.1.0"
43
+ },
44
+ "devDependencies": {
45
+ "@biomejs/biome": "^1.9.0",
46
+ "@types/node": "^20.14.0",
47
+ "typescript": "^5.4.0",
48
+ "vitest": "^2.0.0"
49
+ }
50
+ }