aicodeman 0.9.6 → 0.9.8

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 (169) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +112 -16
  3. package/README.zh-CN.md +664 -0
  4. package/dist/file-stream-manager.d.ts.map +1 -1
  5. package/dist/file-stream-manager.js +6 -2
  6. package/dist/file-stream-manager.js.map +1 -1
  7. package/dist/mux-interface.d.ts +8 -0
  8. package/dist/mux-interface.d.ts.map +1 -1
  9. package/dist/session.d.ts +29 -1
  10. package/dist/session.d.ts.map +1 -1
  11. package/dist/session.js +48 -2
  12. package/dist/session.js.map +1 -1
  13. package/dist/tmux-manager.d.ts +30 -2
  14. package/dist/tmux-manager.d.ts.map +1 -1
  15. package/dist/tmux-manager.js +372 -14
  16. package/dist/tmux-manager.js.map +1 -1
  17. package/dist/types/api.d.ts +10 -17
  18. package/dist/types/api.d.ts.map +1 -1
  19. package/dist/types/api.js +32 -3
  20. package/dist/types/api.js.map +1 -1
  21. package/dist/utils/index.d.ts +1 -0
  22. package/dist/utils/index.d.ts.map +1 -1
  23. package/dist/utils/index.js +1 -0
  24. package/dist/utils/index.js.map +1 -1
  25. package/dist/utils/push-endpoint-validation.d.ts +6 -0
  26. package/dist/utils/push-endpoint-validation.d.ts.map +1 -0
  27. package/dist/utils/push-endpoint-validation.js +80 -0
  28. package/dist/utils/push-endpoint-validation.js.map +1 -0
  29. package/dist/web/public/{api-client.3adebdc2.js → api-client.c9b1cddc.js} +10 -1
  30. package/dist/web/public/api-client.c9b1cddc.js.br +0 -0
  31. package/dist/web/public/api-client.c9b1cddc.js.gz +0 -0
  32. package/dist/web/public/app.a2f053a8.js +35 -0
  33. package/dist/web/public/app.a2f053a8.js.br +0 -0
  34. package/dist/web/public/app.a2f053a8.js.gz +0 -0
  35. package/dist/web/public/{constants.5b68d2de.js → constants.74211deb.js} +1 -0
  36. package/dist/web/public/constants.74211deb.js.br +0 -0
  37. package/dist/web/public/constants.74211deb.js.gz +0 -0
  38. package/dist/web/public/{image-input.7cade6a8.js → image-input.0ea86695.js} +1 -1
  39. package/dist/web/public/{image-input.7cade6a8.js.br → image-input.0ea86695.js.br} +0 -0
  40. package/dist/web/public/image-input.0ea86695.js.gz +0 -0
  41. package/dist/web/public/index.html +23 -19
  42. package/dist/web/public/index.html.br +0 -0
  43. package/dist/web/public/index.html.gz +0 -0
  44. package/dist/web/public/input-cjk.b8686b5e.js +1 -0
  45. package/dist/web/public/input-cjk.b8686b5e.js.br +0 -0
  46. package/dist/web/public/input-cjk.b8686b5e.js.gz +0 -0
  47. package/dist/web/public/{keyboard-accessory.cdfd8c04.js → keyboard-accessory.bc753cc7.js} +3 -2
  48. package/dist/web/public/keyboard-accessory.bc753cc7.js.br +0 -0
  49. package/dist/web/public/keyboard-accessory.bc753cc7.js.gz +0 -0
  50. package/dist/web/public/{mobile-handlers.1e2a8ef8.js → mobile-handlers.d54d97d6.js} +26 -10
  51. package/dist/web/public/mobile-handlers.d54d97d6.js.br +0 -0
  52. package/dist/web/public/mobile-handlers.d54d97d6.js.gz +0 -0
  53. package/dist/web/public/mobile.959f6fe2.css +1 -0
  54. package/dist/web/public/mobile.959f6fe2.css.br +0 -0
  55. package/dist/web/public/mobile.959f6fe2.css.gz +0 -0
  56. package/dist/web/public/notification-manager.9c984ac2.js.gz +0 -0
  57. package/dist/web/public/orchestrator-panel.js +3 -3
  58. package/dist/web/public/orchestrator-panel.js.br +0 -0
  59. package/dist/web/public/orchestrator-panel.js.gz +0 -0
  60. package/dist/web/public/{panels-ui.5192a2c0.js → panels-ui.6bb3169f.js} +4 -4
  61. package/dist/web/public/panels-ui.6bb3169f.js.br +0 -0
  62. package/dist/web/public/panels-ui.6bb3169f.js.gz +0 -0
  63. package/dist/web/public/{ralph-panel.61076370.js → ralph-panel.6de2d0f8.js} +2 -2
  64. package/dist/web/public/{ralph-panel.61076370.js.br → ralph-panel.6de2d0f8.js.br} +0 -0
  65. package/dist/web/public/{ralph-panel.61076370.js.gz → ralph-panel.6de2d0f8.js.gz} +0 -0
  66. package/dist/web/public/{ralph-wizard.52d533d2.js → ralph-wizard.a6b2d36b.js} +6 -6
  67. package/dist/web/public/ralph-wizard.a6b2d36b.js.br +0 -0
  68. package/dist/web/public/ralph-wizard.a6b2d36b.js.gz +0 -0
  69. package/dist/web/public/{respawn-ui.5377f958.js → respawn-ui.2d249da9.js} +1 -1
  70. package/dist/web/public/{respawn-ui.5377f958.js.br → respawn-ui.2d249da9.js.br} +0 -0
  71. package/dist/web/public/{respawn-ui.5377f958.js.gz → respawn-ui.2d249da9.js.gz} +0 -0
  72. package/dist/web/public/session-ui.7e2dbbdd.js +36 -0
  73. package/dist/web/public/session-ui.7e2dbbdd.js.br +0 -0
  74. package/dist/web/public/session-ui.7e2dbbdd.js.gz +0 -0
  75. package/dist/web/public/settings-ui.cbedc88a.js +55 -0
  76. package/dist/web/public/settings-ui.cbedc88a.js.br +0 -0
  77. package/dist/web/public/settings-ui.cbedc88a.js.gz +0 -0
  78. package/dist/web/public/styles.d978a628.css +1 -0
  79. package/dist/web/public/styles.d978a628.css.br +0 -0
  80. package/dist/web/public/styles.d978a628.css.gz +0 -0
  81. package/dist/web/public/subagent-windows.a366a4ad.js.gz +0 -0
  82. package/dist/web/public/sw.js.gz +0 -0
  83. package/dist/web/public/terminal-ui.6ce91b0b.js +3 -0
  84. package/dist/web/public/terminal-ui.6ce91b0b.js.br +0 -0
  85. package/dist/web/public/terminal-ui.6ce91b0b.js.gz +0 -0
  86. package/dist/web/public/upload.html.gz +0 -0
  87. package/dist/web/public/vendor/marked.min.js.gz +0 -0
  88. package/dist/web/public/vendor/xterm-addon-fit.min.js.gz +0 -0
  89. package/dist/web/public/vendor/xterm-addon-unicode11.min.js.gz +0 -0
  90. package/dist/web/public/vendor/xterm-addon-webgl.min.js.gz +0 -0
  91. package/dist/web/public/vendor/xterm-zerolag-input.137ad9f0.js.gz +0 -0
  92. package/dist/web/public/vendor/xterm.css.gz +0 -0
  93. package/dist/web/public/vendor/xterm.min.js.gz +0 -0
  94. package/dist/web/public/voice-input.085e9e73.js.gz +0 -0
  95. package/dist/web/routes/case-routes.d.ts.map +1 -1
  96. package/dist/web/routes/case-routes.js +1 -2
  97. package/dist/web/routes/case-routes.js.map +1 -1
  98. package/dist/web/routes/clipboard-routes.d.ts.map +1 -1
  99. package/dist/web/routes/clipboard-routes.js +3 -2
  100. package/dist/web/routes/clipboard-routes.js.map +1 -1
  101. package/dist/web/routes/file-routes.d.ts.map +1 -1
  102. package/dist/web/routes/file-routes.js +5 -2
  103. package/dist/web/routes/file-routes.js.map +1 -1
  104. package/dist/web/routes/hook-event-routes.js +1 -1
  105. package/dist/web/routes/hook-event-routes.js.map +1 -1
  106. package/dist/web/routes/mux-routes.js +3 -3
  107. package/dist/web/routes/mux-routes.js.map +1 -1
  108. package/dist/web/routes/plan-routes.js +1 -1
  109. package/dist/web/routes/plan-routes.js.map +1 -1
  110. package/dist/web/routes/push-routes.js +2 -2
  111. package/dist/web/routes/push-routes.js.map +1 -1
  112. package/dist/web/routes/ralph-routes.js +2 -2
  113. package/dist/web/routes/ralph-routes.js.map +1 -1
  114. package/dist/web/routes/respawn-routes.d.ts.map +1 -1
  115. package/dist/web/routes/respawn-routes.js +7 -8
  116. package/dist/web/routes/respawn-routes.js.map +1 -1
  117. package/dist/web/routes/scheduled-routes.js +2 -2
  118. package/dist/web/routes/scheduled-routes.js.map +1 -1
  119. package/dist/web/routes/session-routes.d.ts.map +1 -1
  120. package/dist/web/routes/session-routes.js +28 -22
  121. package/dist/web/routes/session-routes.js.map +1 -1
  122. package/dist/web/routes/system-routes.d.ts.map +1 -1
  123. package/dist/web/routes/system-routes.js +13 -17
  124. package/dist/web/routes/system-routes.js.map +1 -1
  125. package/dist/web/routes/ws-routes.d.ts.map +1 -1
  126. package/dist/web/routes/ws-routes.js +21 -1
  127. package/dist/web/routes/ws-routes.js.map +1 -1
  128. package/dist/web/schemas.d.ts +5 -0
  129. package/dist/web/schemas.d.ts.map +1 -1
  130. package/dist/web/schemas.js +7 -2
  131. package/dist/web/schemas.js.map +1 -1
  132. package/dist/web/server.d.ts.map +1 -1
  133. package/dist/web/server.js +59 -5
  134. package/dist/web/server.js.map +1 -1
  135. package/package.json +6 -3
  136. package/dist/web/public/api-client.3adebdc2.js.br +0 -0
  137. package/dist/web/public/api-client.3adebdc2.js.gz +0 -0
  138. package/dist/web/public/app.c860ea08.js +0 -34
  139. package/dist/web/public/app.c860ea08.js.br +0 -0
  140. package/dist/web/public/app.c860ea08.js.gz +0 -0
  141. package/dist/web/public/constants.5b68d2de.js.br +0 -0
  142. package/dist/web/public/constants.5b68d2de.js.gz +0 -0
  143. package/dist/web/public/image-input.7cade6a8.js.gz +0 -0
  144. package/dist/web/public/input-cjk.88082175.js +0 -1
  145. package/dist/web/public/input-cjk.88082175.js.br +0 -0
  146. package/dist/web/public/input-cjk.88082175.js.gz +0 -0
  147. package/dist/web/public/keyboard-accessory.cdfd8c04.js.br +0 -0
  148. package/dist/web/public/keyboard-accessory.cdfd8c04.js.gz +0 -0
  149. package/dist/web/public/mobile-handlers.1e2a8ef8.js.br +0 -0
  150. package/dist/web/public/mobile-handlers.1e2a8ef8.js.gz +0 -0
  151. package/dist/web/public/mobile.26dc30d6.css +0 -1
  152. package/dist/web/public/mobile.26dc30d6.css.br +0 -0
  153. package/dist/web/public/mobile.26dc30d6.css.gz +0 -0
  154. package/dist/web/public/panels-ui.5192a2c0.js.br +0 -0
  155. package/dist/web/public/panels-ui.5192a2c0.js.gz +0 -0
  156. package/dist/web/public/ralph-wizard.52d533d2.js.br +0 -0
  157. package/dist/web/public/ralph-wizard.52d533d2.js.gz +0 -0
  158. package/dist/web/public/session-ui.3e0cf024.js +0 -36
  159. package/dist/web/public/session-ui.3e0cf024.js.br +0 -0
  160. package/dist/web/public/session-ui.3e0cf024.js.gz +0 -0
  161. package/dist/web/public/settings-ui.2b70e2c8.js +0 -55
  162. package/dist/web/public/settings-ui.2b70e2c8.js.br +0 -0
  163. package/dist/web/public/settings-ui.2b70e2c8.js.gz +0 -0
  164. package/dist/web/public/styles.e87cb785.css +0 -1
  165. package/dist/web/public/styles.e87cb785.css.br +0 -0
  166. package/dist/web/public/styles.e87cb785.css.gz +0 -0
  167. package/dist/web/public/terminal-ui.37caa926.js +0 -3
  168. package/dist/web/public/terminal-ui.37caa926.js.br +0 -0
  169. package/dist/web/public/terminal-ui.37caa926.js.gz +0 -0
