@cordfuse/crosstalk 7.0.0-alpha.8 → 7.0.0-beta.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.
Files changed (72) hide show
  1. package/GUIDE-CLI.md +322 -0
  2. package/GUIDE-PROMPTS.md +118 -0
  3. package/LICENSE +21 -0
  4. package/README.md +402 -61
  5. package/bin/crosstalk.js +88 -54
  6. package/commands/agent.js +69 -0
  7. package/commands/auth.js +273 -0
  8. package/commands/channel.js +54 -44
  9. package/commands/chat.js +107 -71
  10. package/commands/daemon.js +120 -0
  11. package/commands/logs.js +108 -19
  12. package/commands/message.js +125 -0
  13. package/commands/server.js +153 -0
  14. package/commands/settings.js +49 -0
  15. package/commands/status.js +37 -13
  16. package/commands/token.js +136 -0
  17. package/commands/transport.js +270 -0
  18. package/commands/version.js +3 -3
  19. package/commands/workflow.js +234 -0
  20. package/deploy/crosstalk@.service +62 -0
  21. package/deploy/install.sh +82 -0
  22. package/lib/api-client.js +77 -22
  23. package/lib/credentials.js +207 -0
  24. package/lib/nativeServer.js +173 -0
  25. package/lib/resolve.js +101 -34
  26. package/package.json +27 -4
  27. package/src/activation.ts +104 -0
  28. package/src/api.ts +1716 -0
  29. package/src/auth/enforce.ts +68 -0
  30. package/src/auth/handlers.ts +266 -0
  31. package/src/auth/middleware.ts +132 -0
  32. package/src/auth/setup.ts +263 -0
  33. package/src/auth/tokens.ts +285 -0
  34. package/src/auth/users.ts +267 -0
  35. package/src/dispatch.ts +492 -0
  36. package/src/dispatchers.ts +91 -0
  37. package/src/filenames.ts +28 -0
  38. package/src/frontmatter.ts +26 -0
  39. package/src/init.ts +116 -0
  40. package/src/invoke.ts +201 -0
  41. package/src/log-buffer.ts +67 -0
  42. package/src/models.ts +283 -0
  43. package/src/resolve.ts +100 -0
  44. package/src/state.ts +190 -0
  45. package/src/stop.ts +37 -0
  46. package/src/transport.ts +243 -0
  47. package/src/web/auth-pages.ts +160 -0
  48. package/src/web/channels.ts +395 -0
  49. package/src/web/chat-page.ts +636 -0
  50. package/src/web/chat-pty.ts +254 -0
  51. package/src/web/dashboard.ts +129 -0
  52. package/src/web/layout.ts +237 -0
  53. package/src/web/stubs.ts +510 -0
  54. package/src/web/workflows.ts +490 -0
  55. package/src/workflow.ts +470 -0
  56. package/template/CLAUDE.md +10 -0
  57. package/template/CROSSTALK-VERSION +1 -0
  58. package/template/CROSSTALK.md +262 -0
  59. package/template/PROTOCOL.md +70 -0
  60. package/template/README.md +64 -0
  61. package/template/auth/.gitkeep +0 -0
  62. package/template/auth/README.md +224 -0
  63. package/template/data/crosstalk.yaml +196 -0
  64. package/template/gitignore +4 -0
  65. package/commands/down.js +0 -40
  66. package/commands/init.js +0 -243
  67. package/commands/pull.js +0 -22
  68. package/commands/replies.js +0 -40
  69. package/commands/restart.js +0 -29
  70. package/commands/rm.js +0 -109
  71. package/commands/run.js +0 -122
  72. package/commands/up.js +0 -135
