agent-embassy 4.2.0 → 4.4.0

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 (48) hide show
  1. package/CHANGELOG.md +19 -0
  2. package/README.md +28 -17
  3. package/SECURITY.md +25 -11
  4. package/dist/src/gateway/broker-control.js +9 -2
  5. package/dist/src/gateway/broker-control.js.map +1 -1
  6. package/dist/src/gateway/broker.d.ts +14 -0
  7. package/dist/src/gateway/broker.js +6 -2
  8. package/dist/src/gateway/broker.js.map +1 -1
  9. package/dist/src/gateway/codex-discovery.d.ts +42 -0
  10. package/dist/src/gateway/codex-discovery.js +604 -0
  11. package/dist/src/gateway/codex-discovery.js.map +1 -0
  12. package/dist/src/gateway/codex-stateless-transport.d.ts +1 -1
  13. package/dist/src/gateway/codex-stateless-transport.js +126 -18
  14. package/dist/src/gateway/codex-stateless-transport.js.map +1 -1
  15. package/dist/src/gateway/core-cli.js +10 -6
  16. package/dist/src/gateway/core-cli.js.map +1 -1
  17. package/dist/src/gateway/core-version.d.ts +1 -1
  18. package/dist/src/gateway/core-version.js +1 -1
  19. package/dist/src/gateway/endpoint-directory.d.ts +12 -0
  20. package/dist/src/gateway/endpoint-directory.js +94 -4
  21. package/dist/src/gateway/endpoint-directory.js.map +1 -1
  22. package/dist/src/gateway/ledger-codec.js +11 -6
  23. package/dist/src/gateway/ledger-codec.js.map +1 -1
  24. package/dist/src/gateway/ledger.d.ts +2 -1
  25. package/dist/src/gateway/ledger.js +5 -2
  26. package/dist/src/gateway/ledger.js.map +1 -1
  27. package/dist/src/gateway/local-control.d.ts +1 -1
  28. package/dist/src/gateway/local-control.js +1 -1
  29. package/dist/src/gateway/owned-state.d.ts +1 -0
  30. package/dist/src/gateway/owned-state.js +1 -1
  31. package/dist/src/gateway/owned-state.js.map +1 -1
  32. package/dist/src/gateway/runtime.d.ts +4 -2
  33. package/dist/src/gateway/runtime.js +18 -5
  34. package/dist/src/gateway/runtime.js.map +1 -1
  35. package/dist/src/gateway/tui-model.d.ts +67 -0
  36. package/dist/src/gateway/tui-model.js +136 -0
  37. package/dist/src/gateway/tui-model.js.map +1 -0
  38. package/dist/src/gateway/tui-view.d.ts +11 -0
  39. package/dist/src/gateway/tui-view.js +206 -0
  40. package/dist/src/gateway/tui-view.js.map +1 -0
  41. package/dist/src/gateway/tui.d.ts +7 -40
  42. package/dist/src/gateway/tui.js +43 -231
  43. package/dist/src/gateway/tui.js.map +1 -1
  44. package/docs/CONFIGURATION.md +59 -17
  45. package/docs/DELIVERY.md +18 -6
  46. package/docs/GATEWAY-ARCHITECTURE.md +43 -21
  47. package/package.json +8 -3
  48. package/skills/embassy-peer/SKILL.md +6 -6
@@ -1,5 +1,7 @@
1
1
  # Configuration
2
2
 
3
+ Embassy requires macOS and Node.js 22 or newer.
4
+
3
5
  Embassy has one broker per login user and machine. Configuration is inherited
4
6
  when the broker starts; changing it requires a broker restart. Provider build
5
7
  or version metadata never grants routing authority.
@@ -96,20 +98,54 @@ native agent list.
96
98
 
97
99
  To receive in Codex, use its managed standalone installation with its App Server
98
100
  daemon already running under the same macOS login; merely having a `codex`