package/LICENSE CHANGED
@@ -1,6 +1,6 @@
1
1
  MIT License
2
2
 
3
- Copyright (c) 2024 Claudeman Contributors
3
+ Copyright (c) 2024-2026 Codeman Contributors
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
package/README.md CHANGED
@@ -5,15 +5,19 @@
5
5
  <h2 align="center">The missing control plane for AI coding agents</h2>
6
6
 
7
7
  <p align="center">
8
- <em>Agent Visualization &bull; Zero-Lag Input Overlay &bull; Mobile-First UI &bull; Respawn Controller &bull; Multi-Session Dashboard </em>
8
+ <em>Agent Visualization &bull; Zero-Lag Input &bull; Mobile-First UI &bull; Hardened Security</em>
9
+ </p>
10
+
11
+ <p align="center">
12
+ <strong>English</strong> &bull; <a href="README.zh-CN.md">简体中文</a>
9
13
  </p>
10
14
 
11
15
  <p align="center">
12
16
  <a href="https://opensource.org/licenses/MIT"><img src="https://img.shields.io/badge/License-MIT-1e3a5f?style=flat-square" alt="License: MIT"></a>
13
- <a href="https://nodejs.org/"><img src="https://img.shields.io/badge/Node.js-18%2B-22c55e?style=flat-square&logo=node.js&logoColor=white" alt="Node.js 18+"></a>
17
+ <a href="https://nodejs.org/"><img src="https://img.shields.io/badge/Node.js-22%2B-22c55e?style=flat-square&logo=node.js&logoColor=white" alt="Node.js 22+"></a>
14
18
  <a href="https://www.typescriptlang.org/"><img src="https://img.shields.io/badge/TypeScript-5.9-3b82f6?style=flat-square&logo=typescript&logoColor=white" alt="TypeScript 5.9"></a>
