agent-embassy 1.0.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 (145) hide show
  1. package/CHANGELOG.md +61 -0
  2. package/CONTRIBUTING.md +122 -0
  3. package/LICENSE +21 -0
  4. package/README.md +185 -0
  5. package/README.zh-CN.md +185 -0
  6. package/SECURITY.md +224 -0
  7. package/assets/live-dashboard/app.css +1610 -0
  8. package/assets/mark-seal.svg +7 -0
  9. package/assets/mark.svg +7 -0
  10. package/assets/social-preview.png +0 -0
  11. package/assets/vendor/react/LICENSE +21 -0
  12. package/assets/vendor/react/react-dom.production.min.js +267 -0
  13. package/assets/vendor/react/react.production.min.js +31 -0
  14. package/dist/src/errors.d.ts +5 -0
  15. package/dist/src/errors.js +11 -0
  16. package/dist/src/errors.js.map +1 -0
  17. package/dist/src/gateway/claude-compatibility-scratch.d.ts +18 -0
  18. package/dist/src/gateway/claude-compatibility-scratch.js +158 -0
  19. package/dist/src/gateway/claude-compatibility-scratch.js.map +1 -0
  20. package/dist/src/gateway/claude-helper-client.d.ts +43 -0
  21. package/dist/src/gateway/claude-helper-client.js +212 -0
  22. package/dist/src/gateway/claude-helper-client.js.map +1 -0
  23. package/dist/src/gateway/claude-helper-protocol.d.ts +172 -0
  24. package/dist/src/gateway/claude-helper-protocol.js +373 -0
  25. package/dist/src/gateway/claude-helper-protocol.js.map +1 -0
  26. package/dist/src/gateway/claude-helper-supervisor.d.ts +74 -0
  27. package/dist/src/gateway/claude-helper-supervisor.js +497 -0
  28. package/dist/src/gateway/claude-helper-supervisor.js.map +1 -0
  29. package/dist/src/gateway/claude-helper.d.ts +1 -0
  30. package/dist/src/gateway/claude-helper.js +269 -0
  31. package/dist/src/gateway/claude-helper.js.map +1 -0
  32. package/dist/src/gateway/claude-peer.d.ts +273 -0
  33. package/dist/src/gateway/claude-peer.js +2359 -0
  34. package/dist/src/gateway/claude-peer.js.map +1 -0
  35. package/dist/src/gateway/claude-runtime.d.ts +40 -0
  36. package/dist/src/gateway/claude-runtime.js +302 -0
  37. package/dist/src/gateway/claude-runtime.js.map +1 -0
  38. package/dist/src/gateway/cli-copy.d.ts +8 -0
  39. package/dist/src/gateway/cli-copy.en.d.ts +13 -0
  40. package/dist/src/gateway/cli-copy.en.js +43 -0
  41. package/dist/src/gateway/cli-copy.en.js.map +1 -0
  42. package/dist/src/gateway/cli-copy.js +19 -0
  43. package/dist/src/gateway/cli-copy.js.map +1 -0
  44. package/dist/src/gateway/cli-copy.zh-CN.d.ts +13 -0
  45. package/dist/src/gateway/cli-copy.zh-CN.js +43 -0
  46. package/dist/src/gateway/cli-copy.zh-CN.js.map +1 -0
  47. package/dist/src/gateway/cli.d.ts +44 -0
  48. package/dist/src/gateway/cli.js +969 -0
  49. package/dist/src/gateway/cli.js.map +1 -0
  50. package/dist/src/gateway/codex-app-server.d.ts +310 -0
  51. package/dist/src/gateway/codex-app-server.js +1746 -0
  52. package/dist/src/gateway/codex-app-server.js.map +1 -0
  53. package/dist/src/gateway/codex-local-transport.d.ts +81 -0
  54. package/dist/src/gateway/codex-local-transport.js +617 -0
  55. package/dist/src/gateway/codex-local-transport.js.map +1 -0
  56. package/dist/src/gateway/codex-registration-generation.d.ts +5 -0
  57. package/dist/src/gateway/codex-registration-generation.js +19 -0
  58. package/dist/src/gateway/codex-registration-generation.js.map +1 -0
  59. package/dist/src/gateway/codex-registration-succession.d.ts +209 -0
  60. package/dist/src/gateway/codex-registration-succession.js +588 -0
  61. package/dist/src/gateway/codex-registration-succession.js.map +1 -0
  62. package/dist/src/gateway/compatibility.d.ts +70 -0
  63. package/dist/src/gateway/compatibility.js +252 -0
  64. package/dist/src/gateway/compatibility.js.map +1 -0
  65. package/dist/src/gateway/config.d.ts +24 -0
  66. package/dist/src/gateway/config.js +130 -0
  67. package/dist/src/gateway/config.js.map +1 -0
  68. package/dist/src/gateway/control.d.ts +308 -0
  69. package/dist/src/gateway/control.js +1573 -0
  70. package/dist/src/gateway/control.js.map +1 -0
  71. package/dist/src/gateway/dashboard-copy.d.ts +7 -0
  72. package/dist/src/gateway/dashboard-copy.en.d.ts +506 -0
  73. package/dist/src/gateway/dashboard-copy.en.js +507 -0
  74. package/dist/src/gateway/dashboard-copy.en.js.map +1 -0
  75. package/dist/src/gateway/dashboard-copy.js +516 -0
  76. package/dist/src/gateway/dashboard-copy.js.map +1 -0
  77. package/dist/src/gateway/dashboard-copy.zh-CN.d.ts +506 -0
  78. package/dist/src/gateway/dashboard-copy.zh-CN.js +507 -0
  79. package/dist/src/gateway/dashboard-copy.zh-CN.js.map +1 -0
  80. package/dist/src/gateway/dashboard-model.d.ts +207 -0
  81. package/dist/src/gateway/dashboard-model.js +720 -0
  82. package/dist/src/gateway/dashboard-model.js.map +1 -0
  83. package/dist/src/gateway/dashboard.d.ts +26 -0
  84. package/dist/src/gateway/dashboard.js +941 -0
  85. package/dist/src/gateway/dashboard.js.map +1 -0
  86. package/dist/src/gateway/delivery-machine.d.ts +235 -0
  87. package/dist/src/gateway/delivery-machine.js +540 -0
  88. package/dist/src/gateway/delivery-machine.js.map +1 -0
  89. package/dist/src/gateway/instance-lease.d.ts +21 -0
  90. package/dist/src/gateway/instance-lease.js +549 -0
  91. package/dist/src/gateway/instance-lease.js.map +1 -0
  92. package/dist/src/gateway/live-dashboard-app/app.js +2914 -0
  93. package/dist/src/gateway/live-dashboard-assets.d.ts +10 -0
  94. package/dist/src/gateway/live-dashboard-assets.js +73 -0
  95. package/dist/src/gateway/live-dashboard-assets.js.map +1 -0
  96. package/dist/src/gateway/live-dashboard-bootstrap.d.ts +36 -0
  97. package/dist/src/gateway/live-dashboard-bootstrap.js +176 -0
  98. package/dist/src/gateway/live-dashboard-bootstrap.js.map +1 -0
  99. package/dist/src/gateway/live-dashboard-command.d.ts +54 -0
  100. package/dist/src/gateway/live-dashboard-command.js +324 -0
  101. package/dist/src/gateway/live-dashboard-command.js.map +1 -0
  102. package/dist/src/gateway/live-dashboard-http.d.ts +41 -0
  103. package/dist/src/gateway/live-dashboard-http.js +445 -0
  104. package/dist/src/gateway/live-dashboard-http.js.map +1 -0
  105. package/dist/src/gateway/live-dashboard-protocol.d.ts +38 -0
  106. package/dist/src/gateway/live-dashboard-protocol.js +156 -0
  107. package/dist/src/gateway/live-dashboard-protocol.js.map +1 -0
  108. package/dist/src/gateway/live-dashboard-server.d.ts +33 -0
  109. package/dist/src/gateway/live-dashboard-server.js +130 -0
  110. package/dist/src/gateway/live-dashboard-server.js.map +1 -0
  111. package/dist/src/gateway/live-dashboard-stream.d.ts +46 -0
  112. package/dist/src/gateway/live-dashboard-stream.js +233 -0
  113. package/dist/src/gateway/live-dashboard-stream.js.map +1 -0
  114. package/dist/src/gateway/live-dashboard.d.ts +31 -0
  115. package/dist/src/gateway/live-dashboard.js +190 -0
  116. package/dist/src/gateway/live-dashboard.js.map +1 -0
  117. package/dist/src/gateway/locale.d.ts +4 -0
  118. package/dist/src/gateway/locale.js +10 -0
  119. package/dist/src/gateway/locale.js.map +1 -0
  120. package/dist/src/gateway/progress-watch-machine.d.ts +97 -0
  121. package/dist/src/gateway/progress-watch-machine.js +172 -0
  122. package/dist/src/gateway/progress-watch-machine.js.map +1 -0
  123. package/dist/src/gateway/providers.d.ts +287 -0
  124. package/dist/src/gateway/providers.js +2451 -0
  125. package/dist/src/gateway/providers.js.map +1 -0
  126. package/dist/src/gateway/server.d.ts +57 -0
  127. package/dist/src/gateway/server.js +264 -0
  128. package/dist/src/gateway/server.js.map +1 -0
  129. package/dist/src/gateway/service.d.ts +449 -0
  130. package/dist/src/gateway/service.js +4831 -0
  131. package/dist/src/gateway/service.js.map +1 -0
  132. package/dist/src/gateway/store.d.ts +340 -0
  133. package/dist/src/gateway/store.js +4047 -0
  134. package/dist/src/gateway/store.js.map +1 -0
  135. package/dist/src/gateway/types.d.ts +514 -0
  136. package/dist/src/gateway/types.js +414 -0
  137. package/dist/src/gateway/types.js.map +1 -0
  138. package/dist/src/mutex.d.ts +4 -0
  139. package/dist/src/mutex.js +23 -0
  140. package/dist/src/mutex.js.map +1 -0
  141. package/docs/DESIGN.md +134 -0
  142. package/docs/GATEWAY-ARCHITECTURE.md +858 -0
  143. package/package.json +80 -0
  144. package/skills/embassy-peer/SKILL.md +198 -0
  145. package/skills/embassy-peer/agents/openai.yaml +4 -0