99
- executable on PATH is insufficient, and Embassy does not install or start that daemon.
100
-
101
- A Codex task registers itself with `embassy register-codex --alias ...` using
102
- its inherited `CODEX_THREAD_ID`. The ID is not a command argument or public
103
- output. Registration is a logical state change and performs no App Server I/O.
104
- Each delivery independently attests the current App Server interface and exact
105
- task before authorization, resumes that task without retaining history, and
106
- writes through a fresh operation.
101
+ executable on PATH is insufficient, and Embassy does not install, start or
102
+ update that daemon.
103
+
104
+ Embassy observes the daemon's recency-sorted top 20 unarchived root threads and keeps them
105
+ current from lifecycle and name events. Native names become public lookup
106
+ aliases; native task IDs remain only in the closed private endpoint binding,
107
+ while previews, turns and item content are neither retained nor printed.
108
+ Sub-agents are not discovered or displayed. Busy roots queue ordinary messages;
109
+ waiting means approval/user input, idle means ready, and dormant means unloaded.
110
+ Delivery resumes the exact dormant root without retaining history.
111
+ Embassy derives a safe alias from the native name: normalized
112
+ lower-case ASCII tokens, a `codex-` prefix, at most 32 characters before
113
+ `@host`. A missing, `Untitled task`, or native-ID-revealing name gets a stable alias from
114
+ the opaque Embassy endpoint ID, never from the native task ID.
115
+
116
+ Absence from the daemon's loaded list alone never marks an agent unreachable;
117
+ dormant wake is ordinary use. Embassy labels a session unsupported only from
118
+ positive native evidence.
119
+
120
+ `embassy register-codex --alias ...` remains a fallback for harnesses without
121
+ native daemon integration. It uses the caller's inherited `CODEX_THREAD_ID`;
122
+ the ID is not a command argument or public output. A fallback registration is
123
+ the same endpoint kind as discovery, and a matching native identity cannot
124
+ create a duplicate. Each delivery independently attests the current App Server
125
+ interface and exact task before authorization.
126
+ Explicit registration sets a private retention marker, so older roots remain
127
+ listed after restart even outside the discovery window. Window aging preserves
128
+ automatic rows referenced by pending work, but drops unused automatic rows to
129
+ release capacity. No retirement, suppression or settlement occurs. A returning
130
+ root keeps its ID while retained/pending; after pruning it receives a fresh ID,
131
+ and old receipts never retarget. An unnamed root gets a new generated alias
132
+ after pruning. The existing 128-endpoint bound remains.
133
+ No discovered/registered badge is exposed.
134
+ Explicitly registered rows keep their registered aliases through native scans;
135
+ native names drive automatic rows only. A later explicit registration can rename
136
+ the retained row without moving its identity or admitted work.
107
137
  The ellipsis in `--alias ...` is a substitution: use the task's chosen
108
138
  `codex-` name with this machine's exact `@host` suffix.
109
139
 
110
140
  `register-codex --succeeds <old-alias>` atomically retires a predecessor and
111
141
  installs the caller. It never reanchors pending work to a new identity.
112
142
 
143
+ Explicit retirement suppresses re-discovery of that native identity while its
144
+ bounded retirement evidence remains. Embassy never answers approvals or
145
+ changes a task's sandbox or approval policy. It consumes only the App Server
146
+ metadata and operation methods needed for discovery, unsubscribe, resume,
147
+ delivery and exact-turn STEER; it exposes no generic provider RPC.
148
+
113
149
  ## SSH federation
114
150
 
115
151
  Install Embassy and run `embassy service install` on both Macs; for `studio`
@@ -119,8 +155,9 @@ with each peer name matching both the remote inventory's `host` and a working
119
155
  SSH destination or `~/.ssh/config` Host alias.
120
156
 
121
157
  After changing a running broker's inventory, reload it with
122
- `embassy service install`; register `codex-reviewer@laptop` from the live
123
- Codex task on laptop, then ask the Claude session on studio to run
158
+ `embassy service install`; wait for `codex-reviewer@laptop` to appear from the
159
+ Codex daemon on laptop (or use fallback registration), then ask the Claude
160
+ session on studio to run
124
161
  `embassy send --to codex-reviewer@laptop` with the message on stdin.
125
162
 
126
163
  For each configured remote node Embassy runs the fixed system SSH client in
@@ -148,7 +185,7 @@ destination persists its queue before acceptance, and an uncertain result is
148
185
  never replayed.
149
186
 
150
187
  `embassy refresh` observes configured catalogs in parallel with local Claude
