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.
- package/LICENSE +1 -1
- package/README.md +112 -16
- package/README.zh-CN.md +664 -0
- package/dist/file-stream-manager.d.ts.map +1 -1
- package/dist/file-stream-manager.js +6 -2
- package/dist/file-stream-manager.js.map +1 -1
- package/dist/mux-interface.d.ts +8 -0
- package/dist/mux-interface.d.ts.map +1 -1
- package/dist/session.d.ts +29 -1
- package/dist/session.d.ts.map +1 -1
- package/dist/session.js +48 -2
- package/dist/session.js.map +1 -1
- package/dist/tmux-manager.d.ts +30 -2
- package/dist/tmux-manager.d.ts.map +1 -1
- package/dist/tmux-manager.js +372 -14
- package/dist/tmux-manager.js.map +1 -1
- package/dist/types/api.d.ts +10 -17
- package/dist/types/api.d.ts.map +1 -1
- package/dist/types/api.js +32 -3
- package/dist/types/api.js.map +1 -1
- package/dist/utils/index.d.ts +1 -0
- package/dist/utils/index.d.ts.map +1 -1
- package/dist/utils/index.js +1 -0
- package/dist/utils/index.js.map +1 -1
- package/dist/utils/push-endpoint-validation.d.ts +6 -0
- package/dist/utils/push-endpoint-validation.d.ts.map +1 -0
- package/dist/utils/push-endpoint-validation.js +80 -0
- package/dist/utils/push-endpoint-validation.js.map +1 -0
- package/dist/web/public/{api-client.3adebdc2.js → api-client.c9b1cddc.js} +10 -1
- package/dist/web/public/api-client.c9b1cddc.js.br +0 -0
- package/dist/web/public/api-client.c9b1cddc.js.gz +0 -0
- package/dist/web/public/app.a2f053a8.js +35 -0
- package/dist/web/public/app.a2f053a8.js.br +0 -0
- package/dist/web/public/app.a2f053a8.js.gz +0 -0
- package/dist/web/public/{constants.5b68d2de.js → constants.74211deb.js} +1 -0
- package/dist/web/public/constants.74211deb.js.br +0 -0
- package/dist/web/public/constants.74211deb.js.gz +0 -0
- package/dist/web/public/{image-input.7cade6a8.js → image-input.0ea86695.js} +1 -1
- package/dist/web/public/{image-input.7cade6a8.js.br → image-input.0ea86695.js.br} +0 -0
- package/dist/web/public/image-input.0ea86695.js.gz +0 -0
- package/dist/web/public/index.html +23 -19
- package/dist/web/public/index.html.br +0 -0
- package/dist/web/public/index.html.gz +0 -0
- package/dist/web/public/input-cjk.b8686b5e.js +1 -0
- package/dist/web/public/input-cjk.b8686b5e.js.br +0 -0
- package/dist/web/public/input-cjk.b8686b5e.js.gz +0 -0
- package/dist/web/public/{keyboard-accessory.cdfd8c04.js → keyboard-accessory.bc753cc7.js} +3 -2
- package/dist/web/public/keyboard-accessory.bc753cc7.js.br +0 -0
- package/dist/web/public/keyboard-accessory.bc753cc7.js.gz +0 -0
- package/dist/web/public/{mobile-handlers.1e2a8ef8.js → mobile-handlers.d54d97d6.js} +26 -10
- package/dist/web/public/mobile-handlers.d54d97d6.js.br +0 -0
- package/dist/web/public/mobile-handlers.d54d97d6.js.gz +0 -0
- package/dist/web/public/mobile.959f6fe2.css +1 -0
- package/dist/web/public/mobile.959f6fe2.css.br +0 -0
- package/dist/web/public/mobile.959f6fe2.css.gz +0 -0
- package/dist/web/public/notification-manager.9c984ac2.js.gz +0 -0
- package/dist/web/public/orchestrator-panel.js +3 -3
- package/dist/web/public/orchestrator-panel.js.br +0 -0
- package/dist/web/public/orchestrator-panel.js.gz +0 -0
- package/dist/web/public/{panels-ui.5192a2c0.js → panels-ui.6bb3169f.js} +4 -4
- package/dist/web/public/panels-ui.6bb3169f.js.br +0 -0
- package/dist/web/public/panels-ui.6bb3169f.js.gz +0 -0
- package/dist/web/public/{ralph-panel.61076370.js → ralph-panel.6de2d0f8.js} +2 -2
- package/dist/web/public/{ralph-panel.61076370.js.br → ralph-panel.6de2d0f8.js.br} +0 -0
- package/dist/web/public/{ralph-panel.61076370.js.gz → ralph-panel.6de2d0f8.js.gz} +0 -0
- package/dist/web/public/{ralph-wizard.52d533d2.js → ralph-wizard.a6b2d36b.js} +6 -6
- package/dist/web/public/ralph-wizard.a6b2d36b.js.br +0 -0
- package/dist/web/public/ralph-wizard.a6b2d36b.js.gz +0 -0
- package/dist/web/public/{respawn-ui.5377f958.js → respawn-ui.2d249da9.js} +1 -1
- package/dist/web/public/{respawn-ui.5377f958.js.br → respawn-ui.2d249da9.js.br} +0 -0
- package/dist/web/public/{respawn-ui.5377f958.js.gz → respawn-ui.2d249da9.js.gz} +0 -0
- package/dist/web/public/session-ui.7e2dbbdd.js +36 -0
- package/dist/web/public/session-ui.7e2dbbdd.js.br +0 -0
- package/dist/web/public/session-ui.7e2dbbdd.js.gz +0 -0
- package/dist/web/public/settings-ui.cbedc88a.js +55 -0
- package/dist/web/public/settings-ui.cbedc88a.js.br +0 -0
- package/dist/web/public/settings-ui.cbedc88a.js.gz +0 -0
- package/dist/web/public/styles.d978a628.css +1 -0
- package/dist/web/public/styles.d978a628.css.br +0 -0
- package/dist/web/public/styles.d978a628.css.gz +0 -0
- package/dist/web/public/subagent-windows.a366a4ad.js.gz +0 -0
- package/dist/web/public/sw.js.gz +0 -0
- package/dist/web/public/terminal-ui.6ce91b0b.js +3 -0
- package/dist/web/public/terminal-ui.6ce91b0b.js.br +0 -0
- package/dist/web/public/terminal-ui.6ce91b0b.js.gz +0 -0
- package/dist/web/public/upload.html.gz +0 -0
- package/dist/web/public/vendor/marked.min.js.gz +0 -0
- package/dist/web/public/vendor/xterm-addon-fit.min.js.gz +0 -0
- package/dist/web/public/vendor/xterm-addon-unicode11.min.js.gz +0 -0
- package/dist/web/public/vendor/xterm-addon-webgl.min.js.gz +0 -0
- package/dist/web/public/vendor/xterm-zerolag-input.137ad9f0.js.gz +0 -0
- package/dist/web/public/vendor/xterm.css.gz +0 -0
- package/dist/web/public/vendor/xterm.min.js.gz +0 -0
- package/dist/web/public/voice-input.085e9e73.js.gz +0 -0
- package/dist/web/routes/case-routes.d.ts.map +1 -1
- package/dist/web/routes/case-routes.js +1 -2
- package/dist/web/routes/case-routes.js.map +1 -1
- package/dist/web/routes/clipboard-routes.d.ts.map +1 -1
- package/dist/web/routes/clipboard-routes.js +3 -2
- package/dist/web/routes/clipboard-routes.js.map +1 -1
- package/dist/web/routes/file-routes.d.ts.map +1 -1
- package/dist/web/routes/file-routes.js +5 -2
- package/dist/web/routes/file-routes.js.map +1 -1
- package/dist/web/routes/hook-event-routes.js +1 -1
- package/dist/web/routes/hook-event-routes.js.map +1 -1
- package/dist/web/routes/mux-routes.js +3 -3
- package/dist/web/routes/mux-routes.js.map +1 -1
- package/dist/web/routes/plan-routes.js +1 -1
- package/dist/web/routes/plan-routes.js.map +1 -1
- package/dist/web/routes/push-routes.js +2 -2
- package/dist/web/routes/push-routes.js.map +1 -1
- package/dist/web/routes/ralph-routes.js +2 -2
- package/dist/web/routes/ralph-routes.js.map +1 -1
- package/dist/web/routes/respawn-routes.d.ts.map +1 -1
- package/dist/web/routes/respawn-routes.js +7 -8
- package/dist/web/routes/respawn-routes.js.map +1 -1
- package/dist/web/routes/scheduled-routes.js +2 -2
- package/dist/web/routes/scheduled-routes.js.map +1 -1
- package/dist/web/routes/session-routes.d.ts.map +1 -1
- package/dist/web/routes/session-routes.js +28 -22
- package/dist/web/routes/session-routes.js.map +1 -1
- package/dist/web/routes/system-routes.d.ts.map +1 -1
- package/dist/web/routes/system-routes.js +13 -17
- package/dist/web/routes/system-routes.js.map +1 -1
- package/dist/web/routes/ws-routes.d.ts.map +1 -1
- package/dist/web/routes/ws-routes.js +21 -1
- package/dist/web/routes/ws-routes.js.map +1 -1
- package/dist/web/schemas.d.ts +5 -0
- package/dist/web/schemas.d.ts.map +1 -1
- package/dist/web/schemas.js +7 -2
- package/dist/web/schemas.js.map +1 -1
- package/dist/web/server.d.ts.map +1 -1
- package/dist/web/server.js +59 -5
- package/dist/web/server.js.map +1 -1
- package/package.json +6 -3
- package/dist/web/public/api-client.3adebdc2.js.br +0 -0
- package/dist/web/public/api-client.3adebdc2.js.gz +0 -0
- package/dist/web/public/app.c860ea08.js +0 -34
- package/dist/web/public/app.c860ea08.js.br +0 -0
- package/dist/web/public/app.c860ea08.js.gz +0 -0
- package/dist/web/public/constants.5b68d2de.js.br +0 -0
- package/dist/web/public/constants.5b68d2de.js.gz +0 -0
- package/dist/web/public/image-input.7cade6a8.js.gz +0 -0
- package/dist/web/public/input-cjk.88082175.js +0 -1
- package/dist/web/public/input-cjk.88082175.js.br +0 -0
- package/dist/web/public/input-cjk.88082175.js.gz +0 -0
- package/dist/web/public/keyboard-accessory.cdfd8c04.js.br +0 -0
- package/dist/web/public/keyboard-accessory.cdfd8c04.js.gz +0 -0
- package/dist/web/public/mobile-handlers.1e2a8ef8.js.br +0 -0
- package/dist/web/public/mobile-handlers.1e2a8ef8.js.gz +0 -0
- package/dist/web/public/mobile.26dc30d6.css +0 -1
- package/dist/web/public/mobile.26dc30d6.css.br +0 -0
- package/dist/web/public/mobile.26dc30d6.css.gz +0 -0
- package/dist/web/public/panels-ui.5192a2c0.js.br +0 -0
- package/dist/web/public/panels-ui.5192a2c0.js.gz +0 -0
- package/dist/web/public/ralph-wizard.52d533d2.js.br +0 -0
- package/dist/web/public/ralph-wizard.52d533d2.js.gz +0 -0
- package/dist/web/public/session-ui.3e0cf024.js +0 -36
- package/dist/web/public/session-ui.3e0cf024.js.br +0 -0
- package/dist/web/public/session-ui.3e0cf024.js.gz +0 -0
- package/dist/web/public/settings-ui.2b70e2c8.js +0 -55
- package/dist/web/public/settings-ui.2b70e2c8.js.br +0 -0
- package/dist/web/public/settings-ui.2b70e2c8.js.gz +0 -0
- package/dist/web/public/styles.e87cb785.css +0 -1
- package/dist/web/public/styles.e87cb785.css.br +0 -0
- package/dist/web/public/styles.e87cb785.css.gz +0 -0
- package/dist/web/public/terminal-ui.37caa926.js +0 -3
- package/dist/web/public/terminal-ui.37caa926.js.br +0 -0
- package/dist/web/public/terminal-ui.37caa926.js.gz +0 -0
package/LICENSE
CHANGED
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 • Zero-Lag Input
|
|
8
|
+
<em>Agent Visualization • Zero-Lag Input • Mobile-First UI • Hardened Security</em>
|
|
9
|
+
</p>
|
|
10
|
+
|
|
11
|
+
<p align="center">
|
|
12
|
+
<strong>English</strong> • <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-
|
|
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-
|
|
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
|
|
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+
|
|
413
|
-
| `Ctrl+
|
|
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+
|
|
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
|
|
422
|
-
| `
|
|
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
|
|
541
|
-
| **Domain splitting** | `types.ts` →
|
|
542
|
-
| **Frontend modules** | `app.js` →
|
|
543
|
-
| **Config consolidation** | ~70 scattered magic numbers →
|
|
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)
|