package/package.json ADDED
@@ -0,0 +1,80 @@
1
+ {
2
+ "name": "agent-embassy",
3
+ "version": "1.0.0",
4
+ "description": "A local gateway for bidirectional messaging between Claude Code sessions and Codex tasks.",
5
+ "license": "MIT",
6
+ "repository": {
7
+ "type": "git",
8
+ "url": "git+https://github.com/YuanpingSong/embassy.git"
9
+ },
10
+ "bugs": {
11
+ "url": "https://github.com/YuanpingSong/embassy/issues"
12
+ },
13
+ "homepage": "https://github.com/YuanpingSong/embassy#readme",
14
+ "keywords": [
15
+ "ai-agents",
16
+ "gateway",
17
+ "claude-code",
18
+ "codex",
19
+ "multi-agent"
20
+ ],
21
+ "packageManager": "npm@10.9.8",
22
+ "type": "module",
23
+ "os": [
24
+ "darwin"
25
+ ],
26
+ "bin": {
27
+ "embassy": "dist/src/gateway/cli.js",
28
+ "claude-codex-gateway": "dist/src/gateway/cli.js"
29
+ },
30
+ "files": [
31
+ "dist/src/gateway",
32
+ "dist/src/errors.js",
33
+ "dist/src/errors.js.map",
34
+ "dist/src/errors.d.ts",
35
+ "dist/src/mutex.js",
36
+ "dist/src/mutex.js.map",
37
+ "dist/src/mutex.d.ts",
38
+ "assets/mark-seal.svg",
39
+ "assets/mark.svg",
40
+ "assets/social-preview.png",
41
+ "skills/embassy-peer",
42
+ "docs/DESIGN.md",
43
+ "docs/GATEWAY-ARCHITECTURE.md",
44
+ "CHANGELOG.md",
45
+ "CONTRIBUTING.md",
46
+ "README.md",
47
+ "README.zh-CN.md",
48
+ "SECURITY.md",
49
+ "LICENSE",
50
+ "assets/live-dashboard",
51
+ "assets/vendor/react"
52
+ ],
53
+ "scripts": {
54
+ "build": "npm run clean && tsc -p tsconfig.build.json && tsc -p src/gateway/live-dashboard-app/tsconfig.json",
55
+ "check": "npm run typecheck && npm test",
56
+ "clean": "node -e \"require('node:fs').rmSync('dist',{recursive:true,force:true})\"",
57
+ "embassy": "node dist/src/gateway/cli.js",
58
+ "prepack": "npm run build",
59
+ "probe:codex-local": "tsx scripts/probe-codex-local.ts",
60
+ "probe:codex-remote": "tsx scripts/probe-codex-remote.ts",
61
+ "pretest": "npm run build",
62
+ "start": "node dist/src/gateway/cli.js serve",
63
+ "test": "tsx --test test/*.test.ts",
64
+ "typecheck": "tsc -p tsconfig.json && tsc -p src/gateway/live-dashboard-app/tsconfig.json --noEmit"
65
+ },
66
+ "engines": {
67
+ "node": ">=20"
68
+ },
69
+ "dependencies": {
70
+ "ws": "8.21.3"
71
+ },
72
+ "devDependencies": {
73
+ "@types/node": "24.10.1",
74
+ "@types/react": "18.3.12",
75
+ "@types/ws": "8.18.1",
76
+ "tsx": "4.20.6",
77
+ "typescript": "5.9.3"
78
+ },
79
+ "author": "Yuanping Song <yuanping.song@outlook.com>"
80
+ }
@@ -0,0 +1,198 @@
1
+ ---
2
+ name: embassy-peer
3
+ description: Operate Embassy through current name@host or Claude session-UUID selectors. Use when a Codex task needs to register for native inbound messaging, list available peers, open the local dashboard, pair with and message a Claude session, or unregister without exposing provider credentials, socket paths, or message bodies.
4
+ ---
5
+
6
+ # Embassy Peer Gateway
7
+
8
+ Use only the installed `embassy` CLI. Treat it as the sole facade over the private, local Embassy control socket. Keep this skill repo-scoped; do not install, copy, or modify provider configuration.
9
+
10
+ Provider-authorized mutations require exactly one inherited principal. Stop on missing or dual Codex/Claude identity; never choose one on the caller's behalf. Operator-only `serve`, health, status, refresh, select, and unselect commands do not infer a provider principal. `pair` and `unpair` carry the inherited `CODEX_THREAD_ID` as attestation when run inside a Codex task and otherwise fail closed; only the authenticated live dashboard creates or removes an edge without attestation.
11
+
12
+ ## Select a peer
13
+
14
+ Address a Claude session by its latest `name@host` or by a user-supplied native session UUID. The UUID is the stable identity; the name is only the current live index. The gateway stores no historical names, so an old name stops resolving immediately after a rename. The shipped launcher accepts only `this-mac`; remote connectors are deferred. Ask the user to choose a selector when it is ambiguous.
15
+
16
+ Run `embassy status` to read the current snapshot. Run `embassy refresh-dashboard` when passive live discovery is authorized. Claude Code's native `ListAgents` includes genuine Claude sessions plus each explicitly advertised `codex-*` Embassy peer.
17
+
18
+ Read the status snapshot's `availablePeers` as sanitized current-name candidates. Native `codex-*` gateway advertisements are excluded because they are not Claude destinations. A send never pairs with a Claude session automatically. Create the exact user-chosen edge with `pair` — or the one-task shorthand `select-claude` — before sending; an unpaired destination is not routable.
19
+
20
+ Accept a Claude session UUID only when the user supplies it or it is already part of the current task context. Never discover one by scanning history or configuration, and never infer a peer from a thread ID, process ID, working directory, socket path, or title.
21
+
22
+ ## Check the gateway
23
+
24
+ Run this before a state-changing operation:
25
+
26
+ ```sh
27
+ embassy health
28
+ ```
29
+
30
+ If Embassy is unavailable, stop and report that it must be started in a trusted local terminal with `embassy serve`. `GATEWAY_INSTANCE_IN_USE` means an Embassy or recognized legacy lock already owns this login account; stop that foreground process rather than changing `EMBASSY_STATE_DIR`. If no legacy process remains, the operator may remove only the exact stale legacy controller lock and retry. Do not launch a background copy, retry in a loop, discover sockets, or fall back to a provider CLI.
31
+
32
+ List the public snapshot:
33
+
34
+ ```sh
35
+ embassy status
36
+ ```
37
+
38
+ Regenerate the metadata-only dashboard:
39
+
40
+ ```sh
41
+ embassy refresh-dashboard
42
+ ```
43
+
44
+ Run that refresh only at the passive-discovery authorization stage. Treat the response as a normalized refresh result; it does not reveal the path. The operator-facing page is `gateway-dashboard.html` in the configured state directory, by default `~/.local/state/agent-embassy/`. Use the operator's configured location when it differs. Do not search for the file or scan controller-owned paths.
45
+
46
+ ## Pair with a Claude session
47
+
48
+ Create one explicit Claude↔Codex edge by naming both ends. The Claude end must be a user-chosen, unique candidate from `availablePeers`:
49
+
50
+ ```sh
51
+ embassy pair --claude advisor@this-mac --codex codex-reviewer@this-mac
52
+ ```
53
+
54
+ Pairs are additive and bounded; many edges may coexist, and `pair` never retires another edge. Run `pair` and `unpair` from inside a registered Codex task so the CLI reads the inherited `CODEX_THREAD_ID`; a plain operator shell fails closed with `CODEX_IDENTITY_REQUIRED` — use the live dashboard or the one-task shorthand instead. Remove exactly the named edge:
55
+
56
+ ```sh
57
+ embassy unpair --claude advisor@this-mac --codex codex-reviewer@this-mac
58
+ ```
59
+
60
+ When the Codex end is unambiguous — inherited from the calling task, or the sole registered task — the one-task shorthand forms or removes the same edge:
61
+
62
+ ```sh
63
+ embassy select-claude --alias advisor@this-mac
64
+ ```
65
+
66
+ Or address the same logical session directly by UUID:
67
+
68
+ ```sh
69
+ embassy select-claude --session 123e4567-e89b-42d3-a456-426614174000
70
+ ```
71
+
72
+ Remove the same one-task edge by naming the Claude endpoint:
73
+
74
+ ```sh
75
+ embassy unselect-claude --alias advisor@this-mac
76
+ ```
77
+
78
+ With zero or several possible Codex ends, the shorthands fail closed and name the explicit verb; never guess an end on the caller's behalf.
79
+
80
+ Let the gateway resolve either selector against the current genuine Claude discovery snapshot. It refreshes process and socket coordinates by UUID; those transport details are never caller inputs. If discovery is ambiguous, incompatible, or unavailable, stop on the result.
81
+
82
+ If the paired session is offline or was renamed while Embassy was stopped, the user may instead supply its UUID with `--session`. Pairing and removal manage only the gateway edge. They do not start, interrupt, configure, or terminate Claude Code.
83
+
84
+ ## Register a Codex task
85
+
86
+ Register only from the Codex task being named:
87
+
88
+ ```sh
89
+ embassy register-codex --alias codex-reviewer@this-mac
90
+ ```
91
+
92
+ Let the CLI read that task's inherited `CODEX_THREAD_ID`. Never supply the thread ID as an argument, print it, persist it, or register another task by guessing its identity. The alias must start with `codex-`; a successful registration advertises that task for native inbound turns.
93
+
94
+ The first successful Codex registration fixes its exact alias, task, and host
95
+ until it is explicitly succeeded. Exact re-registration remains available for
96
+ connector recovery. To hand the registration to a different task on the same
97
+ host, run this from inside the successor task:
98
+
99
+ ```sh
100
+ embassy register-codex --alias codex-successor@this-mac --succeeds codex-reviewer@this-mac
101
+ ```
102
+
103
+ This is the only supported identity change without restarting the broker.
104
+ Embassy freezes the outgoing route, drains its accepted work to terminal
105
+ settlement, and publishes the successor on a fresh listener generation.
106
+ Nothing transfers: no queued body, conversation, reply capability, or delivery
107
+ token. A succession that cannot be completed pins the identity fail-closed
108
+ until manual recovery rather than leaving two live registrations.
109
+
110
+ Embassy also pins the exact identity fail-closed when a retained route cannot fully reactivate or a fresh registration cannot confirm complete rollback. Retry only that exact identity; choose another only after the old route is confirmed unregistered and Embassy is restarted.
111
+
112
+ Unregister from the same Codex task:
113
+
114
+ ```sh
115
+ embassy unregister-codex --alias codex-reviewer@this-mac
116
+ ```
117
+
118
+ If the task identity or selector does not match, stop on the fail-closed result.
119
+
120
+ ## Send a message
121
+
122
+ Pass a non-empty UTF-8 body through standard input. Never place message text in a gateway argument or a temporary file.
123
+
124
+ From a registered Codex task to a paired Claude session:
125
+
126
+ ```sh
127
+ embassy send-to-claude \
128
+ --from codex-reviewer@this-mac \
129
+ --to advisor@this-mac <<'GATEWAY_MESSAGE'
130
+ Please review the current approach and note the main risk in your own session.
131
+ GATEWAY_MESSAGE
132
+ ```
133
+
134
+ The `--to` value may instead be the session UUID. The current name and UUID
135
+ address the same logical route; a former name is not retained as an alias.
136
+
137
+ Let the CLI read the current `CODEX_THREAD_ID`; do not inspect or forward it.
138
+
139
+ The foreground launcher supports native bidirectional messaging for each explicitly registered `codex-*` task. Claude discovers them with native `ListAgents` and sends with native `SendMessage`. In default paired mode, a task accepts only compatible live Claude sessions holding an explicit pair edge with it; every other sender settles terminally with `SENDER_NOT_PAIRED`. `embassy serve --inbound open` is the explicit operator opt-out that accepts any compatible live same-UID session. The Codex task's existing native approval and sandbox policy governs an accepted turn. Claude Code's `crossSessionInbound` controls messages entering the paired Claude session, including Embassy's outbound Codex-to-Claude delivery. Embassy starts the Codex turn and returns its final reply to the originating Claude session.
140
+
141
+ An accepted send returns a public conversation token and a fresh delivery token. The delivery token is an opaque, memory-only correlation handle, exactly `dlv_` plus 24 base64url characters. Copy the exact returned value; do not construct, shorten, log, or persist it.
142
+
143
+ Use exactly one send for one user-authorized message. A send never selects a Claude session automatically. Do not automatically retry, fan out, hand-roll a poll loop, or fall back to Claude Code's native `SendMessage`.
144
+
145
+ ## Reply to a conversation
146
+
147
+ Use the exact public conversation token returned by the gateway; do not construct one:
148
+
149
+ ```sh
150
+ embassy reply \
151
+ --conversation conv_REPLACE_WITH_RETURNED_TOKEN \
152
+ --alias codex-reviewer@this-mac <<'GATEWAY_MESSAGE'
153
+ Here is the requested adjustment.
154
+ GATEWAY_MESSAGE
155
+ ```
156
+
157
+ The CLI infers the caller from the inherited environment. In a Codex task it uses `CODEX_THREAD_ID`; in Claude Code it uses `CLAUDE_CODE_MESSAGING_SOCKET` transiently. Never echo it or pass it as an argument. If both identities or neither identity are present, stop on the fail-closed result instead of selecting one.
158
+
159
+ An accepted reply returns its own fresh delivery token under the same rules as a send.
160
+
161
+ ## Check or wait for delivery
162
+
163
+ Use the exact delivery token returned by the accepted send or reply. For one current observation, run:
164
+
165
+ ```sh
166
+ embassy delivery-status --token dlv_0123456789abcdefghijklmn
167
+ ```
168
+
169
+ The token above is a format-only placeholder. Substitute the exact returned token. The result is either `{"found":false}` or a found result with `state`, `terminal`, `updatedAt`, and `deadlineAt`, plus optional `pendingForMs` and `safeErrorCode`. `pendingForMs` is age since gateway acceptance, including time spent in flight. The closed state vocabulary is `queued`, `stalled`, `delivered`, `expired`, `failed`, `ambiguous`, and `cancelled`. Only `queued` and `stalled` are nonterminal.
170
+
171
+ When the user explicitly asks to wait for finality, run the bounded waiter once:
172
+
173
+ ```sh
174
+ embassy wait-delivery --token dlv_0123456789abcdefghijklmn
175
+ ```
176
+
177
+ It checks every 250 ms and emits only a terminal result. It stops at the delivery deadline plus 3 seconds; an unknown token fails immediately. Exit `0` means `delivered`; every other terminal state (`expired`, `failed`, `ambiguous`, or `cancelled`) preserves its exact JSON result and uses the shared delivery-failure exit `6`. An unknown token exits `3`. A local waiter timeout exits `4`, is not a terminal result, and is not permission to resend. A terminal result closes only that delivery attempt: `delivered` does not promise a reply, and `ambiguous` must never be retried automatically.
178
+
179
+ The in-memory status table is bounded. Under pressure, only its oldest terminal handle may be evicted; active `queued` or `stalled` handles are retained. An evicted handle returns `{"found":false}`.
180
+
181
+ ## Interpret queue state
182
+
183
+ Treat `accepted` as gateway ownership, not proof that the peer read or answered the message. Use `delivery-status` for the accepted delivery, or `status` and the dashboard for aggregate route state, when the user asks for progress. The optional `pendingForMs` field is age since acceptance, including in-flight time. `stalled` remains nonterminal. For native Claude-to-Codex ingress, Embassy first attempts immediate dispatch. A terminal result observed before the one-second prompt boundary produces only its terminal acknowledgement; native `held` is sent only when the body truly remains queued or dispatch is still nonterminal at that boundary, followed later by the terminal acknowledgement. Claude's rendered “approved and released” notice means only that the paired-consent gateway accepted and released the body to the recipient queue — released is not read, and no human approval is implied. The default `merged` notice policy separately sends at most one nonterminal stall user frame exactly at `floor(messageDeadlineMs / 2)`, containing only a bounded pending age and allowlisted reason. The operator may choose `verbose` to retain the additional terminal diagnostic user frame or `quiet` to suppress gateway-authored user-frame notices; native status and dashboard truth do not change. Ordinary work queues while the Codex task is active or temporarily unavailable. Only when the user explicitly asks to steer the active Codex turn may a Claude sender put the exact prefix `STEER:` at the beginning of the body. Embassy submits that input at the next tool-call boundary, never mid-generation or by interrupting; clean boundary refusal silently returns it to the normal queue. At most three steering messages remain queued per route, and the dashboard journal labels their lifecycle with `STEER`. If a registered Codex connector is closed or faulted, an explicit `register-codex` replaces it and wakes held work when the recovered route is idle; it never retries an ambiguous write.
184
+
185
+ Do not synthesize `STEER:`, use it from Codex to Claude, approve permissions, widen tools, alter inbound-message policy, or interrupt a turn to force delivery. Report `held`, refused, incompatible, full, expired, unavailable, or `STEER_QUEUE_SUPERSEDED` outcomes or safe error codes without treating them as additional `delivery-status` states and without retrying. Native receipt settlement follows the originating Claude session's stable UUID and revalidates its current endpoint before every stall or terminal write; names, PIDs, and sockets are not receipt identity. Ordinary process/socket rotation for the same Claude UUID is therefore refreshed automatically. After a gateway restart, the prior UUID-bound selection starts stale, but the next authorized complete discovery may reactivate exactly that UUID and adopt its latest name. A changed UUID, name or UUID collision, incomplete discovery, or failed workspace/provider revalidation stays stale; do not retry around it. Queued or in-flight text, callbacks, native receipt handles, delivery tokens/status trackers, pending replies, and conversation capabilities do not survive. A pre-restart delivery token is unknown and no body is replayed.
186
+
187
+ ## Preserve the boundary
188
+
189
+ - Keep the gateway local, single-user, and non-hosted.
190
+ - Keep the shipped launcher local-host-only.
191
+ - Never read provider credentials, authentication state, history, settings, registries, raw sockets, or Keychain entries.
192
+ - Publish only each registered `codex-*` peer record owned by the gateway and remove it on shutdown.
193
+ - Never print or copy discovered provider-native identifiers, callback addresses, raw message bodies, tool data, or stderr into skill output or an agent-created file. A user-supplied Claude session UUID may be passed unchanged as an explicit selector, but do not echo it in the normalized result. The gateway may retain the UUID in its closed, mode-0600 private route-binding state.
194
+ - Never modify Claude or Codex permissions, hooks, plugins, agents, MCP configuration, or settings.
195
+ - Return only the CLI's concise public outcome: selectors, normalized state, a public conversation token, or an opaque delivery correlation handle when present.
196
+
197
+
198
+ Agents do not use the live dashboard; it is an operator-facing browser surface whose only mutations are explicitly confirmed two-endpoint pair, unpair, and refresh-discovery actions. It has no registration, send, reply, approval, interruption, settings, or generic provider authority. Agent-facing paths remain `embassy status` for a sanitized snapshot and the static `gateway-dashboard.html` for offline metadata. A status snapshot observation may settle already-due lifecycle deliveries before projecting state.
@@ -0,0 +1,4 @@
1
+ interface:
2
+ display_name: "Embassy Peer Gateway"
3
+ short_description: "Message selected Claude and registered Codex peers"
4
+ default_prompt: "Use $embassy-peer to register this task and message a selected name@host peer safely."