151
- discovery. A successful observation replaces that node's bounded display rows
188
+ and Codex discovery. A successful observation replaces that node's bounded display rows
152
189
  and timestamp. A failed observation retains its last rows and records
153
190
  `PEER_TUNNEL_UNAVAILABLE`. `embassy status` reads that snapshot without SSH or
154
191
  provider I/O. Display is capped at 128 remote rows across all nodes; exact and
@@ -200,9 +237,12 @@ before provider setup, so only one broker can run.
200
237
 
201
238
  ## Private state reset
202
239
 
203
- Version 4 accepts only schema-6 `gateway-state.json`. It deliberately contains
204
- no 3.x converter or compatibility reader. An older or unknown schema refuses
205
- with `GATEWAY_STATE_SCHEMA_UNSUPPORTED`; invalid schema-6 bytes refuse with
240
+ This release reads valid schema-6 `gateway-state.json` forward, treating every
241
+ existing row as retained; new writes use schema 7. The retention marker is the
242
+ only added field. Back up state before upgrading 4.2.0; no reset is required,
243
+ but 4.2.0 refuses schema 7 and rollback requires the pre-upgrade backup.
244
+ There is no 3.x converter. Schema ≤5 or unknown schemas refuse with
245
+ `GATEWAY_STATE_SCHEMA_UNSUPPORTED`; malformed accepted schemas refuse with
206
246
  `CORRUPT_GATEWAY_STATE`. Refusal does not mutate the installed file.
207
247
 
208
248
  Reset procedure:
@@ -213,9 +253,11 @@ Reset procedure:
213
253
  serve process) and confirm it is stopped with `embassy service status`.
214
254
  3. Back up and move aside only `gateway-state.json` in that broker's state
215
255
  directory. Keep the valid `nodes.json`.
216
- 4. Install 4.0.0, then run `embassy service install`.
217
- 5. The v4 broker creates fresh schema-6 state.
218
- 6. Re-register Codex tasks. Claude endpoints are recorded on discovery/use.
256
+ 4. Install the current discovery-enabled 4.x release, then run
257
+ `embassy service install`.
258
+ 5. The broker creates fresh schema-7 state.
259
+ 6. Let current Codex agents be discovered. Use fallback registration only for
260
+ non-native harnesses. Claude endpoints are recorded on discovery/use.
219
261
 
220
262
  All state produced by Embassy 3.x is unsupported by 4.x; preserve the matching
221
263
  old binary as well as its old state if rollback may be needed, and never run
package/docs/DELIVERY.md CHANGED
@@ -10,8 +10,10 @@ Its `name@host` alias is a lookup index and display label. A send by name
10
10
  resolves once, before admission. Every later transition and reply uses the
11
11
  endpoint tuple; a rename or replacement cannot retarget old work.
12
12
 
13
- Codex callers must already be registered. A Claude caller is derived from its
14
- inherited native socket and recorded under the exact discovered session UUID.
13
+ Codex callers must already be known through daemon discovery or fallback
14
+ registration. Both paths identify the same endpoint kind by the exact native
15
+ task identity. A Claude caller is derived from its inherited native socket and
16
+ recorded under the exact discovered session UUID.
15
17
  The caller never supplies `--from`. A remote source is supplied by the trusted
16
18
  SSH peer. Its claimed host must be in `nodes.json`, and the message's source
17
19
  host must match that claim. The destination does not wait for a catalog poll
@@ -72,10 +74,17 @@ The receiving Claude session wakes through its native socket.
72
74
  ### Codex destination
73
75
 
74
76
  The broker creates a fresh bounded App Server operation, resumes the exact
75
- registered task without retaining returned history, prepares the input, then
76
- revalidates the registration and operation immediately before the write. The
77
- accepted operation remains attached until its terminal lifetime event so an
78
- active-turn STEER has a valid target.
77
+ known task without retaining returned history, prepares the input, then
78
+ revalidates the endpoint and operation immediately before the write. Dormant
79
+ roots therefore wake through ordinary delivery. The accepted operation remains attached
80
+ until its terminal lifetime event so an active-turn STEER has a valid target.
81
+
82
+ Ordinary messages remain queued while the immediately observed task status is
83
+ active. If another client starts a turn between Embassy's idle check and its
84
+ write, the message enters that turn as steer text; the App Server response
85
+ cannot distinguish this, so the receipt proves acceptance and lifetime only,
86
+ not that a fresh turn started. The same residual race applies to fallback-
87
+ registered tasks. Embassy does not use the App Server's native queue.
79
88
 