15
19
  <a href="https://fastify.dev/"><img src="https://img.shields.io/badge/Fastify-5.x-1e3a5f?style=flat-square&logo=fastify&logoColor=white" alt="Fastify"></a>
16
- <img src="https://img.shields.io/badge/Tests-1435%20total-22c55e?style=flat-square" alt="Tests">
20
+ <img src="https://img.shields.io/badge/Tests-2861%20total-22c55e?style=flat-square" alt="Tests">
17
21
  </p>
18
22
 
19
23
  <p align="center">
@@ -34,7 +38,7 @@ You'll need at least one AI coding CLI installed — [Claude Code](https://docs.
34
38
 
35
39
  ```bash
36
40
  codeman web
37
- # Open http://localhost:3000 press Ctrl+Enter to start your first session
41
+ # Open http://localhost:3000 and start your first session
38
42
  ```
39
43
 
40
44
  <details>
@@ -177,6 +181,8 @@ Watch background agents work in real-time. Codeman monitors agent activity and d
177
181
  - **Auto-behavior** — windows auto-open on spawn, auto-minimize on completion, tab badge shows "AGENT" or "AGENTS (n)" count
178
182
  - **Nested agents** — supports 3-level hierarchies (lead session -> teammate agents -> sub-subagents)
179
183
 
