@cordfuse/llmux 0.11.0 → 0.12.1

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/README.md CHANGED
@@ -1,119 +1,199 @@
1
1
  # llmux
2
2
 
3
- You have Claude Code in one terminal, Codex in another, aider in a third, and
4
- opencode in a fourth. They're all live, all mid-conversation, all costing
3
+ You have Claude Code in one terminal, Codex in another, Aider in a third, and
4
+ OpenCode in a fourth. They're all live, all mid-conversation, all costing
5
5
  nothing to keep open. But to fire a prompt at one of them you have to find the
6
- right window, click in, and type. To fire the same prompt at two of them — you
7
- just don't. And if you're on the couch with your phone? Forget it.
6
+ right window, click in, and type. To do anything from your phone? Forget it.
8
7
 
9
8
  llmux turns every agent CLI into a named tmux session you can drive from
10
- anywhere. Spawn `claude`, `agy`, `codex`, `qwen`, `opencode`, `grok`, `aider`,
11
- `goose`, and `gh copilot` once. Then fire prompts at any of them — by name,
12
- broadcast to several at once, from a REST call, a curl one-liner, or a browser
13
- terminal on your phone over Tailscale.
9
+ anywhere. Spawn `claude`, `codex`, `agy`, `gemini`, `qwen`, `opencode`, `amp`,
10
+ `grok`, `aider`, `continue`, `kiro`, `cursor`, `plandex`, `goose`, or
11
+ `gh copilot` once. Then fire prompts at any of them by name, from a CLI, from
12
+ a REST call, or from a browser on your phone over Tailscale. Past
13
+ conversations are browsable and resumable. The agents keep running.
14
14
 
15
- The agents keep running. You stop window-hopping.
16
-
17
- > **Status:** v0.2.1 — Phases 0, 1, and 4 shipped. Phases 2, 3, 5, 6, 7 pending.
18
- > See [CHANGELOG.md](./CHANGELOG.md).
15
+ > **Status:** v0.12.0 daemon + CLI client consolidated into one binary
16
+ > (`llmux`). Auth, tokens, mobile picker, conversation resume, Claude Code
17
+ > history adapter shipped. See [CHANGELOG.md](./CHANGELOG.md).
19
18
 
20
19
  ## Install
21
20
 
22
21
  ```bash
23
- # On the machine with tmux + your agent CLIs
24
- npm install -g @cordfuse/llmuxd
25
-
26
- # Anywhere you want to send prompts from (laptop, phone, CI)
22
+ # One package, one binary — installs on the daemon host AND any client machine
27
23
  npm install -g @cordfuse/llmux
28
24
  ```
29
25
 
26
+ If you used the now-deprecated `@cordfuse/llmuxd` package: uninstall it and
27
+ install `@cordfuse/llmux` instead. The `llmuxd` binary is gone; the `llmux`
28
+ binary covers both daemon and client roles.
29
+
30
30
  ## 30-second quickstart
31
31
 
32
32
  ```bash
33
- # Spawn an agent in a named tmux session
34
- llmuxd spawn claude --name main --cwd ~/projects/myapp
33
+ # 1. Start the daemon (binds REST + WebSocket + browser picker)
34
+ llmux server start --port 3030
35
+
36
+ # 2. Spawn an agent into a named tmux session
37
+ llmux session start claude --name main --cwd ~/projects/myapp
35
38
 
36
- # Fire a prompt at it — fire-and-forget
37
- llmuxd send main "what does src/index.ts do?"
39
+ # 3. Fire a prompt — fire-and-forget
40
+ llmux session prompt main "what does src/index.ts do?"
38
41
 
39
- # Or attach interactively (switch-client if you're already in tmux)
40
- llmuxd attach main
42
+ # 4. Or attach interactively (raw TTY pass-through)
43
+ llmux session attach main
41
44
 
42
- # Or expose a browser-terminal opens the session in any browser
43
- llmuxd serve
45
+ # 5. Or open the browser picker (URL is in the server start banner)
46
+ # Pick a session, get a full-screen xterm.js terminal wired over WebSocket.
44
47
  ```
45
48
 