80
89
  An exact leading `STEER:` is special only from Claude to Codex. It is delivered
81
90
  through that exact accepted operation's `turn/steer` capability at the next
@@ -111,6 +120,9 @@ broker restart while its bounded retained row and both endpoint identities are
111
120
  still valid. Retirement, replacement, retention expiry, eviction, or state
112
121
  reset makes it unavailable. Conversation references are intentionally not
113
122
  stable across a reset.
123
+ If an unused automatic endpoint is pruned from the discovery window, references
124
+ bound to that identity refuse for the rest of their retention window, even if
125
+ the native thread returns as a new endpoint. Re-address it by its current alias.
114
126
 
115
127
  ## Receipts and retirement
116
128
 
@@ -2,7 +2,7 @@
2
2
 
3
3
  ## Product contract
4
4
 
5
- Embassy connects live Claude Code sessions and registered Codex CLI tasks by
5
+ Embassy connects live Claude Code sessions and Codex CLI agents by
6
6
  name, locally or across directly configured SSH gateways. All four provider
7
7
  pairs are supported. Sending is one `embassy send` command; receiving wakes the
8
8
  target through its native interface. A receipt proves delivery machinery, not
@@ -31,7 +31,7 @@ Claude/Codex CLI
31
31
  remote broker ledger