184
+ **Agent Teams** — first-class support for Claude Code's native multi-agent teams (`CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS=1`). `TeamWatcher` polls `~/.claude/teams/`, matches teammates to their lead session, and surfaces them as live subagent windows with **team-aware idle detection** — so the Respawn Controller won't fire while teammates are still working. See [`docs/agent-teams/`](docs/agent-teams/).
185
+
180
186
  ---
181
187
 
182
188
  ## Zero-Lag Input Overlay
@@ -214,6 +220,20 @@ WATCHING → IDLE DETECTED → SEND UPDATE → /clear → /init → CONTINUE →
214
220
 
215
221
  ---
216
222
 
223
+ ## Orchestrator Loop
224
+
225
+ Beyond single-session respawn, the **Orchestrator** turns a high-level goal into a phased plan and drives it to completion across multiple agents — a state machine that runs `idle → planning → approval → executing → verifying → (replanning) → completed`.
226
+
227
+ - **Plan, then execute** — generates a phased plan from your goal and pauses for approval before touching anything; reject with feedback to regenerate
228
+ - **Per-phase verification gates** — each phase is verified before the next begins; on failure the orchestrator replans instead of barreling ahead
229
+ - **Multi-agent execution** — fans phases out to team agents / a task queue, coordinating work too big for one session
230
+ - **Crash-safe** — full state persists under the `orchestrator` key in `state.json`, so it survives restarts
231
+ - **Driven from the UI or API** — the Orchestrator panel, or `POST /api/orchestrator/start` → `/approve` → `/status` (10 endpoints)
232
+
233
+ > Distinct from Ralph (a single-session autonomous loop): the orchestrator coordinates multi-phase, multi-agent execution. Full design: [`docs/orchestrator-loop-architecture.md`](docs/orchestrator-loop-architecture.md).
234
+
235
+ ---
236
+
217
237
  ## Multi-Session Dashboard