46
- `llmuxd serve` prints reachable URLs (Local, LAN, Tailscale). Open one, pick a
47
- session, and you get a full-screen xterm.js terminal wired to your live tmux
48
- session over WebSocket. Multiple browsers can attach to the same session — tmux
49
- handles the multiplexing. On mobile, the floating toolbar gives you arrow keys,
50
- modifiers, and shell chars `gboard` hides.
49
+ On mobile the picker is a real PWA-style surface spawn / restart / kill /
50
+ edit / resume past conversations, with a confirmation modal on destructive
51
+ actions. The chat page is a phone-friendly xterm with a custom soft-keyboard
52
+ toolbar that surfaces Esc / Tab / Ctrl / Alt / arrows / shell chars that
53
+ gboard hides.
51
54
 
52
- > **Auth:** `serve` runs without authentication today. Phase 3 lands SAS tokens.
53
- > Until then, bind to `127.0.0.1` (default) or expose only over Tailscale.
55
+ ## Remote operation
54
56
 
55
- ## How it works
57
+ The same binary is the client. Set `--server` (or `LLMUX_SERVER` env) on any
58
+ session/agent verb and it routes over HTTP instead of operating locally:
56
59
 
57
- Two packages:
60
+ ```bash
61
+ export LLMUX_SERVER=http://100.105.221.46:3030
62
+ export LLMUX_TOKEN=sas_… # mint with `llmux token create`
58
63
 
59
- | Package | Where it runs | What it does |
60
- |---|---|---|
61
- | `@cordfuse/llmuxd` | The machine with tmux | Daemon: session management, REST API, web terminal |
62
- | `@cordfuse/llmux` | Anywhere | Thin HTTP client no tmux dependency |
64
+ llmux session list
65
+ llmux session prompt main "tomorrow's plan?"
66
+ llmux session attach main # raw TTY pass-through over WS
67
+ llmux session resume main --latest # rebind to the most recent claude convo
68
+ ```
69
+
70
+ Localhost requests bypass auth; remote requests require a Bearer token.
71
+ `--token <sas>` per-command works too.
63
72
 
64
- Each spawned agent is a real tmux session, not a wrapped PTY. llmuxd dispatches
65
- input via `tmux send-keys` and reads output by attaching xterm.js over a
66
- WebSocket bridge. That keeps the agent CLIs unmodified — Claude Code is still
67
- running Claude Code; llmuxd just coordinates input and exposes the surface.
73
+ ## Noun-prefix surface
68
74
 
69
- Session metadata lives at `$XDG_STATE_HOME/llmuxd/sessions.json` (default
70
- `~/.local/state/llmuxd/sessions.json`, `0600` perms, versioned schema).
71
- Reconciliation is on demand — sessions can die outside llmuxd, and `status`
72
- reports live tmux state.
75
+ ```
76
+ session list / start / stop / restart / attach / prompt / broadcast
77
+ / resume / history
78
+ server start
79
+ token create / list / revoke
80
+ agent list [--all] [--installed] [--json]
81
+ ```
73
82
 
74
- The daemon runs on Node (not Bun) because `node-pty`'s native prebuilds target
75
- Node; Bun caused immediate SIGHUP on the PTY child.
83
+ Global flags: `--server <url>`, `--token <sas>`, `--help`, `--version`.
84
+
85
+ Backward-compat shims (kept one release): `llmux serve`, `llmux ls`,
86
+ `llmux status`, and the legacy flat verbs (`llmux send`, `llmux spawn`,
87
+ `llmux kill`, etc.) still work; they fall through to the noun-prefix
88
+ dispatcher.
89
+
90
+ ## How it works
91
+
92
+ Each spawned agent is a real tmux session, not a wrapped PTY. The daemon
93
+ dispatches input via `tmux send-keys` and exposes the surface over a REST API
94
+ plus a WebSocket bridge to xterm.js (via node-pty attached to
95
+ `tmux attach -t <name>`). That keeps the agent CLIs unmodified — Claude Code
96
+ is still running Claude Code; llmux just coordinates input and exposes the
97
+ surface.
98
+
99
+ State lives at `~/.local/state/llmuxd/sessions.json` (or
100
+ `$XDG_STATE_HOME/llmuxd/sessions.json`) with `0600` perms and a versioned
101
+ schema. Auth tokens live in the sibling `auth.json`. The state directory keeps
102
+ its `llmuxd/` name across the v0.12.0 package consolidation so existing
103
+ operators don't need to migrate anything.
104
+
105
+ The daemon runs on Node (not Bun) — `node-pty`'s native prebuilds target
106
+ Node, and attaching to tmux through node-pty under Bun caused immediate SIGHUP.
76
107
 
