@cordfuse/crosstalk 5.0.0-alpha.7 → 6.0.0-alpha.10
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/GUIDE-CLI.md +298 -0
- package/GUIDE-PROMPTS.md +132 -0
- package/README.md +139 -0
- package/bin/crosstalk.js +51 -80
- package/package.json +9 -5
- package/src/activation.ts +104 -0
- package/src/actor.ts +29 -4
- package/src/attach.ts +1 -1
- package/src/channel.ts +8 -21
- package/src/chat.ts +52 -115
- package/src/dispatch.ts +288 -660
- package/src/dlq.ts +89 -136
- package/src/init.ts +23 -42
- package/src/open.ts +55 -31
- package/src/replies.ts +59 -0
- package/src/send.ts +87 -72
- package/src/state.ts +173 -0
- package/src/status.ts +18 -57
- package/src/stop.ts +37 -0
- package/src/transport.ts +81 -198
- package/src/turnq.ts +64 -32
- package/src/upgrade.ts +9 -11
- package/src/wake.ts +5 -6
- package/template/CLAUDE.md +12 -2
- package/template/gitignore +4 -0
- package/template/upstream/CROSSTALK-VERSION +1 -1
- package/template/upstream/CROSSTALK.md +172 -463
- package/template/upstream/OPERATOR.md +9 -9
- package/template/upstream/PROTOCOL.md +64 -244
- package/template/upstream/actors/concierge.md +24 -118
- package/src/cursor.ts +0 -48
- package/template/.amazonq/rules/crosstalk.md +0 -2
- package/template/.continue/rules/crosstalk.md +0 -7
- package/template/.cursor/rules/crosstalk.mdc +0 -7
- package/template/.github/copilot-instructions.md +0 -2
- package/template/.windsurfrules +0 -2
- package/template/AGENTS.md +0 -2
- package/template/ANTIGRAVITY.md +0 -2
- package/template/GEMINI.md +0 -2
- package/template/OPENCODE.md +0 -2
- package/template/QWEN.md +0 -2
- package/template/README.md +0 -22
- package/template/local/CROSSTALK.md +0 -4
- package/template/upstream/JITTER.md +0 -24
- package/template/upstream/actors/cloud-architect.md +0 -83
- package/template/upstream/actors/devops-engineer.md +0 -83
- package/template/upstream/actors/documentation-engineer.md +0 -107
- package/template/upstream/actors/infrastructure-engineer.md +0 -83
- package/template/upstream/actors/junior-developer.md +0 -83
- package/template/upstream/actors/precise-generalist.md +0 -48
- package/template/upstream/actors/product-manager.md +0 -83
- package/template/upstream/actors/qa-engineer.md +0 -83
- package/template/upstream/actors/security-engineer.md +0 -92
- package/template/upstream/actors/senior-generalist-engineer.md +0 -111
- package/template/upstream/actors/senior-software-engineer.md +0 -94
- package/template/upstream/actors/skeptic.md +0 -89
- package/template/upstream/actors/technical-writer.md +0 -89
- package/template/upstream/actors/ux-designer.md +0 -83
package/GUIDE-CLI.md
ADDED
|
@@ -0,0 +1,298 @@
|
|
|
1
|
+
# Crosstalk CLI Guide
|
|
2
|
+
|
|
3
|
+
Quick reference for the `crosstalk` CLI. Run `crosstalk <subcommand> --help` for flags.
|
|
4
|
+
|
|
5
|
+
Requires: Node.js ≥ 20. All subcommands (except `init`) must be run from inside a transport (a directory containing `upstream/CROSSTALK-VERSION`).
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Setup
|
|
10
|
+
|
|
11
|
+
### `crosstalk init`
|
|
12
|
+
|
|
13
|
+
Scaffold a new transport in the current directory:
|
|
14
|
+
|
|
15
|
+
```sh
|
|
16
|
+
mkdir my-transport && cd my-transport
|
|
17
|
+
git init
|
|
18
|
+
crosstalk init
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
Creates `upstream/` (spec + protocol docs), `hosts/`, `data/`, and `local/actors/`. Commit and push to your git remote; that repo is now the message bus.
|
|
22
|
+
|
|
23
|
+
> ### Multi-host: seed every host file before sending
|
|
24
|
+
>
|
|
25
|
+
> Each host's delivery waterline is the commit that first added **its** host
|
|
26
|
+
> file to the transport. A message addressed to a host *before* that host's
|
|
27
|
+
> file exists in history sits below the waterline and is never delivered.
|
|
28
|
+
>
|
|
29
|
+
> **Therefore, when adding a host to a multi-host bus, commit + push its
|
|
30
|
+
> `hosts/<alias>.md` BEFORE anyone sends messages to it.** A host that joins
|
|
31
|
+
> an existing transport must seed its host file first; messages sent to it
|
|
32
|
+
> earlier won't be received.
|
|
33
|
+
>
|
|
34
|
+
> `crosstalk send` warns when `--to <actor>@<host>` names a host with no host
|
|
35
|
+
> file in the transport, so the silent drop becomes a visible error at send
|
|
36
|
+
> time.
|
|
37
|
+
>
|
|
38
|
+
> **Single-host operators don't need to think about this** — `crosstalk init`
|
|
39
|
+
> seeds your host file at setup, before any messaging, so the ordering can
|
|
40
|
+
> never bite you.
|
|
41
|
+
|
|
42
|
+
---
|
|
43
|
+
|
|
44
|
+
## Choosing and wiring an agent
|
|
45
|
+
|
|
46
|
+
Crosstalk is **agent-agnostic**. An actor is any CLI that reads a prompt and
|
|
47
|
+
prints a reply — there is no built-in model and no vendor requirement. You wire
|
|
48
|
+
your agent in the host file, under the actor's tier, as a `cli:` string:
|
|
49
|
+
|
|
50
|
+
```yaml
|
|
51
|
+
# hosts/<your-host>.md
|
|
52
|
+
---
|
|
53
|
+
alias: my-laptop
|
|
54
|
+
hostname: my-laptop
|
|
55
|
+
actors:
|
|
56
|
+
concierge:
|
|
57
|
+
default:
|
|
58
|
+
cli: <your-agent-cli> # the command crosstalk runs to invoke the agent
|
|
59
|
+
---
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
### The contract
|
|
63
|
+
|
|
64
|
+
When the dispatcher invokes an actor it:
|
|
65
|
+
|
|
66
|
+
1. composes `system prompt + the message(s)` and **appends it as the last
|
|
67
|
+
argument to your CLI command**, then
|
|
68
|
+
2. reads the CLI's **stdout** as the reply body, and expects exit code **0**.
|
|
69
|
+
|
|
70
|
+
So a `cli:` works if the command runs **one prompt non-interactively** (taking
|
|
71
|
+
the prompt as its trailing positional or flag-value) and **prints the answer
|
|
72
|
+
to stdout**. Two things to get right per agent:
|
|
73
|
+
|
|
74
|
+
- **Non-interactive / skip-approval flag.** Each agent has a flag that stops it
|
|
75
|
+
from pausing for confirmation or opening a TUI. Use it, or every dispatch will
|
|
76
|
+
hang until the 5-minute timeout and land in the DLQ.
|
|
77
|
+
- **Trailing argument shape.** The dispatcher tacks the prompt on the end of
|
|
78
|
+
whatever you put in `cli:`. So `cli: codex exec` becomes
|
|
79
|
+
`codex exec "<prompt>"`, `cli: gemini -p` becomes `gemini -p "<prompt>"`,
|
|
80
|
+
and `cli: claude --print --dangerously-skip-permissions` becomes
|
|
81
|
+
`claude --print --dangerously-skip-permissions "<prompt>"`. Every modern
|
|
82
|
+
agent CLI is happy with one of those shapes.
|
|
83
|
+
|
|
84
|
+
> For prompts larger than 64 KB (huge batches) the dispatcher falls back to
|
|
85
|
+
> writing the prompt to **stdin** automatically — the default argv path covers
|
|
86
|
+
> every supported agent, and the stdin fallback keeps things working past the
|
|
87
|
+
> OS `ARG_MAX` limit.
|
|
88
|
+
|
|
89
|
+
### Recipes
|
|
90
|
+
|
|
91
|
+
Starting points — **verify flags against your installed CLI version**;
|
|
92
|
+
vendors change them.
|
|
93
|
+
|
|
94
|
+
| Agent | Example `cli:` | Notes |
|
|
95
|
+
|---|---|---|
|
|
96
|
+
| Claude Code | `claude --print --dangerously-skip-permissions` | accepts the prompt as a positional arg |
|
|
97
|
+
| OpenAI Codex | `codex exec` | `exec` = non-interactive; add its bypass/sandbox flag |
|
|
98
|
+
| Gemini CLI | `gemini -p` | `-p` one-shot prompt; add `--yolo` to skip approvals |
|
|
99
|
+
| Qwen Code | `qwen -p` | Gemini-CLI-family flags |
|
|
100
|
+
| opencode | `opencode run` | `run` = one-shot |
|
|
101
|
+
| Antigravity | `agy -p` | `-p`/`--print` non-interactive |
|
|
102
|
+
|
|
103
|
+
You can mix agents in one transport — different actors (or different hosts) can
|
|
104
|
+
run entirely different vendors. Senders never know or care which agent answered.
|
|
105
|
+
|
|
106
|
+
> **Privacy note for shared infrastructure.** The prompt is passed as an
|
|
107
|
+
> argv arg, which means it's visible to anything that can read the
|
|
108
|
+
> dispatcher process's `/proc/<pid>/cmdline` (e.g. `ps auxww`). On a single-
|
|
109
|
+
> user laptop or dedicated dispatcher VM that's a non-issue; on multi-user
|
|
110
|
+
> machines, plan accordingly.
|
|
111
|
+
|
|
112
|
+
### Tiers (optional)
|
|
113
|
+
|
|
114
|
+
A tier is a named CLI slot under an actor. The bare-string shorthand is `count: 1`;
|
|
115
|
+
the object form adds `count:` for parallel instances. Senders may request a tier
|
|
116
|
+
with `--tier <name>`; the dispatcher falls back to the first declared tier when
|
|
117
|
+
the requested one is absent.
|
|
118
|
+
|
|
119
|
+
```yaml
|
|
120
|
+
actors:
|
|
121
|
+
junior-developer:
|
|
122
|
+
fast:
|
|
123
|
+
cli: gemini -p --yolo
|
|
124
|
+
count: 5 # five parallel slots picking up work independently
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
---
|
|
128
|
+
|
|
129
|
+
## Sending messages
|
|
130
|
+
|
|
131
|
+
### `crosstalk send --to <actor> --channel <uuid> "<body>"`
|
|
132
|
+
|
|
133
|
+
Post a message to an actor. The channel must already exist (see `crosstalk channel`).
|
|
134
|
+
|
|
135
|
+
```sh
|
|
136
|
+
crosstalk send \
|
|
137
|
+
--to concierge \
|
|
138
|
+
--channel 56f57ff9-7031-4ab2-9b98-4f299d3240fb \
|
|
139
|
+
"What is the capital of France?"
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
Prints `Sent: <relPath>` — save that path if you need to check for replies.
|
|
143
|
+
|
|
144
|
+
| Flag | Required | Notes |
|
|
145
|
+
|---|---|---|
|
|
146
|
+
| `--to <actor[,actor]>` | yes | bare name or `actor@host`; comma-separated list OK |
|
|
147
|
+
| `--channel <uuid>` | yes | channel UUID |
|
|
148
|
+
| `--from <actor>` | no | defaults to `$USER` / `operator` |
|
|
149
|
+
| `--tier <name>` | no | request a specific model tier |
|
|
150
|
+
| `--new` | no | suppress automatic `re:` linking (start new work, not a reply) |
|
|
151
|
+
|
|
152
|
+
---
|
|
153
|
+
|
|
154
|
+
## Running a dispatcher
|
|
155
|
+
|
|
156
|
+
### `crosstalk dispatch`
|
|
157
|
+
|
|
158
|
+
Start the dispatch loop in the current transport. Runs forever, polling for new messages and invoking actor CLIs.
|
|
159
|
+
|
|
160
|
+
```sh
|
|
161
|
+
crosstalk dispatch --poll 30 --json
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
| Flag | Default | Notes |
|
|
165
|
+
|---|---|---|
|
|
166
|
+
| `--poll <seconds>` | `30` | quiet-tick interval; active ticks drop to 1s automatically |
|
|
167
|
+
| `--host <alias>` | auto-detect | override which `hosts/<alias>.md` to load |
|
|
168
|
+
| `--json` | off | structured JSON log lines |
|
|
169
|
+
| `--log-file <path>` | none | mirror logs to a file |
|
|
170
|
+
| `--once` | off | run one tick then exit (useful for testing) |
|
|
171
|
+
|
|
172
|
+
> **macOS note — hostname auto-detect.** macOS's kernel hostname (`os.hostname()`) can drift across network state when the static **HostName** is unset (`configd` re-derives it from DHCP, reverse-DNS, or your VPN/Tailscale machine name). The dispatcher works around this on Darwin by also trying `scutil --get LocalHostName` and its `.local` form when matching against `hosts/<alias>.md`. If auto-detect still fails, either pin `--host <alias>` or pin your kernel hostname once:
|
|
173
|
+
> ```sh
|
|
174
|
+
> sudo scutil --set HostName <your-host-alias>
|
|
175
|
+
> ```
|
|
176
|
+
|
|
177
|
+
Dispatcher state (cursors, DLQ, heartbeat, error log) is stored under `$CROSSTALK_STATE_DIR` (default `~/.local/state/crosstalk/<transport-id>/`) — never in the transport repo.
|
|
178
|
+
|
|
179
|
+
---
|
|
180
|
+
|
|
181
|
+
## Observability
|
|
182
|
+
|
|
183
|
+
### `crosstalk status`
|
|
184
|
+
|
|
185
|
+
Print host file, active channels, cursor positions, DLQ count, and dispatcher heartbeat.
|
|
186
|
+
|
|
187
|
+
```sh
|
|
188
|
+
crosstalk status
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
### `crosstalk replies --re <relPath>[,<relPath>...]`
|
|
192
|
+
|
|
193
|
+
Show which of your dispatched messages have replies. Matches via the runtime-written `re:` field — ground truth, not body-parsing.
|
|
194
|
+
|
|
195
|
+
```sh
|
|
196
|
+
crosstalk replies --re 2026/06/10/130847758Z-780a8b90.md
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
---
|
|
200
|
+
|
|
201
|
+
## DLQ
|
|
202
|
+
|
|
203
|
+
### `crosstalk dlq`
|
|
204
|
+
|
|
205
|
+
Manage the dead-letter queue — messages that failed to dispatch repeatedly.
|
|
206
|
+
|
|
207
|
+
```sh
|
|
208
|
+
crosstalk dlq --list # list quarantined entries
|
|
209
|
+
crosstalk dlq --show <id> # full detail for one entry
|
|
210
|
+
crosstalk dlq --retry <id> # re-queue for dispatch
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
A common first-run cause of DLQ entries: the actor's `cli:` isn't truly
|
|
214
|
+
non-interactive (missing its skip-approval flag), so dispatches hang until the
|
|
215
|
+
5-minute timeout. See **Choosing and wiring an agent**.
|
|
216
|
+
|
|
217
|
+
---
|
|
218
|
+
|
|
219
|
+
## Channels
|
|
220
|
+
|
|
221
|
+
### `crosstalk channel --name <name>`
|
|
222
|
+
|
|
223
|
+
Create a new channel and print its UUID.
|
|
224
|
+
|
|
225
|
+
```sh
|
|
226
|
+
crosstalk channel --name "sprint-42"
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
| Flag | Notes |
|
|
230
|
+
|---|---|
|
|
231
|
+
| `--name <name>` | required; unique within the transport |
|
|
232
|
+
| `--parent <uuid>` | make this a subchannel; it reports back to the parent |
|
|
233
|
+
|
|
234
|
+
---
|
|
235
|
+
|
|
236
|
+
## Interactive
|
|
237
|
+
|
|
238
|
+
### `crosstalk chat`
|
|
239
|
+
|
|
240
|
+
Send a message and wait for the reply in one command. Useful for interactive sessions from the terminal.
|
|
241
|
+
|
|
242
|
+
```sh
|
|
243
|
+
crosstalk chat --to concierge --channel <uuid>
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
### `crosstalk open --actor <name>`
|
|
247
|
+
|
|
248
|
+
Open an interactive REPL-style session with an actor — each exchange is a full dispatch cycle. Requires a TTY.
|
|
249
|
+
|
|
250
|
+
```sh
|
|
251
|
+
crosstalk open --actor concierge
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
### `crosstalk attach`
|
|
255
|
+
|
|
256
|
+
Attach to a running dispatch loop's live log output (like `tail -f`, but structured).
|
|
257
|
+
|
|
258
|
+
> Prefer talking to Crosstalk in plain language instead of memorising flags?
|
|
259
|
+
> See **[GUIDE-PROMPTS.md](GUIDE-PROMPTS.md)** for the natural-language operator interface.
|
|
260
|
+
|
|
261
|
+
---
|
|
262
|
+
|
|
263
|
+
## Misc
|
|
264
|
+
|
|
265
|
+
### `crosstalk wake`
|
|
266
|
+
|
|
267
|
+
Poke the dispatcher to tick immediately. Rarely needed — `send` already signals the dispatcher.
|
|
268
|
+
|
|
269
|
+
### `crosstalk version`
|
|
270
|
+
|
|
271
|
+
Print the installed runtime version.
|
|
272
|
+
|
|
273
|
+
### `crosstalk upgrade`
|
|
274
|
+
|
|
275
|
+
Check whether the transport's protocol version matches the installed runtime and apply any necessary upgrades to `upstream/`.
|
|
276
|
+
|
|
277
|
+
---
|
|
278
|
+
|
|
279
|
+
## Common patterns
|
|
280
|
+
|
|
281
|
+
**One-shot task from a script:**
|
|
282
|
+
```sh
|
|
283
|
+
UUID=$(crosstalk channel --name "batch-$(date +%s)" | grep -o '[0-9a-f-]\{36\}')
|
|
284
|
+
crosstalk send --to concierge --channel "$UUID" "Summarise this file: ..." > /dev/null
|
|
285
|
+
# dispatch loop will pick it up on next poll
|
|
286
|
+
```
|
|
287
|
+
|
|
288
|
+
**Check if fan-out replies are all in:**
|
|
289
|
+
```sh
|
|
290
|
+
# After dispatching to 5 peers, record their relPaths:
|
|
291
|
+
crosstalk replies --re path1.md,path2.md,path3.md,path4.md,path5.md
|
|
292
|
+
```
|
|
293
|
+
|
|
294
|
+
**Troubleshooting a stuck dispatcher:**
|
|
295
|
+
```sh
|
|
296
|
+
crosstalk status # check heartbeat freshness and DLQ count
|
|
297
|
+
crosstalk dlq --list # see what's quarantined
|
|
298
|
+
```
|
package/GUIDE-PROMPTS.md
ADDED
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
# Crosstalk Natural-Language Guide
|
|
2
|
+
|
|
3
|
+
You don't have to memorise the `crosstalk` CLI to use Crosstalk. You can just
|
|
4
|
+
**talk to it.**
|
|
5
|
+
|
|
6
|
+
Crosstalk has an *operator mode*: you open a conversation with an agent inside
|
|
7
|
+
your transport and ask for things in plain language — "ask the test-runner on
|
|
8
|
+
the server whether the build is green." The agent translates your words into the
|
|
9
|
+
right `crosstalk` commands, waits for the answer, and tells you what came back —
|
|
10
|
+
no UUIDs, no file paths, no git.
|
|
11
|
+
|
|
12
|
+
This is the companion to the **[CLI guide](GUIDE-CLI.md)**. Same system, two
|
|
13
|
+
front doors: type commands, or just speak.
|
|
14
|
+
|
|
15
|
+
> Operator mode is **agent-agnostic**, like the rest of Crosstalk. Whatever
|
|
16
|
+
> coding agent you already run — Claude Code, Codex, Gemini, Qwen, opencode,
|
|
17
|
+
> Antigravity — can be your operator interface, as long as it can read the
|
|
18
|
+
> transport's orientation file and run shell commands.
|
|
19
|
+
|
|
20
|
+
---
|
|
21
|
+
|
|
22
|
+
## Starting an operator conversation
|
|
23
|
+
|
|
24
|
+
Pick whichever fits your setup:
|
|
25
|
+
|
|
26
|
+
```sh
|
|
27
|
+
# Purpose-built: open an actor in an interactive operator session
|
|
28
|
+
crosstalk open --actor concierge
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
or simply **launch your agent CLI from inside the transport directory.** The
|
|
32
|
+
transport ships an orientation file at its root (`CLAUDE.md`, and equivalents
|
|
33
|
+
for other agents) that tells your agent it is in operator mode and how to drive
|
|
34
|
+
Crosstalk. Start talking.
|
|
35
|
+
|
|
36
|
+
> **Operator mode ≠ being an actor.** When you open a session this way, *you*
|
|
37
|
+
> (through the agent) are the human's interface — you are not `concierge` or any
|
|
38
|
+
> other actor, and you do **not** process incoming messages. Leave message
|
|
39
|
+
> *processing* to the running dispatcher (`crosstalk dispatch`). Don't run
|
|
40
|
+
> `crosstalk dispatch` or `crosstalk open` from an operator session — both
|
|
41
|
+
> compete with the dispatcher.
|
|
42
|
+
|
|
43
|
+
---
|
|
44
|
+
|
|
45
|
+
## The phrasebook
|
|
46
|
+
|
|
47
|
+
Say it however feels natural; these are the intents the operator agent
|
|
48
|
+
recognises and what it does for you.
|
|
49
|
+
|
|
50
|
+
| You say… | What happens |
|
|
51
|
+
|---|---|
|
|
52
|
+
| "ask concierge to summarise `report.md`" | sends the task to `concierge`, waits, surfaces the reply |
|
|
53
|
+
| "ask the junior-dev on the server to run the tests" | sends to `junior-developer@server`, waits, reports back |
|
|
54
|
+
| "ask everyone for a status update" | sends to `all`, collects the replies as they arrive |
|
|
55
|
+
| "in the *sprint-42* channel, ask concierge to plan the work" | scopes the message to that channel |
|
|
56
|
+
| "is the dispatcher alive?" / "check status" | runs `crosstalk status`, explains the heartbeat plainly |
|
|
57
|
+
| "what's stuck?" / "what's in the dead-letter queue?" | runs `crosstalk dlq`, summarises the failures |
|
|
58
|
+
| "retry that failed one" | runs `crosstalk dlq --retry <id>` |
|
|
59
|
+
| "make a channel called *release-7*" | creates the channel, tells you it's ready |
|
|
60
|
+
| "what channels exist?" | lists channels by their human names |
|
|
61
|
+
| "tweak the concierge actor to be more terse" | edits `local/actors/concierge.md`, commits, pushes |
|
|
62
|
+
| "pull the latest" | runs `git pull --rebase` |
|
|
63
|
+
|
|
64
|
+
---
|
|
65
|
+
|
|
66
|
+
## Coordinating a team in plain language
|
|
67
|
+
|
|
68
|
+
The real power is fan-out. Tell the coordinator the goal and let it dispatch:
|
|
69
|
+
|
|
70
|
+
> **You:** "Ask concierge to get three things done: update the changelog, run
|
|
71
|
+
> the test suite on the server, and draft release notes — then summarise when
|
|
72
|
+
> they're all back."
|
|
73
|
+
|
|
74
|
+
Behind the scenes the coordinator sends one message per task to the right
|
|
75
|
+
actors, ends its turn, and is automatically re-woken as each reply lands; when
|
|
76
|
+
all are in, it aggregates and answers you. You just see:
|
|
77
|
+
|
|
78
|
+
> *(waiting for concierge…)*
|
|
79
|
+
> **concierge:** All three done. Changelog updated, 142 tests green on the
|
|
80
|
+
> server, draft release notes attached below. …
|
|
81
|
+
|
|
82
|
+
You never see the orchestration — only the result.
|
|
83
|
+
|
|
84
|
+
---
|
|
85
|
+
|
|
86
|
+
## What to expect
|
|
87
|
+
|
|
88
|
+
- **It's asynchronous.** Each round-trip is roughly 5–30 seconds — your message
|
|
89
|
+
is committed and pushed, the recipient's dispatcher polls, the agent runs, its
|
|
90
|
+
reply is committed and pulled back. The operator agent will say something like
|
|
91
|
+
*"(waiting for concierge…)"* and surface the answer when it arrives.
|
|
92
|
+
- **Replies are matched by fact, not by claim.** Crosstalk records which message
|
|
93
|
+
each reply answers, so "has it replied yet?" is always answered from ground
|
|
94
|
+
truth — a busy or confused actor can't fake completion.
|
|
95
|
+
- **At-least-once delivery.** For anything with side effects (sending an email,
|
|
96
|
+
deploying), the operator agent — and the actors — check the channel for prior
|
|
97
|
+
completion before repeating. For lookups and advice, the occasional duplicate
|
|
98
|
+
is harmless.
|
|
99
|
+
- **If nothing comes back** (~10 minutes), the operator agent will offer to
|
|
100
|
+
check `status` and the DLQ for clues — usually a dispatcher that's down or an
|
|
101
|
+
actor whose CLI isn't wired correctly (see
|
|
102
|
+
[GUIDE-CLI.md → Choosing and wiring an agent](GUIDE-CLI.md#choosing-and-wiring-an-agent)).
|
|
103
|
+
|
|
104
|
+
---
|
|
105
|
+
|
|
106
|
+
## Tips for good results
|
|
107
|
+
|
|
108
|
+
- **Name the actor when it matters.** "ask concierge" reaches it on every host
|
|
109
|
+
that runs it; "ask concierge **on cachy**" pins it to one machine. Use the host
|
|
110
|
+
when *where* the work runs is part of the ask.
|
|
111
|
+
- **Name the channel for threaded work.** If you don't, and there's more than one
|
|
112
|
+
channel, the operator agent will ask which one rather than guess.
|
|
113
|
+
- **Be explicit for non-idempotent actions.** "deploy to staging" is a side
|
|
114
|
+
effect; say so clearly and the actor will verify it hasn't already happened.
|
|
115
|
+
- **You don't need to know UUIDs or paths — ever.** If the operator agent starts
|
|
116
|
+
showing you raw file paths or git output, tell it to "talk to me like a person";
|
|
117
|
+
hiding that machinery is its job.
|
|
118
|
+
|
|
119
|
+
---
|
|
120
|
+
|
|
121
|
+
## When to drop to the CLI
|
|
122
|
+
|
|
123
|
+
Natural language covers day-to-day operation. Reach for the
|
|
124
|
+
**[CLI guide](GUIDE-CLI.md)** when you're:
|
|
125
|
+
|
|
126
|
+
- scripting or automating (cron jobs, CI),
|
|
127
|
+
- setting up hosts and wiring agent CLIs,
|
|
128
|
+
- running the dispatcher itself, or
|
|
129
|
+
- debugging cursors / the DLQ in detail.
|
|
130
|
+
|
|
131
|
+
Both drive the exact same transport — use whichever is faster for the task in
|
|
132
|
+
front of you.
|
package/README.md
ADDED
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
# Crosstalk
|
|
2
|
+
|
|
3
|
+
**A shared message bus for humans and AI agents, built on git.**
|
|
4
|
+
|
|
5
|
+
Crosstalk lets people and AI coding agents talk to each other asynchronously —
|
|
6
|
+
across machines, across vendors, across time — using nothing but a git
|
|
7
|
+
repository as the medium. The repo *is* the bus. There is no server to run, no
|
|
8
|
+
database, no broker. If you can `git push`, you can participate.
|
|
9
|
+
|
|
10
|
+
Crosstalk is **agent-agnostic by design.** It does not ship, embed, or require
|
|
11
|
+
any particular model or vendor. An "actor" is just a command-line program that
|
|
12
|
+
reads a prompt and prints a reply. Claude Code, Codex, Gemini CLI, Qwen Code,
|
|
13
|
+
opencode, Antigravity — anything that follows that one contract can be an actor.
|
|
14
|
+
Mix vendors freely in a single transport.
|
|
15
|
+
|
|
16
|
+
---
|
|
17
|
+
|
|
18
|
+
## Why
|
|
19
|
+
|
|
20
|
+
- **No infrastructure.** The message bus is a git repo. Host it on GitHub, a
|
|
21
|
+
private Gitea, a USB stick — anything git speaks to.
|
|
22
|
+
- **Durable and auditable.** Every message is a committed file. The whole
|
|
23
|
+
conversation is the git history.
|
|
24
|
+
- **Cross-machine.** A dispatcher on each machine picks up messages addressed to
|
|
25
|
+
the actors that machine runs. Your laptop, a server, and a Raspberry Pi can all
|
|
26
|
+
share one transport.
|
|
27
|
+
- **Vendor-neutral.** Bring whichever agent CLI you already use. No lock-in.
|
|
28
|
+
- **Self-coordinating.** Filenames are collision-free; pushes rebase-retry.
|
|
29
|
+
A transport works with no central coordinator at all.
|
|
30
|
+
|
|
31
|
+
---
|
|
32
|
+
|
|
33
|
+
## The one contract
|
|
34
|
+
|
|
35
|
+
A Crosstalk **actor** is any CLI that:
|
|
36
|
+
|
|
37
|
+
1. accepts a prompt (the dispatcher appends it as the CLI's last argument), and
|
|
38
|
+
2. prints its reply to **stdout**, then exits `0`.
|
|
39
|
+
|
|
40
|
+
That's it. No SDK, no plugin, no adapter. If your agent's CLI can run one prompt
|
|
41
|
+
non-interactively and print an answer, it works. See
|
|
42
|
+
[GUIDE-CLI.md](GUIDE-CLI.md#choosing-and-wiring-an-agent) for ready-made `cli:`
|
|
43
|
+
recipes per agent.
|
|
44
|
+
|
|
45
|
+
---
|
|
46
|
+
|
|
47
|
+
## 60-second quickstart
|
|
48
|
+
|
|
49
|
+
```sh
|
|
50
|
+
# 1. Install the runtime
|
|
51
|
+
npm install -g @cordfuse/crosstalk
|
|
52
|
+
|
|
53
|
+
# 2. Scaffold a transport (a git repo that is the message bus)
|
|
54
|
+
mkdir my-bus && cd my-bus && git init
|
|
55
|
+
crosstalk init .
|
|
56
|
+
git add -A && git commit -m "initial transport" && git remote add origin <your-repo> && git push -u origin main
|
|
57
|
+
|
|
58
|
+
# 3. Tell this machine which agent runs your actor.
|
|
59
|
+
# Edit hosts/<this-host>.md and set the actor's CLI to YOUR agent:
|
|
60
|
+
# actors:
|
|
61
|
+
# concierge:
|
|
62
|
+
# default:
|
|
63
|
+
# cli: <your-agent-cli> # see the table below
|
|
64
|
+
git add hosts && git commit -m "configure host" && git push
|
|
65
|
+
|
|
66
|
+
# 4. Start the dispatch loop on this machine
|
|
67
|
+
crosstalk dispatch &
|
|
68
|
+
|
|
69
|
+
# 5. Send a message — the dispatcher invokes your agent and commits its reply
|
|
70
|
+
crosstalk send --to concierge "What is the capital of France?"
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
### Pick your agent
|
|
74
|
+
|
|
75
|
+
Set the actor's `cli:` in your host file to whichever you use. The dispatcher
|
|
76
|
+
appends the prompt as the last argument to your `cli:` command — every modern
|
|
77
|
+
agent CLI accepts it that way, so no wrapper is needed:
|
|
78
|
+
|
|
79
|
+
| Agent | Example `cli:` |
|
|
80
|
+
|---|---|
|
|
81
|
+
| Claude Code | `claude --print --dangerously-skip-permissions` |
|
|
82
|
+
| OpenAI Codex | `codex exec` |
|
|
83
|
+
| Gemini CLI | `gemini -p` |
|
|
84
|
+
| Qwen Code | `qwen -p` |
|
|
85
|
+
| opencode | `opencode run` |
|
|
86
|
+
| Antigravity | `agy -p` |
|
|
87
|
+
|
|
88
|
+
Each agent also needs its own non-interactive / skip-approval flag so it doesn't
|
|
89
|
+
block waiting for input — `claude` uses `--dangerously-skip-permissions`,
|
|
90
|
+
others have equivalents. Confirm flags against your installed CLI version.
|
|
91
|
+
See [GUIDE-CLI.md](GUIDE-CLI.md#choosing-and-wiring-an-agent).
|
|
92
|
+
|
|
93
|
+
---
|
|
94
|
+
|
|
95
|
+
## Two ways to use it
|
|
96
|
+
|
|
97
|
+
- **[GUIDE-CLI.md](GUIDE-CLI.md)** — drive Crosstalk with the `crosstalk`
|
|
98
|
+
command: send, dispatch, channels, DLQ, status. For scripts and operators who
|
|
99
|
+
like a terminal.
|
|
100
|
+
- **[GUIDE-PROMPTS.md](GUIDE-PROMPTS.md)** — drive Crosstalk in plain language.
|
|
101
|
+
Open an actor in operator mode and just *talk*: "ask the test-runner on the
|
|
102
|
+
server whether the build is green." The agent translates your words into
|
|
103
|
+
Crosstalk commands and surfaces the answer conversationally.
|
|
104
|
+
|
|
105
|
+
---
|
|
106
|
+
|
|
107
|
+
## Core concepts (one line each)
|
|
108
|
+
|
|
109
|
+
- **Transport** — a git repo scaffolded by `crosstalk init`; the message bus.
|
|
110
|
+
- **Channel** — a UUID directory under `data/channels/`; a conversation thread.
|
|
111
|
+
- **Message** — a markdown file with YAML frontmatter; `crosstalk send` writes it.
|
|
112
|
+
- **Actor** — a named participant whose system prompt lives in `local/actors/<name>.md`.
|
|
113
|
+
- **Host file** — `hosts/<alias>.md`; declares which actors a given machine runs and with which CLI.
|
|
114
|
+
- **Dispatcher** — `crosstalk dispatch`; the per-machine loop that invokes actors and writes their replies.
|
|
115
|
+
|
|
116
|
+
Full protocol: **[upstream/CROSSTALK.md](transport/upstream/CROSSTALK.md)**.
|
|
117
|
+
|
|
118
|
+
### Multi-host in one sentence
|
|
119
|
+
|
|
120
|
+
Every machine commits its own `hosts/<alias>.md` to the transport, then runs
|
|
121
|
+
`crosstalk dispatch`; address `actor@host` to target a specific machine, or a
|
|
122
|
+
bare `actor` to reach it wherever it runs. (Provision each host's file *before*
|
|
123
|
+
sending to it — see [GUIDE-CLI.md](GUIDE-CLI.md).)
|
|
124
|
+
|
|
125
|
+
---
|
|
126
|
+
|
|
127
|
+
## Running headless (Docker)
|
|
128
|
+
|
|
129
|
+
A reference server image runs a dispatcher unattended against a remote
|
|
130
|
+
transport. It's vendor-neutral too — pass whichever provider keys your actors
|
|
131
|
+
need (`ANTHROPIC_API_KEY`, `OPENAI_API_KEY`, `GEMINI_API_KEY`, …) and install
|
|
132
|
+
the matching CLIs. See [server/ONBOARDING.md](server/ONBOARDING.md).
|
|
133
|
+
|
|
134
|
+
---
|
|
135
|
+
|
|
136
|
+
## Status
|
|
137
|
+
|
|
138
|
+
Crosstalk 6.0. The protocol spec is versioned (`upstream/CROSSTALK-VERSION`);
|
|
139
|
+
the runtime is published as [`@cordfuse/crosstalk`](https://www.npmjs.com/package/@cordfuse/crosstalk).
|