agent-embassy 2.0.1 → 3.1.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 (147) hide show
  1. package/CHANGELOG.md +77 -0
  2. package/CONTRIBUTING.md +23 -36
  3. package/README.md +123 -222
  4. package/SECURITY.md +72 -93
  5. package/dist/src/errors.d.ts +10 -1
  6. package/dist/src/errors.js +3 -1
  7. package/dist/src/errors.js.map +1 -1
  8. package/dist/src/gateway/claude-helper-protocol.d.ts +8 -11
  9. package/dist/src/gateway/claude-helper-protocol.js +12 -11
  10. package/dist/src/gateway/claude-helper-protocol.js.map +1 -1
  11. package/dist/src/gateway/claude-helper-supervisor.d.ts +1 -5
  12. package/dist/src/gateway/claude-helper-supervisor.js +45 -17
  13. package/dist/src/gateway/claude-helper-supervisor.js.map +1 -1
  14. package/dist/src/gateway/claude-helper.js +6 -6
  15. package/dist/src/gateway/claude-helper.js.map +1 -1
  16. package/dist/src/gateway/claude-peer.d.ts +0 -3
  17. package/dist/src/gateway/claude-peer.js +7 -19
  18. package/dist/src/gateway/claude-peer.js.map +1 -1
  19. package/dist/src/gateway/cli.d.ts +17 -7
  20. package/dist/src/gateway/cli.js +945 -265
  21. package/dist/src/gateway/cli.js.map +1 -1
  22. package/dist/src/gateway/codex-socket-holder.d.ts +26 -0
  23. package/dist/src/gateway/codex-socket-holder.js +76 -0
  24. package/dist/src/gateway/codex-socket-holder.js.map +1 -0
  25. package/dist/src/gateway/codex-stateless-transport.js +1 -1
  26. package/dist/src/gateway/codex-stateless-transport.js.map +1 -1
  27. package/dist/src/gateway/config.d.ts +1 -10
  28. package/dist/src/gateway/config.js +4 -10
  29. package/dist/src/gateway/config.js.map +1 -1
  30. package/dist/src/gateway/control.d.ts +66 -80
  31. package/dist/src/gateway/control.js +92 -147
  32. package/dist/src/gateway/control.js.map +1 -1
  33. package/dist/src/gateway/federation-nodes.d.ts +29 -2
  34. package/dist/src/gateway/federation-nodes.js +177 -7
  35. package/dist/src/gateway/federation-nodes.js.map +1 -1
  36. package/dist/src/gateway/peer-client.d.ts +4 -3
  37. package/dist/src/gateway/peer-client.js +22 -13
  38. package/dist/src/gateway/peer-client.js.map +1 -1
  39. package/dist/src/gateway/peer-protocol.d.ts +13 -11
  40. package/dist/src/gateway/peer-protocol.js +14 -12
  41. package/dist/src/gateway/peer-protocol.js.map +1 -1
  42. package/dist/src/gateway/provenance-envelope.d.ts +0 -1
  43. package/dist/src/gateway/provenance-envelope.js +4 -19
  44. package/dist/src/gateway/provenance-envelope.js.map +1 -1
  45. package/dist/src/gateway/providers.d.ts +11 -7
  46. package/dist/src/gateway/providers.js +49 -50
  47. package/dist/src/gateway/providers.js.map +1 -1
  48. package/dist/src/gateway/server.d.ts +4 -14
  49. package/dist/src/gateway/server.js +32 -54
  50. package/dist/src/gateway/server.js.map +1 -1
  51. package/dist/src/gateway/service-agent.d.ts +187 -0
  52. package/dist/src/gateway/service-agent.js +758 -0
  53. package/dist/src/gateway/service-agent.js.map +1 -0
  54. package/dist/src/gateway/service.d.ts +119 -38
  55. package/dist/src/gateway/service.js +754 -798
  56. package/dist/src/gateway/service.js.map +1 -1
  57. package/dist/src/gateway/status-view.d.ts +119 -0
  58. package/dist/src/gateway/status-view.js +484 -0
  59. package/dist/src/gateway/status-view.js.map +1 -0
  60. package/dist/src/gateway/store.d.ts +106 -21
  61. package/dist/src/gateway/store.js +463 -537
  62. package/dist/src/gateway/store.js.map +1 -1
  63. package/dist/src/gateway/types.d.ts +64 -102
  64. package/dist/src/gateway/types.js +40 -86
  65. package/dist/src/gateway/types.js.map +1 -1
  66. package/docs/CONFIGURATION.md +174 -45
  67. package/docs/DELIVERY.md +11 -11
  68. package/docs/GATEWAY-ARCHITECTURE.md +292 -384
  69. package/package.json +4 -12
  70. package/skills/embassy-peer/SKILL.md +69 -92
  71. package/skills/embassy-peer/agents/openai.yaml +1 -1
  72. package/README.zh-CN.md +0 -275
  73. package/assets/live-dashboard/app.css +0 -1619
  74. package/assets/vendor/react/LICENSE +0 -21
  75. package/assets/vendor/react/react-dom.production.min.js +0 -267
  76. package/assets/vendor/react/react.production.min.js +0 -31
  77. package/dist/src/gateway/acp-client.d.ts +0 -110
  78. package/dist/src/gateway/acp-client.js +0 -407
  79. package/dist/src/gateway/acp-client.js.map +0 -1
  80. package/dist/src/gateway/acp-provider.d.ts +0 -66
  81. package/dist/src/gateway/acp-provider.js +0 -275
  82. package/dist/src/gateway/acp-provider.js.map +0 -1
  83. package/dist/src/gateway/claude-helper-client.d.ts +0 -2
  84. package/dist/src/gateway/claude-helper-client.js +0 -2
  85. package/dist/src/gateway/claude-helper-client.js.map +0 -1
  86. package/dist/src/gateway/cli-copy.d.ts +0 -8
  87. package/dist/src/gateway/cli-copy.en.d.ts +0 -22
  88. package/dist/src/gateway/cli-copy.en.js +0 -62
  89. package/dist/src/gateway/cli-copy.en.js.map +0 -1
  90. package/dist/src/gateway/cli-copy.js +0 -27
  91. package/dist/src/gateway/cli-copy.js.map +0 -1
  92. package/dist/src/gateway/cli-copy.zh-CN.d.ts +0 -22
  93. package/dist/src/gateway/cli-copy.zh-CN.js +0 -62
  94. package/dist/src/gateway/cli-copy.zh-CN.js.map +0 -1
  95. package/dist/src/gateway/codex-doctor.d.ts +0 -36
  96. package/dist/src/gateway/codex-doctor.js +0 -127
  97. package/dist/src/gateway/codex-doctor.js.map +0 -1
  98. package/dist/src/gateway/dashboard-copy.d.ts +0 -7
  99. package/dist/src/gateway/dashboard-copy.en.d.ts +0 -504
  100. package/dist/src/gateway/dashboard-copy.en.js +0 -505
  101. package/dist/src/gateway/dashboard-copy.en.js.map +0 -1
  102. package/dist/src/gateway/dashboard-copy.js +0 -514
  103. package/dist/src/gateway/dashboard-copy.js.map +0 -1
  104. package/dist/src/gateway/dashboard-copy.zh-CN.d.ts +0 -504
  105. package/dist/src/gateway/dashboard-copy.zh-CN.js +0 -505
  106. package/dist/src/gateway/dashboard-copy.zh-CN.js.map +0 -1
  107. package/dist/src/gateway/dashboard-model.d.ts +0 -343
  108. package/dist/src/gateway/dashboard-model.js +0 -1061
  109. package/dist/src/gateway/dashboard-model.js.map +0 -1
  110. package/dist/src/gateway/dashboard.d.ts +0 -20
  111. package/dist/src/gateway/dashboard.js +0 -874
  112. package/dist/src/gateway/dashboard.js.map +0 -1
  113. package/dist/src/gateway/deepseek-detect.d.ts +0 -14
  114. package/dist/src/gateway/deepseek-detect.js +0 -41
  115. package/dist/src/gateway/deepseek-detect.js.map +0 -1
  116. package/dist/src/gateway/live-dashboard-app/app.js +0 -2385
  117. package/dist/src/gateway/live-dashboard-assets.d.ts +0 -10
  118. package/dist/src/gateway/live-dashboard-assets.js +0 -74
  119. package/dist/src/gateway/live-dashboard-assets.js.map +0 -1
  120. package/dist/src/gateway/live-dashboard-command.d.ts +0 -60
  121. package/dist/src/gateway/live-dashboard-command.js +0 -334
  122. package/dist/src/gateway/live-dashboard-command.js.map +0 -1
  123. package/dist/src/gateway/live-dashboard-http.d.ts +0 -39
  124. package/dist/src/gateway/live-dashboard-http.js +0 -383
  125. package/dist/src/gateway/live-dashboard-http.js.map +0 -1
  126. package/dist/src/gateway/live-dashboard-protocol.d.ts +0 -34
  127. package/dist/src/gateway/live-dashboard-protocol.js +0 -114
  128. package/dist/src/gateway/live-dashboard-protocol.js.map +0 -1
  129. package/dist/src/gateway/live-dashboard-server.d.ts +0 -33
  130. package/dist/src/gateway/live-dashboard-server.js +0 -144
  131. package/dist/src/gateway/live-dashboard-server.js.map +0 -1
  132. package/dist/src/gateway/live-dashboard-stream.d.ts +0 -46
  133. package/dist/src/gateway/live-dashboard-stream.js +0 -234
  134. package/dist/src/gateway/live-dashboard-stream.js.map +0 -1
  135. package/dist/src/gateway/live-dashboard.d.ts +0 -28
  136. package/dist/src/gateway/live-dashboard.js +0 -154
  137. package/dist/src/gateway/live-dashboard.js.map +0 -1
  138. package/dist/src/gateway/locale.d.ts +0 -4
  139. package/dist/src/gateway/locale.js +0 -10
  140. package/dist/src/gateway/locale.js.map +0 -1
  141. package/dist/src/gateway/progress-watch-machine.d.ts +0 -45
  142. package/dist/src/gateway/progress-watch-machine.js +0 -70
  143. package/dist/src/gateway/progress-watch-machine.js.map +0 -1
  144. package/docs/CONFIGURATION.zh-CN.md +0 -97
  145. package/docs/DASHBOARD.md +0 -98
  146. package/docs/DASHBOARD.zh-CN.md +0 -49
  147. package/docs/DELIVERY.zh-CN.md +0 -55