package/GUIDE-CLI.md ADDED
@@ -0,0 +1,322 @@
1
+ # Crosstalk CLI Guide
2
+
3
+ Reference for the `crosstalk` CLI. Run `crosstalk <noun> --help` (or `crosstalk <noun> <verb> --help`) for inline flags.
4
+
5
+ Requires: Node.js ≥ 20 + git on PATH. alpha.18 is a single-package install — `npm install -g @cordfuse/crosstalk`. The daemon lives as `crosstalk daemon …` inside the same package; there's no separate `crosstalkd` binary anymore.
6
+
7
+ The surface is strict **noun-verb**, mirroring [`@cordfuse/llmux`](https://www.npmjs.com/package/@cordfuse/llmux):
8
+
9
+ | Noun | Verbs |
10
+ |---|---|
11
+ | `auth` | `login` · `logout` · `whoami` · `list` · `use` |
12
+ | `token` | `create` · `list` · `revoke` · `rename` |
13
+ | `server` | `start` · `stop` · `restart` · `status` · `logs` |
14
+ | `transport` | `init` · `rm` |
15
+ | `channel` | `list` · `create` · `rename` · `delete` |
16
+ | `message` | `send` · `replies` |
17
+ | `workflow` | `compose` · `run` · `status` |
18
+ | `chat` | `<agent>` (positional) · `--shell` |
19
+ | `agent` | `list` |
20
+ | `logs` | `list` · `tail` |
21
+ | `settings` | `show` |
22
+ | `daemon` | `dispatch` · `init` · `stop` (internal — spawned by `server start` + systemd) |
23
+ | `status` | (no verb — transport-level snapshot) |
24
+ | `version` | (no verb — print client + engine versions) |
25
+
26
+ **Addressing.** Each transport on the machine is identified by a name — the operator picks it at `crosstalk transport init` (default: `crosstalk`). Every verb that operates on an existing transport takes an optional `--containername <name>` flag (or `-c <name>`).
27
+
28
+ ```sh
29
+ crosstalk transport init # default 'crosstalk' transport
30
+ crosstalk transport init --containername uat # second transport 'uat'
31
+ crosstalk transport init -c prod --remote git@... # third, with upstream at init
32
+ ```
33
+
34
+ **Profiles.** The CLI holds credentials for multiple engines (e.g. local loopback + hosted prod) at `~/.config/crosstalk/credentials.json`. `--profile <name>` overrides the active profile per-invocation; `--server <url>` overrides the target server URL when logging in. See [Auth](#auth).
35
+
36
+ ---
37
+
38
+ ## Transport
39
+
40
+ ### `crosstalk transport init [--containername <name>] [--remote <url>]`
41
+
42
+ Scaffold a new transport on this machine (or repair an incomplete one — phases are independent and idempotent).
43
+
44
+ `<base>` defaults to system mode (`/var/lib/crosstalk`, runs as the `crosstalk` service user). Set `CROSSTALK_USER_MODE=1` to switch to user mode:
45
+ - Linux: `$XDG_DATA_HOME/crosstalk/` (= `~/.local/share/crosstalk/` if unset)
46
+ - macOS: `~/Library/Application Support/crosstalk/`
47
+ - Windows: `%LOCALAPPDATA%\crosstalk\`
48
+
49
+ Mechanics: copies the template into `<base>/<name>/transport/` (via `crosstalk daemon init`), `git init --initial-branch=main` + initial commit, allocates a free API port (`crosstalk` default → 7000; named transports search from 7001), records the port at `<base>/<name>/api-port`.
50
+
51
+ ```sh
52
+ crosstalk transport init
53
+ # → Transport 'crosstalk' ready
54
+ # → api port: 7000 (allocated)
55
+
56
+ crosstalk transport init --containername uat --remote git@github.com:me/transport.git
57
+ # → Transport 'uat' ready
58
+ # → api port: 7001 (allocated)
59
+ # → remote: git@github.com:me/transport.git (added)
60
+ ```
61
+
62
+ ### `crosstalk transport rm [--containername <name>] [--force]`
63
+
64
+ Full teardown: stops the engine (if running), then deletes the entire `<base>/<name>/` tree (transport git repo, dispatcher state, pid/log/port files). Prompts with an explicit enumeration of what gets deleted; `--force` / `-f` skips for scripted use. **Cannot undo — all message history is lost.**
65
+
66
+ ---
67
+
68
+ ## Server (engine lifecycle)
69
+
70
+ User mode (`CROSSTALK_USER_MODE=1`): the engine runs as a detached host process owned by the operator. PID at `<base>/<name>/crosstalk-state/crosstalk.pid`, log at `<base>/<name>/crosstalk-state/crosstalk.log`.
71
+
72
+ System mode (default): the engine runs as the `crosstalk` service user under systemd. The `crosstalk server` verbs in this mode print a hint redirecting to `sudo systemctl <verb> crosstalk@<name>` — that's the right lifecycle when systemd owns the process.
73
+
74
+ ### `crosstalk server start [--containername <name>]`
75
+
76
+ Spawn the engine (`crosstalk daemon dispatch …`) as a detached host process for the named transport. Brief 150ms liveness check catches immediate spawn failures (broken tsx resolution, missing transport dir) before returning success. Output includes the PID + the API loopback URL.
77
+
78
+ ### `crosstalk server stop [--containername <name>]`
79
+
80
+ SIGTERM the running engine. SIGKILL after a 5s grace if it doesn't shut down cleanly. Idempotent — reports `was not running` and exits 0 if there's no live PID.
81
+
82
+ ### `crosstalk server restart [--containername <name>]`
83
+
84
+ Stop + start. State at `<base>/<name>/` is preserved across the restart.
85
+
86
+ ### `crosstalk server status [--containername <name>] [--probe]`
87
+
88
+ Reports PID + API port + uptime (Linux only). With `--probe`, also pings `/healthz` on the API loopback.
89
+
90
+ ### `crosstalk server logs [--containername <name>] [-f|--follow]`
91
+
92
+ Tails `<base>/<name>/crosstalk-state/crosstalk.log`. Last 200 lines by default; `-f` follows.
93
+
94
+ ---
95
+
96
+ ## Auth
97
+
98
+ The engine enforces bearer-token auth on every operational endpoint. Once the engine is up:
99
+
100
+ 1. Visit the `/setup?token=…` URL printed at engine boot to create the first admin user (one-time web wizard).
101
+ 2. Run `crosstalk auth login` — interactive prompts for username + passphrase. The engine returns a bearer token; the CLI stores it as the `default` profile in `~/.config/crosstalk/credentials.json` (mode 0600). All subsequent CLI calls send `Authorization: Bearer …` automatically.
102
+
103
+ `/healthz` and `/version` stay open as monitoring probes; everything else needs a valid token.
104
+
105
+ ### `crosstalk auth login [--server <url>] [--username <name>] [--passphrase <pp>] [--profile <name>]`
106
+
107
+ Prompts interactively if either credential flag is omitted (no-echo passphrase). Saves a profile in credentials.json and sets it active. `--profile` defaults to `default`; pass a different name to keep multiple profiles side-by-side (one CLI can talk to several engines). `--server` records the engine URL for the profile (default: `http://127.0.0.1:7000`).
108
+
109
+ ### `crosstalk auth logout [--profile <name>] [--no-revoke]`
110
+
111
+ Best-effort revocation via `POST /api/auth/logout` + removes the active profile from credentials.json. `--no-revoke` skips the server-side call (useful when the engine is offline). `--profile` targets a specific profile instead of the active one.
112
+
113
+ ### `crosstalk auth whoami [--profile <name>]`
114
+
115
+ Prints username / display name / role / createdAt from `GET /api/account`. Exits 1 if not logged in.
116
+
117
+ ### `crosstalk auth list`
118
+
119
+ Tabular list of saved profiles with their server URL + username + active marker.
120
+
121
+ ```
122
+ PROFILE USERNAME SERVER
123
+ * default stevekrisjanovs http://127.0.0.1:7000
124
+ prod ops https://crosstalk.cordfuse.io
125
+ ```
126
+
127
+ ### `crosstalk auth use <profile>`
128
+
129
+ Switch the active profile. Subsequent commands use that profile's server + token until you switch again (or pass `--profile <other>` per-invocation).
130
+
131
+ ---
132
+
133
+ ## Token
134
+
135
+ API tokens for non-CLI clients (CI, scripts, HTTP). The CLI's own bearer lives in the credentials profile from `auth login` — `token` operations are for additional tokens you want to hand out.
136
+
137
+ ### `crosstalk token list`
138
+
139
+ Lists your own tokens (id, name, created-rel-time, last-used-rel-time, expires if set). You only ever see tokens you own.
140
+
141
+ ### `crosstalk token create <name>`
142
+
143
+ Creates a new bearer token. The plaintext secret is printed once; copy it immediately for use in non-CLI contexts (HTTP clients, CI). The CLI does NOT swap to the new token — that's `auth login`.
144
+
145
+ ### `crosstalk token revoke <tokenId>`
146
+
147
+ Revokes a token by id (use `token list` to find ids). Engine refuses to revoke tokens you don't own.
148
+
149
+ ### `crosstalk token rename <tokenId> --name <label>`
150
+
151
+ Renames an existing token's label. Ownership-checked.
152
+
153
+ ---
154
+
155
+ ## Channel
156
+
157
+ All channel operations talk to the engine's HTTP API on `127.0.0.1:<port>` (or the active profile's `server` URL for remote engines).
158
+
159
+ ### `crosstalk channel list`
160
+
161
+ Lists every channel on the transport with its UUID + name + optional parent.
162
+
163
+ ### `crosstalk channel create <name>`
164
+
165
+ Creates a new top-level channel.
166
+
167
+ ### `crosstalk channel rename <handle> <new-name>`
168
+
169
+ Renames a channel. `<handle>` is either the current name or the UUID.
170
+
171
+ ### `crosstalk channel delete <handle>`
172
+
173
+ Deletes a channel. The CLI resolves the channel's current name first and passes it as the typed-confirmation token — the verb itself is the operator's explicit consent.
174
+
175
+ ---
176
+
177
+ ## Message
178
+
179
+ ### `crosstalk message send --to <model>[@<machine>] [--as <persona>] [--fanout <n>] [--channel <name|uuid>] [--from <name>] <body|file|->`
180
+
181
+ Write a primitive sub-message. `<body>` can be an inline string, a file path, or `-` (stdin).
182
+
183
+ ```sh
184
+ crosstalk message send --to sonnet "summarise CROSSTALK.md"
185
+ crosstalk message send --to sonnet --fanout 3 --as junior-developer "draft a release codename"
186
+ crosstalk message send --to opus@cachy --channel mctest "review these drafts" < drafts.md
187
+ ```
188
+
189
+ Flags:
190
+ - `--to <model>[@<machine>]` (required) — model identity in qualified `<provider>/<model>` form (or a bare model name when claimed uniquely); optional `@machine` for scoped routing. See `data/crosstalk.yaml`.
191
+ - `--fanout <n>` — dispatch N identical sub-primitives in parallel (each becomes a separate worker reply)
192
+ - `--as <persona>` — invoke the model with `local/actors/<persona>.md` prepended as system prompt
193
+ - `--channel <name|uuid>` — explicit channel (default: auto-pick if exactly one exists)
194
+ - `--from <name>` — override the `from:` identity
195
+
196
+ ### `crosstalk message replies <relPath>...`
197
+
198
+ Poll reply status for one or more dispatched messages. Exits 0 when every target is REPLIED or FAILED, exit 2 while anything is PENDING — agents can poll cheaply in a loop.
199
+
200
+ ```sh
201
+ crosstalk message replies 2026/06/13/130218231Z-15387115.md
202
+ # → REPLIED 2026/06/13/130218231Z-15387115.md <- sonnet@laptop (2026/06/13/130218252Z-5f54c697.md)
203
+ ```
204
+
205
+ ---
206
+
207
+ ## Workflow
208
+
209
+ ### `crosstalk workflow compose <prompt> [--channel <name|uuid>] [--compiler <model>]`
210
+
211
+ Interactive: engine compiles `<prompt>` into a workflow plan, prints the YAML for review, then prompts `[y]es / [e]dit / [n]o`. Choosing `e` opens `$VISUAL` / `$EDITOR` / `vi` on a temp file; on save the edited YAML is reviewed again. On `y`, the plan is submitted.
212
+
213
+ ```sh
214
+ crosstalk workflow compose "Fan out 3 sonnet drafts. Have opus pick the strongest."
215
+ ```
216
+
217
+ `--compiler <model>` overrides the default compiler agent (the first claimed model otherwise).
218
+
219
+ ### `crosstalk workflow run <file> [--channel <name|uuid>] [--from <name>]`
220
+
221
+ Submit an already-authored workflow YAML (or markdown body) file. The runtime handles execution end-to-end: compile pass (prose → JSON plan) → fanout → synthesize → route. See [transport/CROSSTALK.md § Workflows](transport/CROSSTALK.md#workflows) for the protocol.
222
+
223
+ ```sh
224
+ crosstalk workflow run workflows/review-and-synthesize.md
225
+ ```
226
+
227
+ ### `crosstalk workflow status [--id <childUuid>]`
228
+
229
+ Without `--id`: tabular list of every workflow on the transport — child uuid prefix, parent channel name, phase, fanout completion ratio.
230
+
231
+ With `--id <childUuid>`: detailed snapshot of one workflow (uuid, parent, marker path, phase, fanout/synth state, complete flag).
232
+
233
+ ---
234
+
235
+ ## Chat (interactive PTY)
236
+
237
+ ### `crosstalk chat <agent> [--cwd <path>]`
238
+
239
+ Spawn an interactive agent CLI as a foreground child of the operator's shell. Supported agents: `claude`, `codex`, `gemini`, `qwen`, `opencode`, `agy`.
240
+
241
+ `<agent>` is required (the host may have multiple agent CLIs installed; operator picks explicitly). `--cwd <path>` chdir's the child before exec — useful for pinning the session to a specific project root.
242
+
243
+ **Lifecycle:** agent owns stdin/stdout/stderr while running. When the operator exits the agent (Ctrl-D / `/quit` / agent finishes), the child is reaped and `crosstalk chat` exits with the same status. There is no persistent live agent — crosstalk is async-by-design, no detach/reattach model. SIGINT/SIGTERM are forwarded for clean shutdown; defensive SIGKILL fallback on the rare case where an agent CLI forks a holding subprocess.
244
+
245
+ Auth setup is per-agent and lives in `data/crosstalk.yaml`'s per-provider `env_file:` (env-injected at dispatch spawn) plus the agent's own one-time login command (e.g. `codex login --with-api-key`). Recipes in `transport/auth/README.md`.
246
+
247
+ ```sh
248
+ crosstalk chat claude
249
+ crosstalk chat codex --cwd ~/Repos/myproject
250
+ ```
251
+
252
+ ### `crosstalk chat --shell`
253
+
254
+ Drop into your `$SHELL` (or bash if unset) — useful for one-time setup commands. No agent positional needed.
255
+
256
+ ```sh
257
+ crosstalk chat --shell
258
+ npm install -g @anthropic-ai/claude-code
259
+ exit
260
+ ```
261
+
262
+ **After installing a new CLI**, run `crosstalk server restart` so the dispatcher rescans PATH and claims it. The dispatcher reads PATH only at startup; CLIs installed while the engine is running don't appear in `claimed_models` until the next restart. `crosstalk status` will say so explicitly.
263
+
264
+ ---
265
+
266
+ ## Agent / Logs / Settings
267
+
268
+ These three nouns surface engine introspection that mirrors what the web UI shows on `/agents`, `/logs`, and `/settings`.
269
+
270
+ ### `crosstalk agent list [--installed] [--json]`
271
+
272
+ Catalog of agent CLIs on this host. Default columns: `name`, `installed` (on PATH yes/no), `yaml` (referenced in `data/crosstalk.yaml`), `claimed` (engine has at least one claimed model on this CLI). `--installed` filters to only the present ones. `--json` for raw JSON.
273
+
274
+ ### `crosstalk logs list [--limit N] [--json]`
275
+
276
+ Snapshot of recent engine log entries (the structured event stream — same source as the `/logs` web page). `--limit N` trims to the last N entries; `--json` emits raw JSON instead of one human line per entry.
277
+
278
+ ### `crosstalk logs tail [--since <iso>]`
279
+
280
+ Live SSE stream — Ctrl-C to stop. `--since <iso>` replays everything newer than the given ISO-8601 timestamp before switching to live updates.
281
+
282
+ ### `crosstalk settings show [--json]`
283
+
284
+ Current engine settings snapshot: alias, version, transportRoot, claimedModels, apiPort, pollSeconds.
285
+
286
+ ---
287
+
288
+ ## Meta
289
+
290
+ ### `crosstalk status [--containername <name>]`
291
+
292
+ Prints transport name, host storage path (escape hatch for power users who want to poke around with raw git), engine alias + version, claimed models, dispatch heartbeat + age, cursor, channel list, errors-logged count.
293
+
294
+ ### `crosstalk version`
295
+
296
+ Prints client + engine versions side-by-side. Engine is queried over the HTTP API; reports `(unreachable)` if the engine isn't running.
297
+
298
+ Version skew (client and engine on different versions) triggers a `[WARN]` block to stderr on the first API call. Fix by `npm install -g @cordfuse/crosstalk` to update. One-shot per process.
299
+
300
+ ---
301
+
302
+ ## Environment variables
303
+
304
+ | Env | Default | Effect |
305
+ |---|---|---|
306
+ | `CROSSTALK_USER_MODE` | unset (system mode) | Set to `1` for user mode — engine runs as the operator, paths under the operator's home. |
307
+ | `CROSSTALK_API_PORT` | `7000` | Engine HTTP port. Honored by both the CLI (when talking to a non-default loopback) and the engine itself (when binding). |
308
+ | `CROSSTALK_API_BIND` | `127.0.0.1` | Engine bind address. Loopback by default; only change if you understand what you're exposing. |
309
+ | `CROSSTALK_ALIAS` | `<transport-name>` | Override the dispatcher's machine identity in the bus. |
310
+ | `DISPATCH_POLL_SECONDS` | `30` | Engine main-loop tick interval. |
311
+ | `XDG_CONFIG_HOME` | per-OS default | Where `credentials.json` lives. |
312
+ | `XDG_DATA_HOME` | per-OS default | Where transport storage lives (user mode). |
313
+ | `VISUAL` / `EDITOR` | `vi` | Used by `workflow compose` when editing the YAML preview. |
314
+
315
+ ---
316
+
317
+ ## Where to go next
318
+
319
+ - Protocol spec: [transport/CROSSTALK.md](transport/CROSSTALK.md)
320
+ - Natural-language pattern (agent drives crosstalk for you): [GUIDE-PROMPTS.md](GUIDE-PROMPTS.md)
321
+ - alpha.18 design rationale + full old→new migration table: [V8-CLI-ALIGN.md](V8-CLI-ALIGN.md)
322
+ - Architecture overview: [README.md](README.md)
@@ -0,0 +1,118 @@
1
+ # Crosstalk Natural-Language Guide
2
+
3
+ You don't have to memorise the `crosstalk` CLI to use Crosstalk. You can just **talk to it.**
4
+
5
+ The interactive Crosstalk pattern: **`crosstalk chat <agent>`** spawns the named agent CLI as a foreground process attached to your terminal. The transport's `PROTOCOL.md` orients the agent — it learns the layout, the six core nouns, and which `crosstalk` commands it can run on your behalf. From there you speak in plain language; the agent translates into commands, waits for answers, and tells you what came back.
6
+
7
+ `<agent>` is required (positional) — the host may have multiple agent CLIs installed, and there's no implicit default. When you exit the agent (Ctrl-D / `/quit` / agent finishes), the process is gone — crosstalk is async-by-design, no persistent live agent.
8
+
9
+ ```sh
10
+ crosstalk chat claude
11
+ > ask sonnet on cachy to summarise report.md
12
+ ```
13
+
14
+ The agent CLI owns your terminal while running; Crosstalk owns the bus on disk; they meet at the transport git repo.
15
+
16
+ > **New to Crosstalk?** The [main README](README.md) has the six-word glossary (Transport / Machine / Message / Model / Actor / Channel) plus a local-only quickstart. Worth a 60-second read first.
17
+
18
+ This is the companion to the **[CLI guide](GUIDE-CLI.md)**. Same system, two front doors: type commands, or just speak.
19
+
20
+ > The natural-language interface is **agent-agnostic**, like the rest of Crosstalk. Whatever coding agent you already run — Claude Code, Codex, Gemini, Qwen Code, opencode, Antigravity — can be your interactive front door, as long as it can read `PROTOCOL.md` and run shell commands.
21
+
22
+ ---
23
+
24
+ ## Starting an interactive session
25
+
26
+ ```sh
27
+ crosstalk chat claude # or: crosstalk chat codex, crosstalk chat gemini, ...
28
+ ```
29
+
30
+ This spawns the named agent CLI as a foreground child of your shell — the agent owns stdin/stdout/stderr while running. Use `--cwd <path>` to pin the session to a specific project root if your agent needs the transport's `PROTOCOL.md` and `CLAUDE.md` for cwd-based orientation.
31
+
32
+ You don't need to teach the agent anything. Start talking.
33
+
34
+ > **Interactive ≠ being a model.** When you're talking to the agent this way, *you* (through the agent) are the human's front door. You are not a model in the bus and you do not process incoming messages. The engine (started via `crosstalk server start` or systemd) handles incoming traffic via its internal `crosstalk daemon dispatch` loop. Don't start a second dispatcher from inside the chat session — it would compete with the one already running.
35
+
36
+ ---
37
+
38
+ ## The phrasebook
39
+
40
+ Say it however feels natural; these are the intents the interactive agent recognises and the commands it runs on your behalf. There's one CLI — `crosstalk` — and it talks to the engine over HTTP. The daemon lives as `crosstalk daemon …` inside the same binary but is internal; the agent never invokes it directly.
41
+
42
+ | You say… | What the agent does |
43
+ |---|---|
44
+ | "ask sonnet to summarise `report.md`" | `crosstalk message send --to sonnet "..."`, polls with `crosstalk message replies <path>`, surfaces the reply |
45
+ | "ask sonnet on cachy to look for typos" | `crosstalk message send --to sonnet@cachy "..."`, waits, reports back |
46
+ | "fan out three drafts running sonnet" | `crosstalk message send --to sonnet --fanout 3 "..."`, surfaces all three replies when they arrive |
47
+ | "in the *sprint-42* channel, ask opus to plan the work" | adds `--channel sprint-42` to the `message send` |
48
+ | "run this workflow" (with file path) | `crosstalk workflow run <file>` — the runtime auto-creates a child channel and runs compile → fanout → synthesize → route deterministically |
49
+ | "fan out three drafts then have opus pick one" (free-form prose) | `crosstalk workflow compose "<your prose>"` — the engine compiles, surfaces the YAML plan for your `[y]es / [e]dit / [n]o` review, then dispatches |
50
+ | "how's that workflow going?" / "show the workflow status" | `crosstalk workflow status` (all) or `--id <childUuid>` for a specific one |
51
+ | "is the dispatcher alive?" / "check status" | `crosstalk server status --probe` (local lifecycle) or `crosstalk status` (transport snapshot — heartbeat, channels, claimed models) |
52
+ | "what failed?" | scans the current channel for `failed: true` replies and summarises |
53
+ | "make a channel called *release-7*" | `crosstalk channel create release-7`, tells you the UUID |
54
+ | "what channels exist?" | `crosstalk channel list` |
55
+ | "rename this channel to *release-8*" | `crosstalk channel rename <current> release-8` |
56
+ | "delete the *batch-old* channel" | `crosstalk channel delete batch-old` (the verb is your explicit consent — no extra typed confirmation needed) |
57
+ | "what agent CLIs are installed here?" | `crosstalk agent list` |
58
+ | "show the recent engine logs" / "tail the logs" | `crosstalk logs list` (snapshot) or `crosstalk logs tail` (live SSE) |
59
+ | "what's the engine configured with?" | `crosstalk settings show` |
60
+ | "add a new model called fable" | edits `data/crosstalk.yaml`, commits, then `crosstalk server restart` so the dispatcher rescans PATH and claims it |
61
+ | "pull the latest" | `git pull --rebase` in the transport directory |
62
+
63
+ There is no "what's in the DLQ?" — v7 has no DLQ. Failures land in the channel as normal messages with `failed: true` + `error:` in frontmatter; "what failed?" asks the agent to grep the current channel for those.
64
+
65
+ ---
66
+
67
+ ## Coordinating a team in plain language
68
+
69
+ The real power is workflows. Describe the goal and let the runtime dispatch — no model plays an orchestration role; the runtime drives it deterministically.
70
+
71
+ > **You:** "Fan out three drafts of the release notes via sonnet, then have opus pick the strongest unified version."
72
+
73
+ The interactive agent runs `crosstalk workflow compose "<your prose>"`. The engine takes over:
74
+
75
+ 1. One LLM call compiles the prose to a structured workflow plan (`fanout: {to: sonnet, count: 3, ...}`, `synthesize: {to: opus, ...}`) and prints the YAML for review.
76
+ 2. You confirm with `[y]es`, tweak with `[e]dit` (opens `$VISUAL`/`$EDITOR`), or abort with `[n]o`. On `y`, the plan is submitted and a child channel is auto-created.
77
+ 3. Three sub-primitives addressed to scoped recipients (`sonnet@<alias>`, round-robined across the dispatcher registry) fire into the child channel.
78
+ 4. Once all three replies are in, one synthesis sub-primitive with the candidates concatenated dispatches to opus.
79
+ 5. The synthesis reply gets routed back to you in the parent channel.
80
+
81
+ You see:
82
+
83
+ > *(running workflow…)*
84
+ > **workflow@cachy:** *(final synthesis — the chosen unified release-notes draft.)*
85
+
86
+ You never see the orchestration — only the result. To drill into how the work happened, ask "show me the child channel for that workflow."
87
+
88
+ ---
89
+
90
+ ## What to expect
91
+
92
+ - **It's asynchronous.** Each round-trip is roughly 5–30 seconds — your message is committed and pushed, the recipient's dispatcher polls, the agent runs, its reply is committed and pulled back. The interactive agent will say something like *"(waiting for sonnet…)"* and surface the answer when it arrives.
93
+ - **Replies are matched by fact, not by claim.** Crosstalk records which message each reply answers via the `re:` field, so "has it replied yet?" is always answered from ground truth — a busy or confused model can't fake completion.
94
+ - **At-least-once delivery.** For anything with side effects (sending an email, deploying), the interactive agent — and the models — check the channel for prior completion before repeating. For lookups and advice, the occasional duplicate is harmless.
95
+ - **Failures are loud.** A failed dispatch lands as a normal reply with `failed: true` + `error: <text>`. The interactive agent will surface failures the same way it surfaces successes — no separate place to check.
96
+ - **If nothing comes back** (~10 minutes), the interactive agent will offer to check `crosstalk server status --probe` (local) or `crosstalk status` (engine API) for the dispatcher heartbeat. Usually it's a remote dispatcher that's down or a model whose CLI isn't wired correctly in `data/crosstalk.yaml`.
97
+
98
+ ---
99
+
100
+ ## Tips for good results
101
+
102
+ - **Name the machine when it matters.** "ask sonnet" reaches sonnet on whichever dispatcher claims it first; "ask sonnet on cachy" pins it to one machine. Use the machine when *where* the work runs is part of the ask.
103
+ - **Name the channel for threaded work.** If you don't, and there's more than one channel, the agent will ask which one rather than guess.
104
+ - **Be explicit for non-idempotent actions.** "deploy to staging" is a side effect; say so clearly and the model will verify it hasn't already happened.
105
+ - **You don't need to know UUIDs or paths — ever.** If the agent starts showing you raw file paths or git output, tell it to "talk to me like a person"; hiding that machinery is its job.
106
+
107
+ ---
108
+
109
+ ## When to drop to the CLI
110
+
111
+ Natural language covers day-to-day operation. Reach for the **[CLI guide](GUIDE-CLI.md)** when you're:
112
+
113
+ - scripting or automating (cron jobs, CI),
114
+ - editing `data/crosstalk.yaml` to wire a new agent (and follow with `crosstalk server restart` to reload it),
115
+ - managing the engine lifecycle (`crosstalk server start` / `stop` / `restart`), or
116
+ - inspecting state at a low level (cursor SHA, heartbeat freshness via `crosstalk status`).
117
+
118
+ Both drive the exact same transport — use whichever is faster for the task in front of you.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Cordfuse
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.