218
238
 
219
239
  Run **20 parallel sessions** with full visibility — real-time xterm.js terminals at 60fps, per-session token and cost tracking, tab-based navigation, and one-click management.
@@ -270,6 +290,20 @@ PTY Output → 16ms Server Batch → DEC 2026 Wrap → SSE → Client rAF → xt
270
290
 
271
291
  ---
272
292
 
293
+ ## More Features
294
+
295
+ - **Self-update** — git-clone installs under systemd/launchd update in place from **App Settings → Updates**: it detects the latest release, auto-stashes a dirty tree, and streams build progress across the service restart (npm installs report as non-updatable)
296
+ - **Dual-CLI** — run **Claude Code** or **OpenCode** per session; env-var prefixes auto-gate (`CLAUDE_CODE_*` vs `OPENCODE_*`). See [`docs/opencode-integration.md`](docs/opencode-integration.md)
297
+ - **Effort & Ultracode** — set a per-session default effort (`low`–`max`) or enable **ultracode** (dynamic multi-agent workflows). Soft defaults only — switchable anytime with `/effort` in-session. Extended-thinking budget is configurable too
298
+ - **Voice input** — dictate prompts with Deepgram Nova-3 (Web Speech API fallback): toggle recording, auto-silence stop, live level meter (`Ctrl+Shift+V`)
299
+ - **Image input** — paste or drag-and-drop images straight into a session
300
+ - **Gesture control** *(opt-in)* — a MediaPipe hand-tracking overlay to grab/drag session windows and pinch buttons, hands-free. Enable with `CODEMAN_GESTURE=1` + App Settings → Display
301
+ - **Multi-monitor span** *(macOS)* — one click opens a browser window maximized across all displays, so floating agent/gesture panels can cross the physical seam
302
+ - **CJK / IME input** — full composition support for Chinese / Japanese / Korean
303
+ - **OS notifications & hostname-aware titles** — desktop alerts and tab titles are prefixed `codeman:<host>` so multi-host setups stay unambiguous
304
+
305
+ ---
306
+
273
307
  ## Remote Access — Cloudflare Tunnel
274
308
 