package/README.md CHANGED
@@ -1,7 +1,5 @@
1
- [English](README.md) · [简体中文](README.zh-CN.md)
2
-
3
1
  <p align="center">
4
- <img src="https://raw.githubusercontent.com/YuanpingSong/embassy/main/assets/social-preview.png" alt="Embassy — a local gateway for bidirectional messaging between Claude Code sessions and Codex desktop tasks" width="720">
2
+ <img src="https://raw.githubusercontent.com/YuanpingSong/embassy/main/assets/social-preview.png" alt="Embassy — a local gateway for messaging between Claude Code sessions and Codex CLI tasks" width="720">
5
3
  </p>
6
4
 
7
5
  # Embassy
@@ -12,294 +10,197 @@
12
10
  [![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)
13
11
  [![Node ≥ 20](https://img.shields.io/badge/node-%E2%89%A520-43853d)](package.json)
14
12
 
15
- Your [Claude Code](https://code.claude.com) sessions, [Codex](https://chatgpt.com/codex) desktop tasks, local DeepSeek Harness, Grok Build agent, and shell harnesses do not share one routing surface. Embassy is a small local broker that gives all five providers named routes and explicit consent edgesno plugins, no API keys handled by Embassy, and no cloud relay.
13
+ Embassy is a small local broker that lets a [Claude Code](https://code.claude.com) session and a [Codex](https://chatgpt.com/codex) CLI task on the same Mac message each other by name, with a receipt for every delivery. It is personal software one person, one macOS account, agents you already trust to run as that user and an unofficial project, not affiliated with or endorsed by Anthropic or OpenAI.
14
+
15
+ ## Install
16
16
 
17
17
  ```bash
18
18
  npm install -g agent-embassy
19
+ embassy service install
19
20
  ```
20
21
 
21
- Prerequisites, stated honestly: Claude routes require a live same-user Claude
22
- Code session with peer protocol 1. Embassy derives the external registry and
23
- peer-socket roots from the current OS user; it does not inspect Claude's
24
- launcher or configuration. Codex routes require **a managed Codex App Server
25
- standalone install** (created by the ChatGPT desktop app, or by the official
26
- installer `curl -fsSL
27
- https://chatgpt.com/codex/install.sh | sh` followed by `codex app-server
28
- daemon start` — the daemon alone does not provision the layout). A missing
29
- Claude registry degrades only Claude while the broker and other providers stay
30
- available. pnpm users: pin the version (`pnpm install -g
31
- agent-embassy@latest` can resolve stale metadata; prefer an explicit
32
- version) and ensure `PNPM_HOME/bin` is on PATH in non-interactive shells.
22
+ Use one global package manager for Embassy (npm or pnpm), not both. Check for shadowing installations in each launch environment:
33
23
 
34
24
  ```bash
35
- embassy serve
25
+ which -a embassy
26
+ embassy --version
27
+ ssh <node> 'which -a embassy; embassy --version'
36
28
  ```
37
29
 
38
- Or from source: `git clone https://github.com/YuanpingSong/embassy && cd embassy && npm ci && npm run build && npm link`.
39
-
40
- Embassy is built for one person, one macOS account, and agents you already trust to run as that user. It is an unofficial community project and is not affiliated with or endorsed by Anthropic or OpenAI.
41
-
42
- ## Quickstart
43
-
44
- **Requirements:** macOS and Node.js 20+. Claude routes require peer protocol 1; Codex routes use Codex CLI tasks with the managed standalone App Server. DeepSeek is optional and launches from `DSH_HOME` (default `~/.dsh`) through the checkout's `demo:acp` script; Grok Build is optional and launches the release-pinned ACP package. A shell peer needs only the local CLI and its one-time token. The release-owned [support matrix](support/provider-support-matrix.json) records the exact tested provider artifacts and capabilities; it is release evidence, never a runtime allowlist:
45
-
46
- ```bash
47
- codex app-server daemon start
48
- ```
30
+ For a configured federation peer, `<node>` is its OpenSSH Host alias; the SSH
31
+ check uses federation's non-interactive launch environment. Update or remove a
32
+ shadowing install through its owning package manager; updating npm does not update pnpm.
33
+ The launchd plist pins the absolute Node and CLI paths used by `embassy service install`,
34
+ not the next shell's PATH. After removing an installation, rerun `embassy service install`
35
+ from the retained installation. `embassy service status` reports a plist program path
36
+ that is no longer on disk.
49
37
 
50
- Run the managed daemon from a normal terminal and use Codex CLI as the supported task host. Desktop's `CODEX_APP_SERVER_USE_LOCAL_DAEMON` attachment is broken in Desktop 26.820 and later ([openai/codex#41112](https://github.com/openai/codex/issues/41112)), so it is not a supported setup. If `CALLER_IDENTITY_CONFLICT` reports both identities, strip only the unwanted inherited identity at the call site: use `env -u CLAUDE_CODE_MESSAGING_SOCKET embassy …` for a Codex-side call, or `env -u CODEX_THREAD_ID embassy …` for a Claude-side call. The Claude destination needs [`crossSessionInbound`](docs/CONFIGURATION.md) enabled.
38
+ `service install` runs the broker as your user's launchd agent: it starts at login, restarts after a crash, and logs to `~/Library/Logs/agent-embassy/broker.log`. Prefer a process you start by hand? Run `embassy serve` in a terminal and leave it running instead. You need macOS, Node.js 20+, Claude Code (with its [`crossSessionInbound`](docs/CONFIGURATION.md#claude-codes-own-setting-crosssessioninbound) setting enabled on any session that should receive mail), and Codex CLI with the managed standalone App Server the official installer `curl -fsSL https://chatgpt.com/codex/install.sh | sh`, then `codex app-server daemon start`. From source: `git clone https://github.com/YuanpingSong/embassy && cd embassy && npm ci && npm run build && npm link`.
51
39
 
52
- Runtime delivery is best effort. Version and build strings are unverified metadata and never grant or withhold routing authority. Consent plus exact logical route/session identity authorizes an attempt; the current per-operation transport and correlated evidence determine its honest result. Unsupported or changed interfaces therefore fail with provider-local safe codes instead of an online compatibility tier. Embassy still validates the trust boundary: exact owned or executed artifacts and state paths, generations of artifacts it actually uses, strict consumed protocol fields, Claude peer protocol 1, bounded queues, and no replay after an ambiguous write.
40
+ Every alias below ends in `@your-host`. Replace `your-host` with this machine's host the `hostId` on the broker's ready line (in the log, under launchd); name the wrong host and the CLI says which one this machine uses.
53
41
 
54
- > **Known limitation:** Embassy can reach Codex tasks only while Desktop uses the managed standalone App Server. In that mode, tasks currently cannot connect to Desktop's built-in in-app browser (`@Browser` loads but does not attach). Switching Desktop back to its default private App Server restores the built-in browser immediately — but makes those tasks unreachable by Embassy. No other capability regressions have been identified, though this was not an exhaustive parity test.
42
+ ## Your first message in four commands
55
43
 
56
- ### 1. Start Embassy
57
-
58
- After creating the mandatory private `nodes.json` described in [Configuration](docs/CONFIGURATION.md), run the foreground broker under the same OS account as Claude Code and Codex:
44
+ **1. Register the Codex task.** Ask your Codex agent to run this as a shell step in its current turn; it must run inside the task so it inherits the task's identity. You should see `"accepted":true`.
59
45
 
60
46
  ```bash
61
- embassy serve
47
+ embassy register-codex --alias codex-reviewer@your-host
62
48
  ```
63
49
 
64
- You should see `"status":"ready"`. In another terminal:
50
+ **2. Read what the broker sees.** The `sessions` block lists your live Claude Code sessions by name. If it is empty, start a Claude Code session and run `embassy refresh`, then look again.
65
51
 
66
52
  ```bash
67
- embassy health
68
53
  embassy status
69
54
  ```
70
55
 
71
- `status` lists `availablePeers` the live Claude sessions you can select. If
72
- that list is empty, start a Claude Code session and run
73
- `embassy refresh-dashboard`, which refreshes discovery; the next `status`
74
- should show it.
75
-
76
- ### 2. Register the Codex task
77
-
78
- Ask your Codex agent to run this as a shell step in its current turn — the command must run inside the task so it inherits the task's identity:
56
+ **3. Send.** From the Codex task, body on stdin, to the name `status` showed. The session's route installs on its first use — there is no step between reading a name and messaging it. You get a `conv_` conversation token and a `dlv_` delivery token back.
79
57
 
80
58
  ```bash
81
- embassy register-codex --alias codex-reviewer@this-mac
82
- ```
83
-
84
- You should see `"accepted":true`. The `codex-` prefix is required for Claude discovery. To retire the task later, run `embassy unregister-codex --alias codex-reviewer@this-mac` from inside that same task.
85
-
86
- Registration records the exact inherited task identity and performs no App Server I/O. Every delivery opens a fresh attested local transport, initializes it, resumes that exact task with history excluded, and authorizes the body write once. App Server and Desktop restarts therefore do not require re-registration or re-anchoring; a current unavailable or unobservable task keeps the logical route and consent edge while the attempt reports an exact safe code. Embassy never retargets by alias or replays an ambiguously written body.
87
-
88
- ### Optional: register a universal shell peer
89
-
90
- A local shell harness can join as a `peer-*` route without a plugin, stable shell, daemon, PID binding, token file, or Keychain entry:
91
-
92
- When native Codex inbound dispatch is unavailable, this shell-peer mailbox is the supported fallback channel: register once, keep its token only in agent memory, and receive with bounded `await` calls.
93
-
94
- ```bash
95
- embassy register-peer --alias peer-reviewer@this-mac
96
- ```
97
-
98
- Registration prints the `peer_` token exactly once. Keep it in the agent's context and provide it on the first stdin line of every authenticated peer command; when a command also carries a message body, the remaining stdin bytes are the body. Never put the token in argv. For example, wait for inbound mail:
99
-
100
- ```bash
101
- embassy await --alias peer-reviewer@this-mac --token-stdin <<'TOKEN'
102
- peer_<32-character-token>
103
- TOKEN
59
+ embassy send --from codex-reviewer@your-host --to advisor@your-host --expects-reply <<'MSG'
60
+ Please review the current approach and identify the main risk.
61
+ MSG
104
62
  ```
105
63
 
106
- `await` performs bounded 30-second long polls until mail arrives or the caller stops it. Each registration may have one waiter and the broker permits 16 in total. Embassy writes the complete framed message to stdout, waits for stdout to flush, and only then acknowledges its private receipt. A missing receipt is `unconfirmed`; uncertainty after write authorization is `ambiguous`, and neither is replayed after restart. `register-peer --emit-env` is an optional convenience for harnesses that really do retain one stable shell; stdin is the universal path.
107
-
108
- ### 3. Select a Claude destination
109
-
110
- Pick one name from `availablePeers`:
64
+ **4. Answer by conversation.** Every delivered body arrives inside one broker-owned `<cross-session-message>` frame naming the attested sender (on a federated hop, the sender is named by the sending node see [SECURITY.md](SECURITY.md)), and its first `<embassy-reply-hint>` carries the full `conv_` token and this exact command; the recipient runs it with the answer on stdin.
111
65
 
112
66
  ```bash
113
- embassy select-claude --alias advisor@this-mac
67
+ embassy send --conversation conv_<token> --from advisor@your-host <<'MSG'
68
+ The main risk is the double-write window; gate it behind the flag.
69
+ MSG
114
70
  ```
115
71
 
116
- Run this from any same-UID process that can reach the private control socket. `embassy select-claude --session <uuid>` selects the same session by its native UUID.
72
+ The same `send` runs from a Claude Code session, inheriting that session's identity, and the other direction needs no Embassy command at all: a Claude session finds `codex-reviewer` with its native `ListAgents` tool and messages it with `SendMessage`. `--to <session-uuid>` addresses a Claude session by its UUID. When two live sessions share a name, the send is refused with `PEER_ALIAS_COLLISION` rather than delivered to a guess — rename one and retry. A Claude session's reply to a `--expects-reply` send is routed back to the Codex task by itself.
117
73
 
118
- You should see `"accepted":true`. Selection creates no permission edge. Create the user-chosen edge explicitly:
74
+ ## After any Claude Code or Codex CLI update
119
75
 
120
76
  ```bash
121
- embassy pair --from codex-reviewer@this-mac --to advisor@this-mac
77
+ embassy check
122
78
  ```
123
79
 
124
- Conversely, `unselect-claude` removes the selected route, removes its incident consent edges, and settles their in-flight work from the durable attempt phase.
125
-
126
- To connect any two routes from different providers, name both ends explicitly with `embassy pair --from <alias> --to <alias>`; many edges can coexist. Same-UID access to the private control socket authorizes the command, and agents must create only the edge the user chose. The live dashboard offers the same bounded, confirmed operation.
80
+ `check` is the upstream-drift tripwire. It registers an ephemeral shell peer of its own — its attributable rows and bodies are omitted from durable state and its route from the federation catalog, but aggregate counters still advance. Its native advertisement to Claude sessions is released with it; a broker that dies mid-check can leave that record until the alias is next registered and released. The check sends one marked message through the ordinary send path to the most recently observed registered Codex task (observed within ten minutes; a task never observed is not eligible), waits for `delivered`, awaits the echo on its own mailbox, releases the registration, and prints every hop with its timing; any failing hop exits non-zero with the safe code that explains it. `--to <alias>` picks a target and `--timeout <s>` bounds each wait. The peer answers because the shipped [skill](skills/embassy-peer/SKILL.md) tells it to — a message whose verified sender starts with `peer-check-` and whose body starts `[embassy check` is echoed in one line; either half alone is ordinary untrusted text. It costs the peer one model turn, so it is a deliberate command, not something to poll.
127
81
 
128
- ### 4. Send a message
82
+ ```text
83
+ embassy check 50066f60 → codex-reviewer@this-mac
129
84
 
130
- From the registered Codex task, send via stdin:
85
+ ok register peer-check-b0c963c9@this-mac (ephemeral, 2 min) 6 ms
86
+ ok send accepted, conversation …89abcdef 15 ms
87
+ ok delivered the peer's transport accepted it 256 ms
88
+ ok reply codex-reviewer@this-mac echoed 50066f60 1407 ms
89
+ ok cleanup temporary check identity removed
131
90
 
132
- ```bash
133
- embassy send \
134
- --from codex-reviewer@this-mac \
135
- --to advisor@this-mac \
136
- --expects-reply <<'MSG'
137
- Please review the current approach and identify the main risk.
138
- MSG
91
+ check passed
139
92
  ```
140
93
 
141
- You should see a `conv_` conversation token and a `dlv_` delivery token. Because this send requested a reply, Claude's response is automatically routed back to the Codex task. In the other direction, a compatible Claude session uses its native `ListAgents` and `SendMessage` tools to contact `codex-reviewer` no Embassy command needed.
142
-
143
- The same command runs in the other direction from a Claude session and inherits that session's reply identity:
94
+ The operator copies the repo-shipped, packaged skill where each agent discovers skills Codex tasks can then be prompted with `$embassy-peer`, and Claude Code finds it as a user skill:
144
95
 
145
96
  ```bash
146
- embassy send \
147
- --from advisor@this-mac \
148
- --to codex-reviewer@this-mac \
149
- --expects-reply <<'MSG'
150
- Summarize the migration risks you found.
151
- MSG
152
- ```
153
-
154
- ### 5. Follow up
155
-
156
- Either participant can continue the conversation with `reply`. The initiating
157
- CLI receives the full `conv_` token in its accepted result; the recipient gets
158
- the same token and an exact reply command in the broker-owned message marker:
159
-
160
- ```bash
161
- embassy reply \
162
- --conversation conv_<token> \
163
- --alias codex-reviewer@this-mac <<'MSG'
164
- Please expand on the migration risk.
165
- MSG
97
+ cp -R "$(npm root -g)/agent-embassy/skills/embassy-peer" ~/.codex/skills/
98
+ cp -R "$(npm root -g)/agent-embassy/skills/embassy-peer" ~/.claude/skills/
166
99
  ```
167
100
 
168
- Every routed body reaches either product inside one broker-owned
169
- `<cross-session-message>` textual frame. It identifies the verified sender
170
- alias and begins with an `<embassy-reply-hint>` containing the full conversation
171
- token, the recipient's exact alias, and the corresponding `embassy reply`
172
- command. Use only that delivered full token and alias; never guess one from a
173
- suffix or substitute the sender's alias. The CLI still rechecks the caller,
174
- conversation membership, and current route policy, so the hint is
175
- not a permission bypass.
101
+ For a pnpm installation, substitute `pnpm root -g` for `npm root -g` in both copy commands. Embassy does not install the skill automatically.
176
102
 
177
- The frame is a clear provenance marker, not a cryptographic signature or a
178
- claim that the body is trustworthy. Embassy neutralizes nested occurrences of
179
- its reserved framing tags in the untrusted body before provider delivery;
180
- arbitrary same-user code and all message text remain untrusted input.
103
+ ## Shell-peer fallback
181
104
 
182
- ### See it live
105
+ Any local harness that can run the CLI can join as a `peer-*` route — no plugin, daemon, PID binding, token file, or Keychain entry — and it is the supported fallback channel when native Codex delivery is unavailable. `embassy register-peer --alias peer-reviewer@your-host` prints a `peer_` token exactly once; keep it in the agent's context, never in argv, and pass it as the first stdin line of every later peer command with `--token-stdin` (the remaining stdin bytes are the body; `--emit-env` exists only for a harness that really does keep one stable shell). `embassy await --alias peer-reviewer@your-host --token-stdin` long-polls the mailbox in bounded 30-second iterations — one waiter per route, 16 in total — writes the complete framed message to stdout, and acknowledges only after stdout has flushed. A missing acknowledgement settles `unconfirmed`; uncertainty after the write was armed settles `ambiguous`; neither is replayed.
183
106
 
184
- `embassy dashboard --live` opens a five-tab streaming view in the browser
185
- (overview, deliveries, routes, activity, diagnostics) at
186
- `http://127.0.0.1:41961/` by default. To choose another stable port for that
187
- invocation, run `embassy dashboard --live --port <n>` with an integer from 1024
188
- through 65535. Up to four concurrent live views — across windows, tabs, or
189
- browsers — can use that URL while the foreground companion runs; a fifth stream
190
- is refused until one closes. If the port is occupied, startup fails explicitly,
191
- points to `--port`, and never falls back to another port. See
192
- [Dashboard](docs/DASHBOARD.md) for details.
107
+ ## Federation
193
108
 
194
- The live dashboard can remove any named Codex registration after an explicit confirmation. The confirmation names the consequence: the broker deletes that registration's consent edges, cancels queued or reserved work, settles armed work ambiguous and accepted work unconfirmed, and never replays either uncertain class.
109
+ `nodes.json` in the state directory is optional. The broker writes it on first boot, naming this machine by its own hostname with an empty peer list, and from then on that file — not the hostname is the broker's durable identity. To reach a second machine, add its OpenSSH `Host` alias to `nodes`, keep `host` exactly as written, and restart: the brokers exchange body-free route catalogs and destination-owned handoffs over `ssh <node> embassy peer-stdio`, your SSH configuration owns keys and users, and Embassy opens no listener. Remote routes appear as `alias@host` mirrors. Details in [Configuration](docs/CONFIGURATION.md).
195
110
 
196
- The broker also publishes mode-0600 static snapshots as `gateway-dashboard.html` and `gateway-dashboard.zh-CN.html`. The live dashboard has no login, token, cookie, or per-browser session: it assumes a trusted single-user machine, and local software that can reach or spoof loopback can read it and invoke its bounded actions. The server still requires the exact Host header on every request and the exact Origin plus `X-Embassy-Request` on every POST; it sends no CORS headers and does not accept `OPTIONS`.
111
+ ## Observability
197
112
 
198
- ## How it works
113
+ `embassy status` is the one command for "what is going on". It is read-only — it never rescans; `embassy refresh` does — and prints prose in a terminal. Piped or with `--json`, it emits `{ok,command,result}` with the snapshot under `result`: use `embassy status --json | jq .result.routes`. `--recent <n>` (1–100, default 10) sizes the message list.
199
114
 
200
115
  ```text
201
- Claude Code sessions Codex desktop task
202
- (native ListAgents / (native App Server,
203
- SendMessage tools) existing task policy)
204
- │ │
205
- ▼ ▼
206
- ┌──────────────────── Embassy ─────────────────────────────┐
207
- │ explicit routes │ Codex busy queue │ receipts │ dashboard │
208
- └───────────────────────────────────────────────────────────┘
116
+ embassy 3.1.0 broker ok · pid 41213 · snapshot just now
117
+ state dir /Users/you/.local/state/agent-embassy
118
+ sessions scanned 3s ago
119
+
120
+ connectors
121
+ claude ok
122
+ codex ok
123
+
124
+ sessions
125
+ session state route last seen
126
+ advisor@this-mac busy routed 3s ago
127
+
128
+ routes
129
+ alias provider state queue last seen
130
+ advisor@this-mac claude busy 2 discovered 3s
131
+ codex-reviewer@this-mac codex idle 0 12s ago
132
+
133
+ recent (3 of 3)
134
+ 12s ago advisor@this-mac → codex-reviewer@this-mac queued
135
+ 2m ago codex-reviewer@this-mac → advisor@this-mac delivered 210 ms
136
+ The risk is the double-write window; I would gate it behind…
137
+ 5m ago advisor@this-mac → codex-reviewer@this-mac delivered 61 ms
138
+ Please review the migration risk before the freeze.
209
139
  ```
210
140
 
211
- Embassy publishes each registered Codex task into Claude Code's live-session registry as its own `codex-*` peer. Claude sessions discover those tasks through `ListAgents`; Codex uses its managed App Server. DeepSeek and Grok Build are boot-registered ACP routes whose owned subprocess and one route-local session start lazily on first dispatch. Universal shell peers use `peer-*` aliases and a pull mailbox authenticated by an alias plus one-time-minted token.
212
-
213
- A pair is one explicit permission edge between two named routes from different providers, bounded at 128 edges by default. Every edge is created explicitly with generic `pair --from/--to`; the same-UID private control socket is the command's authority, while agents are instructed to create only user-chosen edges. Selection is separate and implies no consent. Without an edge, a sender settles terminally as `SENDER_NOT_PAIRED`. `embassy serve --inbound open` is the explicit opt-out for supported native inbound senders.
141
+ When something is wrong it says the safe code **and** what to do about it, and one quiet corner never makes the whole broker look broken:
214
142
 
215
- Delivery timing is directional. Once routing and pre-write checks pass, every Claude-bound body is written immediately to Claude's native mailbox regardless of its observed busy or idle state. `transport_written` records that mailbox write and is the Claude-bound terminal `delivered` boundary; it does not mean Claude read or consumed the body. Codex-bound ordinary bodies instead queue while the task is busy and start a turn when it goes idle. In the Claude-to-Codex direction only, a body with an exact leading `STEER:` prefix may enter the active turn at the App Server's next tool-call boundary; if that boundary is unavailable, the message returns to the normal queue.
216
-
217
- Immediately before the provider write, Embassy gives every routed body one
218
- broker-owned cross-session marker containing the verified sender alias and a
219
- recipient reply hint. The full conversation token travels only in the
220
- initiator's accepted result and the recipient's transient message payload; it
221
- never enters the dashboard, public snapshot, journal, receipt, or log.
222
-
223
- Every settled message produces a receipt. `delivered` means the direction's terminal provider boundary was observed toward Codex, the App Server accepted the turn; toward Claude, the native mailbox write completed. Neither means the model read or acted on it. `unconfirmed` and `ambiguous` mean the required evidence is missing; they are terminal states and never auto-retried. See [Delivery](docs/DELIVERY.md) for the full semantics.
224
-
225
- ## The vocabulary
226
-
227
- Four embassy terms name real features:
228
-
229
- - **Registration and pairing** are the permission model: a Codex task is explicitly registered, and each pair is one explicit Claude↔Codex edge — only paired ends exchange messages, and many edges can coexist. No edge means `SENDER_NOT_PAIRED`; nothing is ever implicit.
230
- - **The ledger** is the delivery record: a receipt for every settled message, and a metadata-only dashboard.
231
- - **The pouch** is transit and the archive: bounded bodies, retained under bounded limits, private to your OS account — sealed against other users, not against you.
232
- - **Consulates** are configured Embassy nodes: brokers federate over attach-only SSH and keep destination-owned delivery and consent authority.
233
-
234
- ## For agents
235
-
236
- Embassy's operators are often agents themselves: `register-codex` runs inside the Codex task, and the Claude side is driven entirely through native tools. The repo ships [`skills/embassy-peer/SKILL.md`](skills/embassy-peer/SKILL.md) point your agent at it rather than paraphrasing this README.
237
-
238
- The skill ships in the npm package; install it where each agent discovers skills:
239
-
240
- ```bash
241
- cp -R "$(npm root -g)/agent-embassy/skills/embassy-peer" ~/.codex/skills/
242
- cp -R "$(npm root -g)/agent-embassy/skills/embassy-peer" ~/.claude/skills/
143
+ ```text
144
+ embassy 3.1.0 broker degraded · pid 41213 · snapshot just now
145
+ state dir /Users/you/.local/state/agent-embassy
146
+ sessions scanned 3s ago
147
+
148
+ connectors
149
+ claude ok
150
+ codex degraded MANAGED_CODEX_UNAVAILABLE
151
+ Either a process outside Embassy holds the managed Codex control socket quit itor the managed App Server standalone layout is missing, which starting the daemon alone does not create: follow the Codex prerequisite in the README (the official installer, then the daemon).
152
+ peer-release@this-mac stale (token or await loop gone)
153
+ 2 message(s) waiting: run `embassy await --alias peer-release@this-mac --token-stdin` in the shell holding its token, or `embassy unregister-peer --alias peer-release@this-mac --token-stdin`.
154
+
155
+ sessions
156
+ session state route last seen
157
+ advisor@this-mac busy routed 3s ago
158
+
159
+ routes
160
+ alias provider state queue last seen
161
+ advisor@this-mac claude busy 2 discovered 3s
162
+ codex-reviewer@this-mac codex stale 1 30m ago
163
+ peer-release@this-mac peer idle 2 never
164
+ codex-reviewer@this-mac: That Codex task is gone. Run `embassy register-codex --alias <new-alias> --succeeds <this alias>` from the new task, or `embassy unregister-codex --alias <this alias>` from the old one.
165
+
166
+ recent (3 of 3)
167
+ 12s ago advisor@this-mac → codex-reviewer@this-mac queued
168
+ 2m ago codex-reviewer@this-mac → advisor@this-mac delivered 210 ms
169
+ The risk is the double-write window; I would gate it behind…
170
+ 5m ago advisor@this-mac codex-reviewer@this-mac delivered 61 ms
171
+ Please review the migration risk before the freeze.
172
+
173
+ alerts
174
+ PEER_TUNNEL_UNAVAILABLE studio 45s ago
175
+ The SSH tunnel to that node is down; check the node is reachable and its broker is running.
243
176
  ```
244
177
 
245
- Codex tasks can then be prompted with `$embassy-peer`; Claude Code discovers it as a user skill.
246
-
247
- ## Commands
248
-
249
- | Command | Run by | Purpose |
250
- | --- | --- | --- |
251
- | `serve` | operator | Start the foreground broker and dashboard |
252
- | `health` / `status` | operator | Check liveness and inspect the sanitized snapshot |
253
- | `refresh-dashboard` | operator | Refresh provider discovery and regenerate both static dashboard files |
254
- | `dashboard --live [--lang en\|zh-CN] [--port <n>]` | operator | Start the live dashboard companion with bounded route-consent actions; requires a running `embassy serve` |
255
- | `delivery-status` | either provider | Read one delivery tracker with `embassy delivery-status --token dlv_<token>` |
256
- | `wait-delivery` | either provider | Wait for that tracker to settle, up to the delivery deadline |
257
- | `untrack` | either provider | Close one active progress watch: `embassy untrack --conversation conv_<token>` |
258
- | `register-codex` / `unregister-codex` | Codex task | Advertise or retire that exact task; both take `--alias <codex-alias>`, and `embassy register-codex --alias codex-successor@this-mac --succeeds codex-reviewer@this-mac` hands the registration to a different task |
259
- | `register-peer` / `unregister-peer` | shell harness | Register or retire a `peer-*` route; registration emits its raw token once, while authenticated calls use `--token-stdin` (or the optional stable-shell env form) |
260
- | `await` | registered shell peer | Long-poll the peer mailbox in bounded 30-second iterations; one waiter per route, 16 globally, with acknowledgement only after stdout flush |
261
- | `pair` / `unpair` | same-UID control client | Add or remove one user-chosen cross-provider edge by naming both ends: `embassy pair --from advisor@this-mac --to grok-main@this-mac` |
262
- | `select-claude` / `unselect-claude` | same-UID control client | Select or remove one Claude route using `--alias <name@host>` or `--session <uuid>`; selection creates no permission edge |
263
- | `send` | registered Codex task, Claude session, or shell peer | Send one bounded stdin message between paired routes: `--from <alias> --to <alias>`, optional `--expects-reply` and `--track [--idle-minutes <n>]`; the broker derives direction from the resolved providers |
264
- | `reply` | conversation-token holder | Continue an active conversation with the full token returned to the initiator or delivered in the recipient's broker-owned reply hint: `--conversation conv_<token> --alias <your-alias>`, body on stdin, optional `--track [--idle-minutes <n>]` |
265
-
266
- Version 2.0 accepts only fresh private state. Follow the
267
- [reset-only state runbook](docs/CONFIGURATION.md#private-state-reset) before
268
- starting it over an older installation.
269
-
270
- `--track` opens a progress watch over the conversation; `--idle-minutes <n>`
271
- sets the idle interval for bounded liveness nudges (1–1440, default 5, rejected
272
- without `--track`). If the watch ultimately times out, Embassy records it only
273
- in watch history and emits no runtime stall alert. Close a watch with `untrack`,
274
- or by replying with a leading `DONE:`. See [Delivery](docs/DELIVERY.md).
178
+ `embassy watch` tails the broker until Ctrl-C: each new message and each settlement at most once (`accepted → delivered (61 ms)`), stamped with the local time, plus route installs and retirements as a secondary line; `--json` streams the same events as JSONL. At most once, not exactly once — a transition that passes entirely between two one-second polls is never seen, and rows that left the retained window before the tail reached them are announced as a one-line note. `embassy --help` lists all eighteen commands.
275
179
 
276
180
  ## Safety in one minute
277
181
 
278
- - **Local broker, stable loopback dashboard.** `embassy serve` listens on private Unix-domain sockets and makes no provider API call. The opt-in `embassy dashboard --live` companion is a separate process and the only listener Embassy can create, bound to exact `127.0.0.1` on stable port `41961` by default (or the per-invocation `--port <n>`). It is deliberately unauthenticated local HTTP for a trusted single-user machine; Host, Origin, and sentinel checks constrain browser-origin requests but do not authenticate local processes or OS users.
279
- - **Same-UID containment, not authentication.** Caller identity is inherited from the local process environment. Route ownership and per-operation artifact checks reduce mistakes, but are not a defense against code already running as your OS user.
280
- - **Compatibility is tested offline; runtime is best effort.** The release-owned support matrix records exact tested artifacts, protocols, capabilities, stop fidelity, limitations, and test dates. Runtime never imports that matrix and never turns a version fact into authority. It validates exact owned boundaries and protocol facts, attempts the current operation, and reports provider-local health and safe codes without replaying uncertainty.
281
- - **Native permissions stay native.** Embassy sends no Codex approval or sandbox overrides and answers no approval request. `crossSessionInbound` remains Claude's own control; Embassy cannot override it.
282
- - **Provenance is marked, not authenticated.** Routed bodies carry one broker-owned cross-session marker with the verified sender alias; it distinguishes the transport path for the receiving model but cannot make untrusted text safe or authenticate against code already running as your OS user.
283
- - **Bodies and delivery status stored, bounded, and yours.** Message bodies and their opaque delivery token/status persist in the broker's private mode-0600 v4 state under bounded retention; queued or reserved work may resume once after restart, while armed or provider-accepted work is never replayed. A delivery token never enters a public snapshot, normal log, provider receipt, or dashboard. Raw provider frames stay memory-only. The static dashboard files remain metadata-only; the live dashboard shows retained bodies.
182
+ - **The OS boundary is the permission.** Reaching the same-UID private control socket on this host or on a host in your `nodes.json` plus an exact alias is what lets a process message. There is no separate grant to hand out or revoke, because none could stop code already running as your user; a Claude session's route installs on its first use, and a Codex task registers explicitly only because Embassy must record its inherited identity. `embassy serve` binds no TCP port and serves no HTTP.
183
+ - **Retirement is an explicit OS-boundary exception to owner unregister.** `embassy retire --alias codex-reviewer@your-host` requires no route credential and atomically removes any local Claude, Codex, or shell-peer route; it accepts no token, force, or remote option, refuses a federated mirror with `FEDERATED_ROUTE_READ_ONLY`, and prints settlement counts `{cancelled,ambiguous,unconfirmed}`.
184
+ - **Every routed body carries the provenance envelope naming the sender.** It is a marker for the receiving model, not a signature: treat every delivered body as untrusted input. Native permissions stay native Embassy answers no Codex approval and cannot override Claude's `crossSessionInbound`.
185
+ - **Bounded by design.** Queues, bodies (16 KiB), conversations, rate windows, and deadlines are bounded, and an ambiguous write is never replayed. `delivered` means the provider boundary was crossed — toward Codex the App Server accepted the turn; toward Claude the native mailbox write completed (`transport_written`) — never that a model read it; `unconfirmed` and `ambiguous` mean the evidence is missing and are terminal. Claude-bound bodies are written immediately, busy or idle; Codex-bound bodies queue until the task is idle, and only an exact leading `STEER:` from Claude may enter the active turn at its next tool-call boundary.
186
+ - **Bodies are retained locally and yours.** Message bodies and their opaque delivery token/status persist in the broker's private mode-0600 state under bounded retention, and what `status` prints is a status snapshot that includes retained message bodies: `embassy status` shows retained bodies; treat its output as sensitive as the messages themselves.
187
+
188
+ See [SECURITY.md](SECURITY.md) for the boundary in depth and how to report a vulnerability.
284
189
 
285
- See [SECURITY.md](SECURITY.md) for the full boundary and vulnerability-reporting process.
190
+ **Tested with** (cutover drill, 2026-09-03): Claude Code 2.1.259 and Codex CLI 0.152.0 on macOS, Node 22.23, on two machines — a Claude Code session ↔ Codex CLI task round trip in both directions, `embassy check` (register → send → delivered → reply → cleanup), and a cross-machine shell-peer handoff over ssh.
286
191
 
287
- ## What Embassy is not
192
+ ## Upgrading from 2.x
288
193
 
289
- - **Not an orchestrator.** It does not spawn agents or manage their work. Codex-bound ordinary messages start one turn apiece as the task becomes idle; Claude-bound messages enter Claude's mailbox without waiting for idle.
290
- - **Not a hosted service.** Personal, same-machine, same-OS-account software.
291
- - **Not a permission bypass — but it is a new path.** Neither agent gains a tool it did not already have, and Embassy grants, relaxes, and answers nothing. It does, however, connect two products that previously could not exchange text at all. That path is the product; treat it with the respect you would give any new input channel.
292
- - **Not official.** Not affiliated with or endorsed by Anthropic or OpenAI.
194
+ Version 3 accepts only fresh private state. Stop Embassy, move `gateway-state.json` aside, start 3.0, and re-register Codex tasks; Claude routes reinstall themselves on first use, and `nodes.json` is written for you if absent. The full [private state reset](docs/CONFIGURATION.md#private-state-reset) and every change are in the [changelog](CHANGELOG.md).
293
195
 
294
196
  ## Documentation
295
197
 
296
198
  | Document | What it covers |
297
199
  | --- | --- |
298
- | [Architecture](docs/GATEWAY-ARCHITECTURE.md) | The full design: topology, adapters, control plane, threat model, and the paired-consent inbound model |
200
+ | [Architecture](docs/GATEWAY-ARCHITECTURE.md) | Topology, adapters, control plane, federation, protocol versions, and the OS-boundary permission model |
299
201
  | [Delivery](docs/DELIVERY.md) | Delivery semantics, tokens, settlement states, and retry rules |
300
- | [Configuration](docs/CONFIGURATION.md) | Environment variables, provider contracts, and addressing rules |
301
- | [Dashboard](docs/DASHBOARD.md) | Static and live dashboard setup, security model, and mutation actions |
302
- | [Security policy](SECURITY.md) | How to report a vulnerability, and the boundary in depth |
202
+ | [Configuration](docs/CONFIGURATION.md) | Environment variables, `nodes.json`, the launchd service, and addressing |
203
+ | [Security policy](SECURITY.md) | The boundary in depth, and how to report a vulnerability |
303
204
  | [Contributing](CONTRIBUTING.md) | Where changes go, and how to run the deterministic suite |
304
205
  | [Changelog](CHANGELOG.md) | What each release contains |
305
206
  | [Agent skill](skills/embassy-peer/SKILL.md) | The workflow an agent follows to operate Embassy |