77
108
  ## Supported agents
78
109
 
79
- | Session key | CLI |
80
- |---|---|
81
- | `claude` | [Claude Code](https://github.com/anthropics/claude-code) |
82
- | `agy` | [Antigravity CLI](https://antigravity.dev) |
83
- | `codex` | [OpenAI Codex CLI](https://github.com/openai/codex) |
84
- | `qwen` | [Qwen Code](https://github.com/QwenLM/qwen-code) |
85
- | `opencode` | [opencode](https://opencode.ai) |
86
- | `grok` | [Grok Build CLI](https://x.ai) |
87
- | `aider` | [aider](https://aider.chat) |
88
- | `goose` | [Goose](https://block.github.io/goose/) |
89
- | `copilot` | [GitHub Copilot CLI](https://github.com/github/gh-copilot) (via `gh` extension) |
90
-
91
- Only installed agents are spawnable. llmuxd uses `command -v` (and
92
- `gh extension list` for copilot) to detect availability.
110
+ | Key | CLI | Danger-mode default |
111
+ |---|---|---|
112
+ | `claude` | [Claude Code](https://docs.claude.com/en/docs/claude-code/overview) | `--dangerously-skip-permissions` |
113
+ | `codex` | [OpenAI Codex CLI](https://github.com/openai/codex) | `--dangerously-bypass-approvals-and-sandbox` |
114
+ | `agy` | [Antigravity CLI](https://antigravity.google) | `--dangerously-skip-permissions` |
115
+ | `gemini` | [Gemini CLI](https://github.com/google-gemini/gemini-cli) | `--yolo` |
116
+ | `qwen` | [Qwen Code](https://github.com/QwenLM/qwen-code) | `--yolo` |
117
+ | `opencode` | [OpenCode](https://opencode.ai) | env: `OPENCODE_YOLO=1` (TUI lacks a flag) |
118
+ | `amp` | [Sourcegraph Amp](https://ampcode.com) | `--dangerously-allow-all` |
119
+ | `grok` | [Grok Build CLI](https://x.ai/cli) | `--always-approve` |
120
+ | `aider` | [Aider](https://aider.chat) | `--yes-always` |
121
+ | `continue` | [Continue CLI](https://docs.continue.dev/guides/cli) (`cn`) | `--auto` |
122
+ | `kiro` | [Kiro CLI](https://kiro.dev/cli/) | `--trust-all-tools` |
123
+ | `cursor` | [Cursor CLI](https://cursor.com/docs/cli/installation) (`cursor-agent`) | (config-based) |
124
+ | `plandex` | [Plandex](https://plandex.ai) | (interactive `set-auto`) |
125
+ | `goose` | [Goose](https://block.github.io/goose) | env: `GOOSE_MODE=auto` |
126
+ | `copilot` | [GitHub Copilot CLI](https://docs.github.com/en/copilot/how-tos/use-copilot-in-the-cli) (`gh copilot`) | n/a |
127
+
128
+ Only installed agents appear in `llmux agent list` and the picker dropdown.
129
+ Detection uses a pure-Node PATH walk for most; `copilot` checks the gh-managed
130
+ binary directory.
131
+
132
+ Per-session overrides via `llmux session start <agent>`:
133
+ - `--name <X>` — tmux session name (defaults to the agent key)
134
+ - `--cwd <path>` — working directory (accepts `~/…` shorthand)
135
+ - `--flags "<f>"` — replace the agent's default flags entirely
136
+ - `--env "KEY=VAL"` — extra env vars (newline-separated for multiple)
137
+
138
+ Editing any of these on a running session via the web picker auto-respawns
139
+ the tmux session so changes take effect immediately.
140
+
141
+ ## Conversation resume
142
+
143
+ For agents with a history adapter (Claude Code today; codex/gemini/etc.
144
+ coming), the row gets a `☰ N` button. Tap it to see past conversations in the
145
+ session's cwd; pick one to relaunch the agent with its `--resume <id>` flag.
146
+ State preserves the binding across restarts so respawn keeps you on the
147
+ same conversation. Use `llmux session resume <name> --latest` from the CLI
148
+ for the same flow.
149
+
150
+ ## Auth
151
+
152
+ `llmux server start` runs without auth until you create a token:
153
+
154
+ ```bash
155
+ llmux token create --name phone
156
+ # prints sas_…<43-char-base64url> once; copy it.
157
+ # pass --qr-endpoint tailscale-https for a QR-code deep-link that logs you
158
+ # in on first scan from a phone.
159
+
160
+ llmux token list
161
+ llmux token revoke <8-char-id>
162
+ ```
163
+
164
+ After the first token exists, all non-localhost HTTP/WS requests require
165
+ either `Authorization: Bearer <sas>` (CLI / curl) or the `llmuxd_token`
166
+ cookie set by the browser gate. Localhost stays open so local CLI use needs
167
+ no token.
168
+
169
+ If `tailscale serve --https=443 http://localhost:<port>` is configured on the
170
+ host, the server-start banner surfaces the HTTPS hostname URL above the
171
+ http endpoints. The browser picker is a clean TLS surface; CLI `attach`
172
+ currently speaks ws:// only.
93
173
 
94
174
  ## Config (`.llmux.yaml`)
95
175
 
96
- llmuxd looks for config in this order (highest priority first):
176
+ A YAML config (project-local or global) can override per-agent defaults.
177
+ Discovery order:
97
178
 
98
179
  1. `--config <path>` flag
99
- 2. `./.llmux.yaml` (project-level, auto-discovered in cwd)
180
+ 2. `./.llmux.yaml` (project-local, auto-discovered in cwd)
100
181
  3. `~/.config/llmux/config.yaml` (global default)
101
182
  4. `LLMUX_CONFIG=<path>` env var
102
183
 
103
- All config has sensible defaultsllmuxd runs without any YAML file.
104
-
105
- See [docs/config.md](./docs/config.md) (forthcoming) for the full schema.
184
+ llmux runs without any YAML file all defaults are baked into
185
+ `agents.ts`. The `init` command to generate a starter YAML is not yet
186
+ shipped; create one by hand if you want to override defaults today.
106
187
 
107
- ## Build phases
188
+ ## Environment
108
189
 
109
- - [x] **Phase 0** — scaffold, CLI stubs *(v0.0.1)*
110
- - [x] **Phase 1** — spawn / send / broadcast / chat / kill / status *(v0.1.0)*
111
- - [ ] **Phase 2** `.llmux.yaml` config + `llmuxd init`
112
- - [ ] **Phase 3** — REST API + `llmux` HTTP client + SAS tokens
113
- - [x] **Phase 4** web terminal (xterm.js + node-pty + WebSocket) + mobile UX *(v0.2.0–v0.2.1)*
114
- - [ ] **Phase 5** QR codes + serve UX + service templates (systemd/launchd)
115
- - [ ] **Phase 6** agent-initiated spawning (`LLMUX_SERVER` / `LLMUX_TOKEN` auto-inject)
116
- - [ ] **Phase 7** — polish + npm publish
190
+ | Variable | Purpose |
191
+ |---|---|
192
+ | `LLMUX_SERVER` | Default `--server` URL for session/agent verbs |
193
+ | `LLMUX_TOKEN` | Default `--token` SAS auth |
194
+ | `LLMUX_PORT` | Default port resolution for QR-endpoint helpers |
195
+ | `XDG_STATE_HOME` | Override for the state directory parent |
196
+ | `OPENCODE_YOLO`, `GOOSE_MODE`, | Forwarded by `envDefaults` per-agent |
117
197
 
118
198
  ## License
119
199