275
309
  Access Codeman from your phone or any device outside your local network using a free [Cloudflare quick tunnel](https://developers.cloudflare.com/cloudflare-one/connections/connect-networks/do-more-with-tunnels/trycloudflare/) — no port forwarding, no DNS, no static IP required.
@@ -391,6 +425,41 @@ When someone authenticates via QR, the desktop shows a notification toast with t
391
425
 
392
426
  ---
393
427
 
428
+ ## Security
429
+
430
+ Codeman launches sessions with `--dangerously-skip-permissions`, so the web UI is by design a remote-code-execution surface for whoever can reach it — the whole security model exists to control *who* that is. Recent hardening (v0.9.0 + v0.9.5) closes the browser-driven attack paths that bite self-hosted dev tools. Full model: [`docs/security-architecture.md`](docs/security-architecture.md). **Found a vulnerability?** See [`SECURITY.md`](SECURITY.md) for private disclosure and the list of known limitations.
431
+
432
+ ### Network & access
433
+
434
+ - **Loopback by default** — binds `127.0.0.1`, reachable only from the same machine, so the no-password default is safe out of the box. Binding a non-loopback host without `CODEMAN_PASSWORD` *starts but prints a loud warning* with three concrete fixes (set a password, loopback + an authenticated tunnel, or explicitly acknowledge with `--allow-unauthenticated-network`)
435
+ - **Optional auth, real sessions** — HTTP Basic via `CODEMAN_USERNAME` (default `admin`) / `CODEMAN_PASSWORD`. Success issues an opaque 256-bit `codeman_session` cookie (`randomBytes(32)`) — validated server-side, not client-signed, so it can't be forged offline (24h TTL, auto-extend, device-context audit log)
436
+ - **Per-IP rate limiting** — 10 failed attempts → `429` with `Retry-After` (15-min decay). A valid cookie or correct password recovers *immediately* even while an attacker hammers the same IP — important because all tunnel traffic shares one loopback IP. QR auth has its own separate limiter
437
+
438
+ ### Always-on browser hardening (v0.9.5)
439
+
440
+ These run for **every** request — before auth, even on the default no-password loopback install:
441
+
442
+ - **Host-header allowlist → blocks DNS rebinding.** A custom domain rebound to `127.0.0.1` is rejected with `403 host not allowed` before any handler runs. Allowed: `localhost`, any IP literal, the bind host, `.ts.net` / `.trycloudflare.com` / `.cfargotunnel.com`, the active managed tunnel, and `CODEMAN_ALLOWED_HOSTS` (add custom reverse-proxy domains here — comma-separated; exact host or leading-dot `.suffix` for subdomains)
443
+ - **Cross-site Origin / CSRF guard.** On state-changing methods (`POST`/`PUT`/`PATCH`/`DELETE`) the `Origin` must pass the same allowlist, else `403 cross-site request blocked`. A *missing* Origin is allowed (so `curl`, the CLI, and Claude Code hooks keep working); only a present-but-foreign or opaque `null` origin is rejected
444
+ - **Raw `text/plain` bodies.** The global parser no longer JSON-parses `text/plain`, closing the CORS "simple request" CSRF vector where a cross-site `fetch` could smuggle JSON into a write route with no preflight
445
+ - **WebSocket origin validation.** The terminal WS upgrade runs the same Host + Origin check and closes with code `4003` on failure (anti-CSWSH)
446
+ - **XSS-escaped agent output.** AI-derived strings (tool names, command arguments, subagent descriptions) are HTML-escaped at every injection site before rendering in the subagent / activity panels
447
+
448
+ ### Input, files & headers
449
+
450
+ - **Schema-validated inputs** — every API body is checked with Zod v4 schemas; a `CLAUDE_CODE_*` / `OPENCODE_*` env-prefix allowlist gates which settings each CLI can receive
451
+ - **Path containment** — file routes `realpath` before boundary checks (no TOCTOU); `..`, absolute paths, and symlinks resolving outside the working dir are rejected. Caps: 10 MB text preview / 50 MB raw & download; `/api/download` blocklists sensitive paths (`.env`, `*credentials*`, `~/.ssh/`, `.aws/credentials`). SVG/HTML is served `octet-stream` + `nosniff` + attachment so it downloads rather than executes
452
+ - **Security headers** — `Content-Security-Policy` (`default-src 'self'`, every exception enumerated), `X-Content-Type-Options: nosniff`, `X-Frame-Options: SAMEORIGIN`, HSTS over HTTPS, and CORS reflected **only** for `localhost` / `127.0.0.1` / `::1`
453
+
454
+ ### Supply chain & isolation
455
+
456
+ - **Pinned & verified deps** — security-sensitive transitive deps are forced to patched versions via npm `overrides`; lockfile integrity is checked on every commit/PR (all entries resolve to `registry.npmjs.org` with `sha512` hashes). Public assets are NUL-byte-scanned and `node --check`-validated in CI
457
+ - **Multi-instance isolation** — `CODEMAN_INSTANCE` scopes both the tmux socket (`-L codeman-<name>`) and data dir (`~/.codeman-<name>`) so two instances never attach each other's live sessions
458
+
459
+ > Mobile login uses single-use, 60-second QR tokens — see [QR Code Authentication](#qr-code-authentication) above for the full design (it addresses all 6 flaws from USENIX Security 2025's QR-login study).
460
+
461
+ ---
462
+
394
463
  ## SSH Alternative (`sc`)
395
464
 
396
465
  If you prefer SSH (Termius, Blink, etc.), the `sc` command is a thumb-friendly session chooser:
@@ -407,24 +476,28 @@ Single-digit selection (1-9), color-coded status, token counts, auto-refresh. De
407
476
 
408
477
  ## Keyboard Shortcuts
409
478
 
479
+ > Ctrl bindings also accept Cmd on macOS.
480
+
410
481
  | Shortcut | Action |
411
482
  |----------|--------|
412
- | `Ctrl+Enter` | Quick-start session |
413
- | `Ctrl+W` | Close session |
414
- | `Ctrl+Tab` | Next session |
483
+ | `Ctrl/Cmd+W` | Kill active session |
484
+ | `Ctrl/Cmd+Tab` | Next session |
415
485
  | `Alt+1`–`Alt+9` | Switch to tab N |
416
486
  | `Ctrl+Shift+{` / `Ctrl+Shift+}` | Move active tab left / right |
417
- | `Ctrl+K` | Kill all sessions |
418
- | `Ctrl+L` | Clear terminal |
487
+ | `Ctrl/Cmd+L` | Clear terminal |
419
488
  | `Ctrl+Shift+R` | Restore terminal size |
420
489
  | `Ctrl+Shift+V` | Toggle voice input |
421
- | `Ctrl/Cmd +/-` | Font size |
422
- | `Escape` | Close panels |
490
+ | `Ctrl/Cmd +` / `-` | Font size |
491
+ | `Ctrl/Cmd+?` | Keyboard help |
492
+ | `Shift+Enter` | Insert newline (sent to terminal) |
493
+ | `Escape` | Close panels & modals |
423
494
 
424
495
  ---
425
496
 
426
497
  ## API
427
498
 
499
+ REST over Fastify — **~140 handlers across 15 route modules**, plus an SSE stream and a WebSocket terminal channel. A representative subset:
500
+
428
501
  ### Sessions
429
502
  | Method | Endpoint | Description |
430
503
  |--------|----------|-------------|
@@ -446,6 +519,14 @@ Single-digit selection (1-9), color-coded status, token counts, auto-refresh. De
446
519
  | `GET` | `/api/sessions/:id/ralph-state` | Get loop state + todos |
447
520
  | `POST` | `/api/sessions/:id/ralph-config` | Configure tracking |
448
521
 
522
+ ### Orchestrator
523
+ | Method | Endpoint | Description |
524
+ |--------|----------|-------------|
525
+ | `POST` | `/api/orchestrator/start` | Start orchestration from a goal |
526
+ | `POST` | `/api/orchestrator/approve` | Approve the generated plan |
527
+ | `GET` | `/api/orchestrator/status` | Current phase + progress |
528
+ | `POST` | `/api/orchestrator/stop` | Stop and clean up |
529
+
449
530
  ### Subagents
450
531
  | Method | Endpoint | Description |
451
532
  |--------|----------|-------------|
@@ -460,6 +541,8 @@ Single-digit selection (1-9), color-coded status, token counts, auto-refresh. De
460
541
  | `GET` | `/api/events` | SSE stream |
461
542
  | `GET` | `/api/status` | Full app state |
462
543
  | `POST` | `/api/hook-event` | Hook callbacks |
544
+ | `GET` | `/api/system/update/check` | Check for a new release |
545
+ | `POST` | `/api/system/update` | Self-update (git-clone installs) |
463
546
  | `POST` | `/api/clipboard` | Push text to all connected browsers (`{text}`) |
464
547
  | `GET` | `/api/sessions/:id/run-summary` | Timeline + stats |
465
548
 
@@ -481,11 +564,13 @@ flowchart TB
481
564
  S1["Session (PTY)"]
482
565
  S2["Session (PTY)"]
483
566
  RC["Respawn Controller"]
567
+ ORC["Orchestrator Loop"]
484
568
  end
485
569
 
486
570
  subgraph Detection["Detection Layer"]
487
571
  RT["Ralph Tracker"]
488
572
  SW["Subagent Watcher<br/><small>~/.claude/projects/*/subagents</small>"]
573
+ TW["Team Watcher<br/><small>~/.claude/teams/*</small>"]
489
574
  end
490
575
 
491
576
  subgraph Persistence["Persistence Layer"]
@@ -505,14 +590,17 @@ flowchart TB
505
590
  SM --> S1
506
591
  SM --> S2
507
592
  SM --> RC
593
+ SM --> ORC
508
594
  SM --> SS
509
595
  S1 --> RT
510
596
  S1 --> SCR
511
597
  S2 --> SCR
512
598
  RC --> SCR
599
+ ORC --> SCR
513
600
  SCR --> CLI
514
601
  SW --> BG
515
602
  SW --> SSE
603
+ TW --> SSE
516
604
  ```
517
605
 
518
606
  ---
@@ -537,13 +625,13 @@ The codebase went through a comprehensive 7-phase refactoring that eliminated go
537
625
  | Phase | What changed | Impact |
538
626
  |-------|-------------|--------|
539
627
  | **Performance** | Cached endpoints, SSE adaptive batching, buffer chunking | Sub-16ms terminal latency |
540
- | **Route extraction** | `server.ts` split into 13 domain route modules + auth middleware + port interfaces | **−60%** server.ts LOC (6,736 → 2,697) |
541
- | **Domain splitting** | `types.ts` → 14 domain files, `ralph-tracker` → 7 files, `respawn-controller` → 5 files, `session` → 6 files | No more god files |
542
- | **Frontend modules** | `app.js` → 9 extracted modules (constants, mobile, voice, notifications, keyboard, CJK input, API, Ralph wizard, subagent windows) | **−24%** app.js LOC (15.2K 11.5K) |
543
- | **Config consolidation** | ~70 scattered magic numbers → 9 domain-focused config files | Zero cross-file duplicates |
628
+ | **Route extraction** | `server.ts` split into 15 domain route modules + auth middleware + port interfaces | **−67%** server.ts LOC (6,736 → 2,254) |
629
+ | **Domain splitting** | `types.ts` → 16 domain files, `ralph-tracker` → 7 files, `respawn-controller` → 5 files, `session` → 6 files | No more god files |
630
+ | **Frontend modules** | `app.js` → 18 extracted modules across infra, domain & feature layers | app.js core down to **~3.4K LOC** |
631
+ | **Config consolidation** | ~70 scattered magic numbers → 10 domain-focused config files | Zero cross-file duplicates |
544
632
  | **Test infrastructure** | Shared mock library, 12 route test files, consolidated MockSession | Testable route handlers via `app.inject()` |
545
633
 
546
- Full details: [`docs/code-structure-findings.md`](docs/code-structure-findings.md)
634
+ Full details: [`docs/archive/code-structure-findings.md`](docs/archive/code-structure-findings.md)
547
635
 
548
636
  ---
549
637
 
@@ -563,6 +651,14 @@ npm install xterm-zerolag-input
563
651
 
564
652
  ---
565
653
 
654
+ ## Versioning
655
+
656
+ Codeman follows [SemVer](https://semver.org/). What the version number actually
657
+ commits to — and what counts as internal (the HTTP/SSE API, on-disk state,
658
+ experimental features) — is spelled out in
659
+ [`docs/versioning-policy.md`](docs/versioning-policy.md). If you script against
660
+ the HTTP API, pin to an exact version.
661
+
566
662
  ## License
567
663
 
568
664
  MIT — see [LICENSE](LICENSE)