32
32
  ```
33
33
 
34
- There is one broker per login user and host. The broker owns one schema-6 JSON
34
+ There is one broker per login user and host. The broker owns one schema-7 JSON
35
35
  document and one private control socket. It does not listen on a network port.
36
36
  launchd may supervise the same foreground `serve` entry point.
37
37
 
@@ -52,13 +52,18 @@ and restart. Retirement retains a bounded private hash of the native binding
52
52
  to fence immediate re-enrollment. After that evidence is evicted, a later
53
53
  registration gets a new ID; old replies and remote references cannot revive.
54
54
 
55
- Codex endpoints are explicitly registered by the task that inherits the exact
56
- task UUID. Claude endpoints are discovered by exact session UUID and recorded
55
+ Codex endpoints are discovered as bounded metadata from the same-user App
56
+ Server daemon. The immutable native thread UUID is their private identity;
57
+ native names are mutable lookup aliases for automatic rows; explicitly registered
58
+ rows keep the operator's alias. Only the 20 most recent roots are
59
+ automatically listed, without publishing native IDs. Explicit registration by a
60
+ task that inherits the exact UUID remains a fallback and reconciles with the
61
+ same endpoint row. Claude endpoints are discovered by exact session UUID and recorded
57
62
  when a Claude caller or target is resolved. A same-UUID rename updates one
58
- endpoint; a different identity never inherits work. Two live Claude sessions
59
- may share a display name, but name resolution then refuses with
60
- `PEER_ALIAS_COLLISION`. An exact user-supplied Claude UUID can disambiguate
61
- selection without making UUIDs public output.
63
+ endpoint; a different identity never inherits work. Live endpoints may share
64
+ a display name, but name resolution then refuses with `PEER_ALIAS_COLLISION`.
65
+ An exact user-supplied Claude UUID can disambiguate Claude selection without
66
+ making UUIDs public output.
62
67
  Partial discovery cannot clear an observed collision. The bounded collision
63
68
  proof sets fail closed on overflow until a complete scan; exact UUID lookup
64
69
  remains available. Operator retirement can use `--endpoint <public-id>` when
@@ -69,8 +74,10 @@ and any local cache are bounded and memory-only; neither grants lookup or write
69
74
  authority. Remote endpoint rows contain opaque IDs and aliases, not native
70
75
  handles.
71
76
 
72
- `refresh` runs local Claude discovery and all configured catalog observations
73
- in parallel. Each successful node observation replaces its rows and timestamp.
77
+ `refresh` runs local Claude and Codex discovery and all configured catalog
78
+ observations in parallel. Codex discovery also follows bounded daemon metadata
79
+ events and reconnects with a fresh bounded enumeration after daemon loss. Each
80
+ successful node observation replaces its rows and timestamp.
74
81
  A failure retains the last timestamped rows with `PEER_TUNNEL_UNAVAILABLE`.
75
82
  The status projection reads this cache without network I/O and caps the combined
76
83
  remote display at 128 rows, reporting truncation. Routing still uses the owner
@@ -132,8 +139,8 @@ guessing. The live host lease is checked before a transaction, before
132
139
  persistence, and immediately before rename.
133
140
 
134
141
  No-op transactions write nothing. Unsupported or corrupt state refuses before
135
- mutation. Schema 6 is reset-only; no older loader or converter is linked into
136
- the v4 binary.
142
+ mutation. Valid schema 6 reads forward with all existing rows retained; writes use 7.
143
+ The only added field is the private retention marker. Schema ≤5 still needs a reset.
137
144
 
138
145
  ## Coordinator
139
146
 
@@ -172,10 +179,24 @@ native socket is still used for receive and reply wake-up.
172
179
 
173
180
  ### Codex operation
174
181
 
182
+ One bounded App Server observer enumerates the recency top 20 unarchived root threads,
183
+ combines loaded-state and lifecycle/name events, and retains only the metadata
184
+ used by the endpoint directory. It drains unwanted notifications and
185
+ unsubscribes from threads it is not actively brokering so observation does not
186
+ pin them in memory. Window aging preserves pending identities and drops unused
187
+ automatic rows without settlement or retirement. Explicit registrations remain
188
+ retained across restart. `thread/closed` marks a root dormant, not retired.
189
+ Archive/delete evidence and explicit retirement use existing settlement; operator
190
+ retirement evidence suppresses rediscovery. Identity storage stays bounded.
191
+
175
192
  The Codex adapter creates a fresh App Server connection per operation, checks
176
- the current interface, resumes the exact registered thread with history
177
- excluded, and starts one turn carrying the bounded batch. Returned history and
178
- model output are not retained or forwarded.
193
+ the current interface, resumes the exact known
194
+ thread with history excluded when needed, and starts one turn carrying the
195
+ bounded batch only after an immediate idle-status check. Returned history and
196
+ model output are not retained or forwarded. While active, ordinary messages
197
+ remain in Embassy's ledger. A competing client can start a turn between the
198
+ idle check and write; the indistinguishable App Server response means the
199
+ receipt proves acceptance and lifetime, not that Embassy started a fresh turn.
179
200
 
180
201
  An accepted operation remains tracked until its terminal lifetime notification.
181
202
  An exact leading Claude-to-Codex `STEER:` may use that same accepted
@@ -218,7 +239,7 @@ reset.
218
239
 
219
240
  ## Local control and CLI
220
241
 
221
- The private control protocol is version 5. Each connection carries one bounded
242
+ The private control protocol is version 6. Each connection carries one bounded
222
243
  JSON request and one closed JSON response over the expected private Unix
223
244
  socket. A mutating request whose reply is lost after write reports
224
245
  `CONTROL_WRITE_OUTCOME_AMBIGUOUS`; the CLI does not retry it.
@@ -236,8 +257,9 @@ serve service peer-stdio
236
257
  `send` accepts exactly one of `--to` and `--conversation`; it has no `--from`.
237
258
  Human `status` is a rendering of the same closed body-free JSON shape. Its
238
259
  health word describes control/ledger health, local route rows expose their last
239
- native operation, and the federation section exposes only the last bounded
240
- catalog observation. `health` is a control-path probe. `check` creates temporary
260
+ native operation, and Codex rows expose busy, waiting, idle, dormant or unknown
261
+ status, without parent references or registration-origin labels. The federation section
262
+ exposes only the last bounded catalog observation. `health` is a control-path probe. `check` creates temporary
241
263
  private loopback endpoints and uses the real ledger/coordinator/receipt path,
242
264
  then retires them; no provider or model is contacted. It is not a
243
265
  provider-readiness test.
@@ -261,7 +283,7 @@ Startup order is ownership-sensitive:
261
283
  1. load the private node inventory, or derive a transient first-boot default,
262
284
  and load configuration;
263
285
  2. acquire the fixed host-wide kernel lease;
264
- 3. open and validate schema-6 state without changing the inventory;
286
+ 3. open and validate schema-7 state without changing the inventory;
265
287
  4. atomically install and reload the default inventory when first boot needs
266
288
  one;
267
289
  5. construct native and SSH adapters;
@@ -282,8 +304,8 @@ model interrupt.
282
304
 
283
305
  | Surface | Version | Compatibility policy |
284
306
  |---|---:|---|
285
- | Private state (`gateway-state.json`) | 6 | Reset only; older and unknown schemas refuse without mutation |
286
- | Private control (CLI ↔ broker) | 5 | CLI and broker must come from one installation |
307
+ | Private state (`gateway-state.json`) | 7 | Reset only; older and unknown schemas refuse without mutation |
308
+ | Private control (CLI ↔ broker) | 6 | CLI and broker must come from one installation |
287
309
  | Federation (`peer-stdio`) | 3 | Exact version and host handshake; no compatibility mode |
288
310
  | Consumed Claude peer protocol | 1 | Incompatible records are rejected in isolation |
289
311
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agent-embassy",
3
- "version": "4.2.0",
3
+ "version": "4.4.0",
4
4
  "description": "A local gateway for bidirectional messaging between Claude Code sessions and Codex tasks.",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -57,18 +57,23 @@
57
57
  "probe:codex-remote": "tsx scripts/probe-codex-remote.ts",
58
58
  "pretest": "npm run build",
59
59
  "start": "node dist/src/gateway/core-cli.js serve",
60
- "test": "tsx --test test/*.test.ts",
60
+ "test": "tsx --test --test-timeout=120000 test/*.test.ts",
61
61
  "typecheck": "tsc -p tsconfig.json",
62
62
  "soak": "tsx --test test/soak/core-soak.test.ts"
63
63
  },
64
64
  "engines": {
65
- "node": ">=20"
65
+ "node": ">=22"
66
66
  },
67
67
  "dependencies": {
68
+ "ink": "7.1.1",
69
+ "react": "19.2.8",
70
+ "string-width": "8.2.2",
71
+ "wrap-ansi": "10.0.1",
68
72
  "ws": "8.21.3"
69
73
  },
70
74
  "devDependencies": {
71
75
  "@types/node": "24.10.1",
76
+ "@types/react": "19.2.18",
72
77
  "@types/ws": "8.18.1",
73
78
  "tsx": "4.20.6",
74
79
  "typescript": "5.9.3"
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: embassy-peer
3
- description: Register a Codex task, find named Claude/Codex sessions, and send or reply through an installed Embassy gateway. Use for agent-to-agent messaging and receipts, not provider configuration or direct socket access.
3
+ description: Find named Claude/Codex sessions, use fallback Codex registration when needed, and send or reply through an installed Embassy gateway. Use for agent-to-agent messaging and receipts, not provider configuration or direct socket access.
4
4
  ---
5
5
 
6
6
  # Embassy Peer Gateway
@@ -15,9 +15,9 @@ Healthy means the Embassy control socket and ledger respond; a passing check exe
15
15
 
16
16
  A client reads the private state directory and optional `nodes.json`, then connects to its private Unix socket. A sandboxed task needs read/write access to that directory. Follow denied-access guidance; do not relocate state or start a second broker to bypass it. If access was expected, verify `EMBASSY_STATE_DIR` names this user's own directory.
17
17
 
18
- To receive in Codex, use its managed standalone installation with its App Server daemon already running under the same macOS login; merely having a `codex` executable on PATH is insufficient, and Embassy does not install or start that daemon.
18
+ To receive in Codex, use its managed standalone installation with its App Server daemon already running under the same macOS login; merely having a `codex` executable on PATH is insufficient, and Embassy does not install or start that daemon. The 20 most recent unarchived Codex roots appear automatically in `embassy status`, including dormant roots that resume on delivery. Sub-agents are excluded; explicit fallback registrations remain retained outside that window, including after a broker restart.
19
19
 
20
- Ask the live Codex CLI task to execute the following registration through its shell tool; an ordinary terminal lacks that task's inherited identity:
20
+ For a harness without native daemon integration, ask the live Codex CLI task to execute this fallback registration through its shell tool; an ordinary terminal lacks that task's inherited identity:
21
21
 
22
22
  ```sh
