agent-embassy 4.3.0 → 4.4.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/CHANGELOG.md +15 -0
- package/CONTRIBUTING.md +1 -1
- package/README.md +174 -156
- package/SECURITY.md +13 -11
- package/dist/src/gateway/core-cli.js +2 -1
- package/dist/src/gateway/core-cli.js.map +1 -1
- package/dist/src/gateway/core-version.d.ts +1 -1
- package/dist/src/gateway/core-version.js +1 -1
- package/dist/src/gateway/tui-model.d.ts +67 -0
- package/dist/src/gateway/tui-model.js +136 -0
- package/dist/src/gateway/tui-model.js.map +1 -0
- package/dist/src/gateway/tui-view.d.ts +11 -0
- package/dist/src/gateway/tui-view.js +206 -0
- package/dist/src/gateway/tui-view.js.map +1 -0
- package/dist/src/gateway/tui.d.ts +7 -41
- package/dist/src/gateway/tui.js +43 -234
- package/dist/src/gateway/tui.js.map +1 -1
- package/docs/CONFIGURATION.md +33 -32
- package/docs/GATEWAY-ARCHITECTURE.md +18 -19
- package/package.json +7 -2
- package/skills/embassy-peer/SKILL.md +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,21 @@ All notable changes to this project are documented in this file.
|
|
|
4
4
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
|
6
6
|
|
|
7
|
+
## [4.4.1] - 2026-09-06
|
|
8
|
+
|
|
9
|
+
### Changed
|
|
10
|
+
- Documentation describes the current product; historical scaffolding removed.
|
|
11
|
+
|
|
12
|
+
## [4.4.0] - 2026-09-06
|
|
13
|
+
|
|
14
|
+
### Changed
|
|
15
|
+
- Embassy now requires Node.js 22 or newer. The terminal interface uses Ink 7 for layout, styling, input and incremental rendering.
|
|
16
|
+
- `embassy tui` is rebuilt on Ink: endpoints grouped by state (Working, Waiting, Faulted, Ready, Dormant, Not reporting, Cached) with counts and a column header; one colour per state with the state word always shown; bold names, dim metadata, display-width padding so wide-character names keep the grid.
|
|
17
|
+
- The selected row is one highlight bar and reverse video means selection only; the outcome column receives the width so a failed delivery's safe code is readable at 80 columns; lists scroll by rendered lines, never orphan a group header, and mark clipped rows with "↑ N more" / "↓ N more".
|
|
18
|
+
- Host tabs with a health mark, section tabs with the failed count in red, and one footer line carrying the position counter and the keys; the discovery note shares the header line.
|
|
19
|
+
- Centred, bordered dialogs for retirement and token entry; the retirement dialog shows host, alias, the full endpoint ID and the settlement consequences in red with a distinct confirm key. Every empty list says why it is empty. Without an interactive terminal `tui` prints plain text with no escape codes; NO_COLOR removes styling and keeps the screen interactive.
|
|
20
|
+
- `string-width` is now a runtime dependency (pinned).
|
|
21
|
+
|
|
7
22
|
## [4.3.0] - 2026-09-06
|
|
8
23
|
|
|
9
24
|
### Added
|
package/CONTRIBUTING.md
CHANGED
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Embassy
|
|
2
2
|
|
|
3
|
-
Embassy lets live Claude Code sessions and Codex CLI
|
|
3
|
+
Embassy lets live Claude Code sessions and Codex CLI agents message one another
|
|
4
4
|
by name, on one Mac or across user-owned Macs reached through SSH. The broker
|
|
5
5
|
wakes the receiving agent through its native interface; agents do not poll.
|
|
6
6
|
Claude→Claude, Claude→Codex, Codex→Claude, and Codex→Codex all use the same
|
|
@@ -13,17 +13,19 @@ identity, so a rename or replacement never silently retargets queued work.
|
|
|
13
13
|
|
|
14
14
|
## Requirements
|
|
15
15
|
|
|
16
|
-
- macOS and Node.js
|
|
16
|
+
- macOS and Node.js 22 or newer.
|
|
17
17
|
- Claude Code installed for the Claude sessions you use.
|
|
18
|
-
- To receive in Codex,
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
update that daemon; merely having a `codex` executable on PATH is
|
|
18
|
+
- To receive in Codex, its managed standalone installation with the App Server
|
|
19
|
+
daemon already running under the same macOS login. Embassy discovers the
|
|
20
|
+
20 most recent unarchived root agents automatically, but does not install,
|
|
21
|
+
start or update that daemon; merely having a `codex` executable on PATH is
|
|
22
22
|
insufficient.
|
|
23
23
|
- A private `nodes.json` when choosing an explicit host name or federating;
|
|
24
24
|
first single-machine boot creates one from the short hostname.
|
|
25
25
|
- Key-based, non-interactive SSH between configured machines when federating.
|
|
26
26
|
|
|
27
|
+
## Install
|
|
28
|
+
|
|
27
29
|
Install one copy with one package manager and verify what the shell resolves:
|
|
28
30
|
|
|
29
31
|
```sh
|
|
@@ -32,94 +34,119 @@ which -a embassy
|
|
|
32
34
|
embassy --version
|
|
33
35
|
```
|
|
34
36
|
|
|
35
|
-
|
|
36
|
-
`embassy service install`. After replacing or removing that installation, run
|
|
37
|
-
the install command again.
|
|
38
|
-
|
|
39
|
-
`embassy service install` starts the per-user launchd agent immediately and
|
|
40
|
-
arranges login startup; use the same command to reload broker configuration or
|
|
41
|
-
start a stopped installation, and use `embassy service uninstall` to stop and
|
|
42
|
-
unload it.
|
|
37
|
+
## Start the broker
|
|
43
38
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
signal restarts it.
|
|
49
|
-
|
|
50
|
-
## Quickstart
|
|
39
|
+
```sh
|
|
40
|
+
embassy service install
|
|
41
|
+
embassy health
|
|
42
|
+
```
|
|
51
43
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
44
|
+
`embassy service install` starts the per-user launchd agent immediately and
|
|
45
|
+
arranges login startup; run the same command again to reload broker
|
|
46
|
+
configuration, to start a stopped installation, or after replacing or removing
|
|
47
|
+
the installation (the service records the absolute installation path). Use
|
|
48
|
+
`embassy service uninstall` to stop and unload it. `embassy serve` is the
|
|
49
|
+
foreground alternative.
|
|
50
|
+
|
|
51
|
+
The agent uses launchd's crash-only keepalive policy. A verified `SIGABRT`
|
|
52
|
+
crash relaunches it. A clean exit, boot refusal, `SIGTERM`, or deliberate
|
|
53
|
+
`kill -9` leaves it stopped; inspect `embassy service status` and run
|
|
54
|
+
`embassy service install` deliberately rather than assuming every signal
|
|
55
|
+
restarts it.
|
|
56
|
+
|
|
57
|
+
`health` means the Embassy control socket and ledger respond. It is not a
|
|
58
|
+
provider readiness proof: it does not show that any Claude session or Codex
|
|
59
|
+
task can receive or answer a message.
|
|
60
|
+
|
|
61
|
+
### Host name and state directory
|
|
62
|
+
|
|
63
|
+
Every local alias ends in `@host`, where `host` is the value in `nodes.json`.
|
|
64
|
+
On first single-machine boot without that file, Embassy derives a lower-case
|
|
65
|
+
name from the short hostname and atomically writes an empty-node inventory; it
|
|
66
|
+
never rewrites a present file. Read `host` from that file and use it as every
|
|
67
|
+
local `@host` suffix; the examples use `@studio` only because they chose
|
|
68
|
+
`host: studio`.
|
|
69
|
+
|
|
70
|
+
To choose an explicit host name or to federate, create `nodes.json` before
|
|
71
|
+
starting the broker. `host` is this machine's name; `nodes` lists directly
|
|
72
|
+
reachable Embassy hosts:
|
|
55
73
|
|
|
56
74
|
```json
|
|
57
75
|
{"version":1,"host":"studio","nodes":[]}
|
|
58
76
|
```
|
|
59
77
|
|
|
60
|
-
`nodes.json` lives inside `EMBASSY_STATE_DIR` when set; otherwise
|
|
78
|
+
`nodes.json` lives inside `EMBASSY_STATE_DIR` when set; otherwise in
|
|
61
79
|
`$XDG_STATE_HOME/agent-embassy`, or `~/.local/state/agent-embassy` when
|
|
62
|
-
`XDG_STATE_HOME` is unset
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
The file must be owned by the current user, mode 0600, inside the private
|
|
68
|
-
mode-0700 state directory. If it is absent on first single-machine boot, Embassy derives a
|
|
69
|
-
lower-case name from the short hostname and atomically writes the equivalent
|
|
70
|
-
empty-node file. It never rewrites a present inventory.
|
|
80
|
+
`XDG_STATE_HOME` is unset. Create the private state directory first, set it to
|
|
81
|
+
mode 0700 and `nodes.json` to mode 0600, and install the service afterwards.
|
|
82
|
+
Every client shell must use the same state-directory configuration captured by
|
|
83
|
+
the installed service.
|
|
71
84
|
|
|
72
|
-
|
|
85
|
+
## See the agents
|
|
73
86
|
|
|
74
87
|
```sh
|
|
75
|
-
embassy
|
|
76
|
-
embassy
|
|
88
|
+
embassy tui # the daily view
|
|
89
|
+
embassy status # one text snapshot
|
|
77
90
|
```
|
|
78
91
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
92
|
+
`embassy tui` is the daily view: an Ink-based terminal client (Node 22+) that
|
|
93
|
+
shows the local broker and each direct host in `nodes.json`, with endpoints
|
|
94
|
+
grouped by state, deliveries newest first, retirements, and action results.
|
|
95
|
+
`embassy status` prints the same snapshot once as text.
|
|
83
96
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
97
|
+
Codex agents appear automatically. Embassy observes the same-user Codex App
|
|
98
|
+
Server daemon and lists its 20 most recent unarchived root agents by their
|
|
99
|
+
current public names; dormant agents remain addressable and wake on delivery.
|
|
100
|
+
Only head agents are endpoints: sub-agents are never discovered or displayed.
|
|
101
|
+
Native task IDs, previews and history never appear in Embassy output. If no
|
|
102
|
+
Codex agent appears, check that the Codex daemon is running under this login;
|
|
103
|
+
Embassy never starts it.
|
|
87
104
|
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
105
|
+
Claude sessions are discovered and recorded by exact native identity when a
|
|
106
|
+
Claude caller sends or when a named Claude target is resolved. No helper or
|
|
107
|
+
native advertisement process is installed. To find a Claude session's current
|
|
108
|
+
name, run `embassy refresh` (authorized live discovery) followed by
|
|
109
|
+
`embassy status --json`, or use the exact current name that session supplies.
|
|
92
110
|
|
|
93
|
-
For a harness without native daemon integration,
|
|
94
|
-
to
|
|
111
|
+
For a harness without native daemon integration, registration is the fallback.
|
|
112
|
+
Ask the live Codex CLI task to run this through its own shell tool; an ordinary
|
|
95
113
|
terminal lacks that task's inherited identity:
|
|
96
114
|
|
|
97
115
|
```sh
|
|
98
116
|
embassy register-codex --alias codex-reviewer@studio
|
|
99
117
|
```
|
|
100
118
|
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
119
|
+
The `skills/embassy-peer` folder ships in the `agent-embassy` package under
|
|
120
|
+
`npm root -g`. Copy that entire folder into `~/.codex/skills/` and
|
|
121
|
+
`~/.claude/skills/` and ask each agent to use it, or hand the agent the commands
|
|
122
|
+
shown here directly.
|
|
123
|
+
|
|
124
|
+
## Message an agent
|
|
104
125
|
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
126
|
+
Ask the live Claude Code session to run `embassy send --to codex-reviewer@studio`
|
|
127
|
+
with the message body on stdin, through the agent's shell tool rather than an
|
|
128
|
+
unrelated terminal. The sender is inferred from the calling session; `send`
|
|
129
|
+
takes exactly one of `--to` or `--conversation` and has no `--from`:
|
|
109
130
|
|
|
110
131
|
```sh
|
|
111
132
|
printf '%s\n' 'Please review the change and reply using the supplied Embassy hint' |
|
|
112
133
|
embassy send --to codex-reviewer@studio
|
|
113
134
|
```
|
|
114
135
|
|
|
115
|
-
|
|
136
|
+
A successful send returns `result.deliveryToken` and a conversation reference.
|
|
137
|
+
The receipt proves transport, not comprehension: acceptance means the broker
|
|
138
|
+
owns the delivery, not that a model read or understood the body.
|
|
139
|
+
|
|
140
|
+
## Reply
|
|
141
|
+
|
|
142
|
+
The receiving agent sees a broker hint such as:
|
|
116
143
|
|
|
117
144
|
```text
|
|
118
145
|
<embassy-reply-hint conversation="conv_EXACT_REFERENCE" ...>Reply by running `embassy send --conversation conv_EXACT_REFERENCE` with the reply body on stdin.</embassy-reply-hint>
|
|
119
146
|
```
|
|
120
147
|
|
|
121
|
-
It must execute the exact received command to send the reply
|
|
122
|
-
|
|
148
|
+
It must execute the exact received command to send the reply. Ordinary Codex
|
|
149
|
+
final output is not forwarded automatically, and `conv_example` is not a
|
|
123
150
|
usable reference:
|
|
124
151
|
|
|
125
152
|
```sh
|
|
@@ -127,10 +154,6 @@ printf '%s\n' 'Review complete.' |
|
|
|
127
154
|
embassy send --conversation conv_example
|
|
128
155
|
```
|
|
129
156
|
|
|
130
|
-
For a Claude target, find the current Claude target name with an authorized
|
|
131
|
-
`embassy refresh` followed by `embassy status --json`, or use the exact current
|
|
132
|
-
name supplied by that session.
|
|
133
|
-
|
|
134
157
|
Conversation references are identity-bound, are not aliases, and may survive a
|
|
135
158
|
broker restart while their retained ledger row and both exact endpoints remain
|
|
136
159
|
valid. They stop resolving after retirement, replacement, expiry, eviction, or
|
|
@@ -147,6 +170,12 @@ The durable write phases are `queued`, `reserved`, `armed`, `accepted`, and
|
|
|
147
170
|
`terminal`. Work known not to have been written may return to the queue. An
|
|
148
171
|
uncertain armed or accepted write is never replayed.
|
|
149
172
|
|
|
173
|
+
Ordinary Codex delivery starts only after an immediate idle observation. A
|
|
174
|
+
competing client can start a turn between that observation and Embassy's
|
|
175
|
+
write; the App Server response cannot distinguish the resulting steer from a
|
|
176
|
+
fresh turn, so the race is undetectable on the wire and the receipt proves
|
|
177
|
+
acceptance and lifetime, not fresh-turn creation.
|
|
178
|
+
|
|
150
179
|
An exact leading `STEER:` from Claude to Codex targets the active accepted
|
|
151
180
|
Codex operation at its next safe tool-call boundary. It never interrupts a
|
|
152
181
|
generation. If that boundary is cleanly unavailable, the message remains in
|
|
@@ -155,26 +184,21 @@ the ordinary bounded queue. The global kill switch is
|
|
|
155
184
|
|
|
156
185
|
See [Delivery semantics](docs/DELIVERY.md) for the phase and receipt contract.
|
|
157
186
|
|
|
158
|
-
##
|
|
159
|
-
|
|
160
|
-
Install Embassy and run `embassy service install` on both Macs; for `studio`
|
|
161
|
-
and `laptop`, use `{"version":1,"host":"studio","nodes":["laptop"]}` on
|
|
162
|
-
studio and `{"version":1,"host":"laptop","nodes":["studio"]}` on laptop,
|
|
163
|
-
with each peer name matching both the remote inventory's `host` and a working
|
|
164
|
-
SSH destination or `~/.ssh/config` Host alias.
|
|
187
|
+
## Federate
|
|
165
188
|
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
189
|
+
Connectivity comes first. Install Embassy and run `embassy service install` on
|
|
190
|
+
both Macs; for `studio` and `laptop`, use
|
|
191
|
+
`{"version":1,"host":"studio","nodes":["laptop"]}` on studio and
|
|
192
|
+
`{"version":1,"host":"laptop","nodes":["studio"]}` on laptop, with each peer
|
|
193
|
+
name matching both the remote inventory's `host` and a working SSH destination
|
|
194
|
+
or `~/.ssh/config` Host alias. After changing a running broker's inventory,
|
|
195
|
+
reload it with `embassy service install`.
|
|
171
196
|
|
|
172
197
|
From studio, verify the remote command environment with
|
|
173
198
|
`/usr/bin/ssh laptop 'which -a embassy; node --version; embassy --version'`,
|
|
174
199
|
then verify the corresponding direction from laptop; both remote Node and
|
|
175
|
-
Embassy must resolve without an interactive shell or password prompt.
|
|
176
|
-
|
|
177
|
-
The local broker launches:
|
|
200
|
+
Embassy must resolve without an interactive shell or password prompt. The local
|
|
201
|
+
broker launches:
|
|
178
202
|
|
|
179
203
|
```text
|
|
180
204
|
/usr/bin/ssh <node> embassy peer-stdio
|
|
@@ -189,83 +213,83 @@ queue and trusts the peer's source identity, so first contact does not wait
|
|
|
189
213
|
for a destination catalog poll. Catalogs are bounded memory-only observations,
|
|
190
214
|
never routing authority.
|
|
191
215
|
|
|
216
|
+
Once `codex-reviewer@laptop` appears from the Codex daemon on laptop (or from
|
|
217
|
+
fallback registration there), the Claude session on studio sends with
|
|
218
|
+
`embassy send --to codex-reviewer@laptop` exactly as it would locally.
|
|
219
|
+
|
|
192
220
|
`embassy refresh` observes local Claude and Codex sessions and every configured
|
|
193
|
-
SSH catalog in parallel. `status` performs no provider or network I/O: it shows
|
|
194
|
-
last per-node catalog rows and observation time, retains the last rows when
|
|
195
|
-
later refresh fails, and labels that node `PEER_TUNNEL_UNAVAILABLE`. At most
|
|
196
|
-
remote rows are displayed; truncation is explicit. Named and exact sends
|
|
197
|
-
ask the owner directly.
|
|
221
|
+
SSH catalog in parallel. `status` performs no provider or network I/O: it shows
|
|
222
|
+
the last per-node catalog rows and observation time, retains the last rows when
|
|
223
|
+
a later refresh fails, and labels that node `PEER_TUNNEL_UNAVAILABLE`. At most
|
|
224
|
+
128 remote rows are displayed; truncation is explicit. Named and exact sends
|
|
225
|
+
still ask the owner directly.
|
|
226
|
+
|
|
227
|
+
In `embassy tui`, use `[` / `]` to select a host: the local pane polls every
|
|
228
|
+
second, while independent SSH clients read each remote's
|
|
229
|
+
`embassy status --json` about every five seconds. Each pane reports its own
|
|
230
|
+
broker's health, queue and last operations, not another broker's cached
|
|
231
|
+
catalog, and one hanging host cannot block the other panes. Remote actions run
|
|
232
|
+
the same CLI there over the configured non-interactive SSH; remote retirement
|
|
233
|
+
requires the host plus full endpoint ID confirmation and a fresh supported
|
|
234
|
+
owner snapshot. Disconnected panes are marked stale; an uncertain action is
|
|
235
|
+
never automatically retried. Without an interactive terminal, `tui` prints the
|
|
236
|
+
local status text once and exits without SSH.
|
|
237
|
+
|
|
238
|
+
## Retire
|
|
198
239
|
|
|
199
|
-
|
|
240
|
+
```sh
|
|
241
|
+
embassy retire --alias codex-reviewer@studio
|
|
242
|
+
embassy retire --endpoint <public-id>
|
|
243
|
+
```
|
|
200
244
|
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
245
|
+
`retire` removes one local endpoint identity and settles all of its
|
|
246
|
+
outstanding work: queued and reserved work is cancelled, armed work becomes
|
|
247
|
+
ambiguous, and accepted work becomes unconfirmed. Remote endpoints must be
|
|
248
|
+
retired on their owning host. If departed sessions share a name, retire one
|
|
249
|
+
exactly with `--endpoint` using its opaque public ID from `result.routes`;
|
|
250
|
+
`--alias` and `--endpoint` are mutually exclusive.
|
|
205
251
|
|
|
206
|
-
|
|
207
|
-
are substitutions, not runnable literal values: supply the indicated command
|
|
208
|
-
arguments, exact received conversation reference, exact returned delivery
|
|
209
|
-
token, or public endpoint ID respectively.
|
|
252
|
+
## Operations
|
|
210
253
|
|
|
211
254
|
```sh
|
|
212
|
-
embassy status
|
|
213
255
|
embassy status --json
|
|
214
|
-
embassy tui # interactive operator client
|
|
215
256
|
embassy refresh
|
|
216
257
|
embassy delivery-status --token dlv_example
|
|
217
258
|
embassy wait-delivery --token dlv_example
|
|
218
|
-
embassy retire --alias codex-reviewer@studio
|
|
219
259
|
embassy check
|
|
220
260
|
embassy service status
|
|
221
|
-
embassy serve # foreground alternative
|
|
222
261
|
```
|
|
223
262
|
|
|
263
|
+
`conv_example`, `dlv_example`, and `<public-id>` are substitutions, not
|
|
264
|
+
runnable literal values: supply the exact received conversation reference,
|
|
265
|
+
exact returned delivery token, or public endpoint ID respectively. Retain `result.deliveryToken` from
|
|
266
|
+
the successful send response in your current session; status shows aggregate
|
|
267
|
+
route queues and recent delivery metadata but cannot recover a lost delivery
|
|
268
|
+
token or distinguish identical sends by token.
|
|
269
|
+
|
|
224
270
|
`status` reports the broker ledger, queue depth, recent message outcomes,
|
|
225
271
|
retirements, each local route's last native operation, and the last bounded SSH
|
|
226
272
|
catalog observation. It does not claim that an idle provider is ready.
|
|
227
|
-
|
|
228
|
-
Use `delivery-status` to inspect that delivery's phase, pending age or terminal
|
|
229
|
-
code; use `status --json` to identify a stranded local route, and retire it with
|
|
230
|
-
`retire --alias` using its alias or `retire --endpoint` using its public id from `result.routes`,
|
|
231
|
-
understanding that this settles all outstanding work for that endpoint.
|
|
232
|
-
|
|
233
|
-
`embassy tui` shows the local broker and each direct host in `nodes.json` in one
|
|
234
|
-
terminal. Use `[` / `]` to select a host: local status polls every second, while
|
|
235
|
-
independent SSH clients read each remote's `embassy status --json` about every
|
|
236
|
-
five seconds. Each pane reports its own broker's health, queue and last
|
|
237
|
-
operations—not another broker's cached catalog. One hanging host cannot block
|
|
238
|
-
the other panes. No message bodies are displayed.
|
|
239
|
-
On-screen keys refresh, check, look up a token or retire on the selected host.
|
|
240
|
-
Remote actions run the same CLI there over configured non-interactive SSH;
|
|
241
|
-
retirement requires HOST + full endpoint ID confirmation and a fresh supported
|
|
242
|
-
owner snapshot. An uncertain action is never automatically retried.
|
|
243
|
-
Disconnected views are marked stale; actions are never automatically retried.
|
|
244
|
-
Without an interactive terminal, `tui` prints local status text once and exits
|
|
245
|
-
without SSH. Unsupported remote response shapes are not guessed; a lazy
|
|
246
|
-
`embassy --version` read identifies only that remote CLI, not its broker version.
|
|
247
|
-
Deliveries are newest-admitted first, with faults distinguished from successful
|
|
248
|
-
delivery. Use 1–4 or Tab to change sections, g/G for first/last row, and Esc to
|
|
249
|
-
return from an action result. Token lookup echoes only the token you type;
|
|
250
|
-
tokens are not added to the general delivery list. Retirement confirmation
|
|
251
|
-
shows the full endpoint identity and the consequences for unsettled work.
|
|
252
|
-
|
|
253
273
|
Machine output is one closed JSON line shaped as
|
|
254
274
|
`{"ok":true,"command":"status","result":{...}}`; route rows are therefore at
|
|
255
275
|
`.result.routes`. A terminal `embassy status` renders the same body for a
|
|
256
|
-
person, while `--json` keeps the envelope.
|
|
276
|
+
person, while `--json` keeps the envelope. No message body appears in either.
|
|
277
|
+
|
|
278
|
+
Use `delivery-status` to inspect one delivery's phase, pending age or terminal
|
|
279
|
+
code; `wait-delivery` polls until it is terminal or the bounded wait ends.
|
|
257
280
|
|
|
258
281
|
`check` is a broker-only loopback through the real ledger and coordinator. It
|
|
259
282
|
proves local control, persistence, routing, and receipt handling without
|
|
260
|
-
contacting a live Claude or Codex agent.
|
|
261
|
-
|
|
262
|
-
|
|
283
|
+
contacting a live Claude or Codex agent. A passing check exercises only broker
|
|
284
|
+
loopback, so neither `health` nor `check` proves that a Claude session or Codex
|
|
285
|
+
task can receive or answer a message.
|
|
263
286
|
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
287
|
+
In the TUI, on-screen keys refresh, check, look up a token or retire on the
|
|
288
|
+
selected host. Use 1–4 or Tab to change sections, `g`/`G` for the first or last
|
|
289
|
+
row, and Esc to return from an action result. Token lookup echoes only the
|
|
290
|
+
token you type; tokens are not added to the general delivery list. Retirement
|
|
291
|
+
confirmation shows the full endpoint identity and the consequences for
|
|
292
|
+
unsettled work. No message bodies are displayed.
|
|
269
293
|
|
|
270
294
|
## Safety
|
|
271
295
|
|
|
@@ -278,36 +302,30 @@ If departed sessions share a name, retire one exactly with
|
|
|
278
302
|
- Embassy launches `/usr/bin/ssh` directly without a local shell, in batch mode
|
|
279
303
|
with forwarding disabled; the remote account must resolve the fixed
|
|
280
304
|
`embassy peer-stdio` command in its non-interactive SSH environment.
|
|
281
|
-
-
|
|
282
|
-
|
|
283
|
-
Codex task can receive or answer a message.
|
|
305
|
+
- Embassy never changes a Codex approval or sandbox policy and never answers
|
|
306
|
+
an approval.
|
|
284
307
|
|
|
285
308
|
See [Security](SECURITY.md), [Configuration](docs/CONFIGURATION.md), and
|
|
286
309
|
[Architecture](docs/GATEWAY-ARCHITECTURE.md).
|
|
287
310
|
|
|
288
311
|
## Upgrading to 4.x
|
|
289
312
|
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
settle or explicitly abandon pending work;
|
|
298
|
-
`embassy service uninstall` (or stop the foreground serve
|
|
299
|
-
|
|
300
|
-
`gateway-state.json`
|
|
301
|
-
`
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
old binary as well as its old state if rollback may be needed, and never run
|
|
307
|
-
the old and new brokers together. See the [reset procedure](docs/CONFIGURATION.md#private-state-reset).
|
|
308
|
-
|
|
309
|
-
The rollback boundary is the preserved old state plus its matching old binary.
|
|
310
|
-
Do not point 4.2.0 at schema-7 state or this release at schema ≤5.
|
|
313
|
+
Upgrade the CLI and broker together; they must come from one installation.
|
|
314
|
+
Private state written by an earlier 4.x release (schema 6) is read forward
|
|
315
|
+
into the current schema 7 with every existing endpoint retained; no reset is
|
|
316
|
+
needed, but back up `gateway-state.json` first, because an earlier 4.x binary
|
|
317
|
+
refuses schema 7 and rollback requires that backup.
|
|
318
|
+
|
|
319
|
+
There is no 3.x migration or converter. Before replacing a 3.x installation,
|
|
320
|
+
use its matching CLI to inspect and settle or explicitly abandon pending work;
|
|
321
|
+
stop the broker with `embassy service uninstall` (or stop the foreground serve
|
|
322
|
+
process) and confirm with `embassy service status`; back up and move aside only
|
|
323
|
+
`gateway-state.json` while retaining `nodes.json`; then install the current
|
|
324
|
+
release and run `embassy service install`. Codex agents are discovered; use
|
|
325
|
+
fallback registration only for non-native harnesses. All 3.x state is
|
|
326
|
+
unsupported: preserve the old binary with its old state if rollback may be
|
|
327
|
+
needed, and never run the old and new brokers together. See the
|
|
328
|
+
[reset procedure](docs/CONFIGURATION.md#private-state-reset).
|
|
311
329
|
|
|
312
330
|
## Development
|
|
313
331
|
|
package/SECURITY.md
CHANGED
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
|
|
3
3
|
## Supported versions
|
|
4
4
|
|
|
5
|
-
Security fixes are provided for the current release line.
|
|
6
|
-
|
|
7
|
-
|
|
5
|
+
Security fixes are provided for the current release line. The CLI and broker
|
|
6
|
+
must come from one installation, and federated peers must run the same
|
|
7
|
+
federation protocol.
|
|
8
8
|
|
|
9
9
|
## Reporting a vulnerability
|
|
10
10
|
|
|
@@ -200,8 +200,9 @@ commit boundary remain uncertain and are never replayed automatically.
|
|
|
200
200
|
Public JSON is a closed projection. It may contain opaque Embassy endpoint IDs,
|
|
201
201
|
aliases, providers, hosts, queue depths, safe codes, phases/outcomes, ages,
|
|
202
202
|
recent retirement times, and bounded remote catalog rows and observation times.
|
|
203
|
-
Codex rows may additionally contain observed busy, waiting, idle, dormant
|
|
204
|
-
The explicit-registration retention marker
|
|
203
|
+
Codex rows may additionally contain the observed busy, waiting, idle, dormant,
|
|
204
|
+
systemError or unknown state. The explicit-registration retention marker
|
|
205
|
+
remains private.
|
|
205
206
|
It must never contain native IDs or handles, socket paths, message bodies,
|
|
206
207
|
delivery/conversation secrets, credentials, exceptions, raw diagnostics, or
|
|
207
208
|
provider histories. Human output is derived from the same validated shape.
|
|
@@ -211,12 +212,13 @@ protocol channel. Operational hints use bounded safe codes and stderr.
|
|
|
211
212
|
|
|
212
213
|
## State reset and rollback
|
|
213
214
|
|
|
214
|
-
Private state
|
|
215
|
-
|
|
216
|
-
mutation; no 3.x converter or removed-command alias
|
|
217
|
-
|
|
218
|
-
requires that pre-upgrade backup. Upgrading from 3.x
|
|
219
|
-
unsettled work with the old binary and resetting state while keeping
|
|
215
|
+
Private state is schema 7; a valid schema-6 document from an earlier 4.x
|
|
216
|
+
release is read forward with its rows retained. Schemas ≤5 and unknown state
|
|
217
|
+
refuse before mutation; there is no 3.x converter or removed-command alias.
|
|
218
|
+
Back up state before upgrading, because an earlier 4.x binary refuses schema
|
|
219
|
+
7 and rollback requires that pre-upgrade backup. Upgrading from 3.x requires
|
|
220
|
+
inspecting unsettled work with the old binary and resetting state while keeping
|
|
221
|
+
`nodes.json`.
|
|
220
222
|
|
|
221
223
|
Reset invalidates all old routes, receipts, and conversation references. The
|
|
222
224
|
only rollback is the preserved old binary with its untouched old state. Embassy
|
|
@@ -13,7 +13,6 @@ import { LocalControlError, requestLocalControl } from "./local-control.js";
|
|
|
13
13
|
import { runCoreRuntime } from "./runtime.js";
|
|
14
14
|
import { defaultRunLaunchctl } from "./service-agent.js";
|
|
15
15
|
import { runCoreServiceCommand } from "./core-service-command.js";
|
|
16
|
-
import { runTui } from "./tui.js";
|
|
17
16
|
import { createTuiSshClient } from "./tui-ssh.js";
|
|
18
17
|
import { CORE_VERSION } from "./core-version.js";
|
|
19
18
|
export { CORE_VERSION } from "./core-version.js";
|
|
@@ -203,8 +202,10 @@ export async function runCoreCli(args, dependencies = {}) {
|
|
|
203
202
|
if (command === "tui") {
|
|
204
203
|
if (args.length !== 1)
|
|
205
204
|
return invalid();
|
|
205
|
+
const { runTui } = await import("./tui.js");
|
|
206
206
|
const ssh = createTuiSshClient({ nodes: inventory.nodes, env });
|
|
207
207
|
await runTui({ input: stdin, output: stdout, call, renderStatus, host: inventory.host,
|
|
208
|
+
terminal: { noColor: env.NO_COLOR !== undefined, dumb: env.TERM === "dumb" },
|
|
208
209
|
remote: { hosts: inventory.nodes, call: ssh.call, close: ssh.close },
|
|
209
210
|
hint: (code, host) => host && host !== inventory.host
|
|
210
211
|
? `On ${host}: ${hint("tui", code, "the configured state directory on that host")}`
|