23
23
  embassy register-codex --alias codex-reviewer@your-host
@@ -25,7 +25,7 @@ embassy register-codex --alias codex-reviewer@your-host
25
25
 
26
26
  Read `host` from the `nodes.json` that first boot created and use it as every local `@host` suffix; replace `your-host` with that exact value, not the example `studio` unless you explicitly chose it. `nodes.json` lives inside `EMBASSY_STATE_DIR` when set; otherwise it lives in `$XDG_STATE_HOME/agent-embassy`, or `~/.local/state/agent-embassy` when `XDG_STATE_HOME` is unset; every client shell must use the same state-directory configuration captured by the installed service.
27
27
 
28
- The CLI reads inherited `CODEX_THREAD_ID`; never supply, print, or guess it. Registration performs no provider I/O. Claude callers are identified from inherited `CLAUDE_CODE_MESSAGING_SOCKET` and live registry evidence on first use; there is no separate Claude registration command.
28
+ The CLI reads inherited `CODEX_THREAD_ID`; never supply, print, or guess it. Discovery and fallback registration produce the same endpoint kind and identity. Registration performs no provider I/O. Claude callers are identified from inherited `CLAUDE_CODE_MESSAGING_SOCKET` and live registry evidence on first use; there is no separate Claude registration command.
29
29
 
30
30
  For `CALLER_IDENTITY_CONFLICT`, strip only the unwanted identity at the call site: `env -u CLAUDE_CODE_MESSAGING_SOCKET embassy …` for Codex, or `env -u CODEX_THREAD_ID embassy …` for Claude. Do not read either value or restart the broker to repair the caller's environment.
31
31
 
@@ -33,7 +33,7 @@ Ellipses (`...` or `…`) stand for the intended command and arguments; `conv_RE
33
33
 
34
34
  ## Address, send, reply
35
35
 
36
- `embassy status --json` returns metadata under `.result`: owned routes, recent delivery states, retirements and last operation outcomes. It includes no bodies or native IDs. Human terminal rendering is not a parser contract. `embassy refresh` performs live Claude discovery; run it only when authorized. Named sends resolve directly, including over configured SSH, without requiring prior catalog polling at the destination.
36
+ `embassy status --json` returns metadata under `.result`: owned routes, recent delivery states, retirements and last operation outcomes. It includes no bodies or native IDs. Human terminal rendering is not a parser contract. `embassy refresh` performs live Claude and Codex discovery; run it only when authorized. Named sends resolve directly, including over configured SSH, without requiring prior catalog polling at the destination.
37
37
 
38
38
  Names are lookup indexes, not identities. Stop on `PEER_ALIAS_COLLISION` rather than choosing a session. A Claude UUID may be used as `--to` only when user-supplied; do not discover or echo native IDs. A renamed or replaced endpoint never inherits work addressed to another identity.
39
39
 
@@ -84,7 +84,7 @@ The waiter is bounded by the deadline plus three seconds. A found result has `st
84
84
 
85
85
  Do not resend an ambiguous or unconfirmed delivery. `CONTROL_WRITE_OUTCOME_AMBIGUOUS` also means the operation may have applied: inspect status, do not repeat it. Explicit replies are new messages, not automatic forwarding of Codex output.
86
86
 
87
- Receiving is native: Claude's socket mailbox or Codex's accepted turn. Agents do not poll inbound mail. Ordinary Codex work queues while the task is busy; a bounded backlog is packed into one wake with separate identities, provenance, and receipts. Capacity and deadlines still apply.
87
+ Receiving is native: Claude's socket mailbox or Codex's accepted turn. Agents do not poll inbound mail. Ordinary Codex work queues while the task is observed busy; a bounded backlog is packed into one wake with separate identities, provenance, and receipts. A competing client can start a turn after Embassy's idle check, causing an ordinary message to enter that turn as steer text; the provider response cannot distinguish the race, so the receipt proves acceptance and lifetime, not fresh-turn creation. Capacity and deadlines still apply.
88
88
 
89
89
  Only when explicitly asked to steer, a Claude sender may start the body with exact `STEER:` for an active Codex recipient. Embassy uses that exact turn's same-session capability at the next tool-call boundary, never interrupts, and keeps the three-steer cap and global kill switch. A cleanly unavailable boundary leaves the message queued. Never synthesize STEER, answer approvals, or change a sandbox to force delivery.
90
90