agent-embassy 2.0.1 → 3.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.
- package/CHANGELOG.md +56 -0
- package/CONTRIBUTING.md +19 -34
- package/README.md +110 -228
- package/SECURITY.md +55 -89
- package/dist/src/errors.d.ts +10 -1
- package/dist/src/errors.js +3 -1
- package/dist/src/errors.js.map +1 -1
- package/dist/src/gateway/claude-helper-protocol.d.ts +8 -11
- package/dist/src/gateway/claude-helper-protocol.js +12 -11
- package/dist/src/gateway/claude-helper-protocol.js.map +1 -1
- package/dist/src/gateway/claude-helper-supervisor.d.ts +1 -5
- package/dist/src/gateway/claude-helper-supervisor.js +10 -9
- package/dist/src/gateway/claude-helper-supervisor.js.map +1 -1
- package/dist/src/gateway/claude-helper.js +6 -6
- package/dist/src/gateway/claude-helper.js.map +1 -1
- package/dist/src/gateway/claude-peer.d.ts +0 -3
- package/dist/src/gateway/claude-peer.js +6 -18
- package/dist/src/gateway/claude-peer.js.map +1 -1
- package/dist/src/gateway/cli.d.ts +17 -6
- package/dist/src/gateway/cli.js +912 -261
- package/dist/src/gateway/cli.js.map +1 -1
- package/dist/src/gateway/codex-socket-holder.d.ts +26 -0
- package/dist/src/gateway/codex-socket-holder.js +76 -0
- package/dist/src/gateway/codex-socket-holder.js.map +1 -0
- package/dist/src/gateway/codex-stateless-transport.js +1 -1
- package/dist/src/gateway/codex-stateless-transport.js.map +1 -1
- package/dist/src/gateway/config.d.ts +1 -10
- package/dist/src/gateway/config.js +4 -10
- package/dist/src/gateway/config.js.map +1 -1
- package/dist/src/gateway/control.d.ts +45 -77
- package/dist/src/gateway/control.js +56 -141
- package/dist/src/gateway/control.js.map +1 -1
- package/dist/src/gateway/federation-nodes.d.ts +29 -2
- package/dist/src/gateway/federation-nodes.js +177 -7
- package/dist/src/gateway/federation-nodes.js.map +1 -1
- package/dist/src/gateway/peer-client.d.ts +4 -3
- package/dist/src/gateway/peer-client.js +22 -13
- package/dist/src/gateway/peer-client.js.map +1 -1
- package/dist/src/gateway/peer-protocol.d.ts +8 -11
- package/dist/src/gateway/peer-protocol.js +5 -12
- package/dist/src/gateway/peer-protocol.js.map +1 -1
- package/dist/src/gateway/provenance-envelope.d.ts +0 -1
- package/dist/src/gateway/provenance-envelope.js +4 -19
- package/dist/src/gateway/provenance-envelope.js.map +1 -1
- package/dist/src/gateway/providers.d.ts +7 -4
- package/dist/src/gateway/providers.js +16 -20
- package/dist/src/gateway/providers.js.map +1 -1
- package/dist/src/gateway/server.d.ts +3 -12
- package/dist/src/gateway/server.js +31 -50
- package/dist/src/gateway/server.js.map +1 -1
- package/dist/src/gateway/service-agent.d.ts +187 -0
- package/dist/src/gateway/service-agent.js +758 -0
- package/dist/src/gateway/service-agent.js.map +1 -0
- package/dist/src/gateway/service.d.ts +114 -31
- package/dist/src/gateway/service.js +461 -566
- package/dist/src/gateway/service.js.map +1 -1
- package/dist/src/gateway/status-view.d.ts +167 -0
- package/dist/src/gateway/status-view.js +488 -0
- package/dist/src/gateway/status-view.js.map +1 -0
- package/dist/src/gateway/store.d.ts +103 -21
- package/dist/src/gateway/store.js +454 -529
- package/dist/src/gateway/store.js.map +1 -1
- package/dist/src/gateway/types.d.ts +48 -99
- package/dist/src/gateway/types.js +15 -52
- package/dist/src/gateway/types.js.map +1 -1
- package/docs/CONFIGURATION.md +173 -44
- package/docs/DELIVERY.md +11 -11
- package/docs/GATEWAY-ARCHITECTURE.md +277 -375
- package/package.json +4 -12
- package/skills/embassy-peer/SKILL.md +65 -90
- package/skills/embassy-peer/agents/openai.yaml +1 -1
- package/README.zh-CN.md +0 -275
- package/assets/live-dashboard/app.css +0 -1619
- package/assets/vendor/react/LICENSE +0 -21
- package/assets/vendor/react/react-dom.production.min.js +0 -267
- package/assets/vendor/react/react.production.min.js +0 -31
- package/dist/src/gateway/acp-client.d.ts +0 -110
- package/dist/src/gateway/acp-client.js +0 -407
- package/dist/src/gateway/acp-client.js.map +0 -1
- package/dist/src/gateway/acp-provider.d.ts +0 -66
- package/dist/src/gateway/acp-provider.js +0 -275
- package/dist/src/gateway/acp-provider.js.map +0 -1
- package/dist/src/gateway/cli-copy.d.ts +0 -8
- package/dist/src/gateway/cli-copy.en.d.ts +0 -22
- package/dist/src/gateway/cli-copy.en.js +0 -62
- package/dist/src/gateway/cli-copy.en.js.map +0 -1
- package/dist/src/gateway/cli-copy.js +0 -27
- package/dist/src/gateway/cli-copy.js.map +0 -1
- package/dist/src/gateway/cli-copy.zh-CN.d.ts +0 -22
- package/dist/src/gateway/cli-copy.zh-CN.js +0 -62
- package/dist/src/gateway/cli-copy.zh-CN.js.map +0 -1
- package/dist/src/gateway/codex-doctor.d.ts +0 -36
- package/dist/src/gateway/codex-doctor.js +0 -127
- package/dist/src/gateway/codex-doctor.js.map +0 -1
- package/dist/src/gateway/dashboard-copy.d.ts +0 -7
- package/dist/src/gateway/dashboard-copy.en.d.ts +0 -504
- package/dist/src/gateway/dashboard-copy.en.js +0 -505
- package/dist/src/gateway/dashboard-copy.en.js.map +0 -1
- package/dist/src/gateway/dashboard-copy.js +0 -514
- package/dist/src/gateway/dashboard-copy.js.map +0 -1
- package/dist/src/gateway/dashboard-copy.zh-CN.d.ts +0 -504
- package/dist/src/gateway/dashboard-copy.zh-CN.js +0 -505
- package/dist/src/gateway/dashboard-copy.zh-CN.js.map +0 -1
- package/dist/src/gateway/dashboard-model.d.ts +0 -343
- package/dist/src/gateway/dashboard-model.js +0 -1061
- package/dist/src/gateway/dashboard-model.js.map +0 -1
- package/dist/src/gateway/dashboard.d.ts +0 -20
- package/dist/src/gateway/dashboard.js +0 -874
- package/dist/src/gateway/dashboard.js.map +0 -1
- package/dist/src/gateway/deepseek-detect.d.ts +0 -14
- package/dist/src/gateway/deepseek-detect.js +0 -41
- package/dist/src/gateway/deepseek-detect.js.map +0 -1
- package/dist/src/gateway/live-dashboard-app/app.js +0 -2385
- package/dist/src/gateway/live-dashboard-assets.d.ts +0 -10
- package/dist/src/gateway/live-dashboard-assets.js +0 -74
- package/dist/src/gateway/live-dashboard-assets.js.map +0 -1
- package/dist/src/gateway/live-dashboard-command.d.ts +0 -60
- package/dist/src/gateway/live-dashboard-command.js +0 -334
- package/dist/src/gateway/live-dashboard-command.js.map +0 -1
- package/dist/src/gateway/live-dashboard-http.d.ts +0 -39
- package/dist/src/gateway/live-dashboard-http.js +0 -383
- package/dist/src/gateway/live-dashboard-http.js.map +0 -1
- package/dist/src/gateway/live-dashboard-protocol.d.ts +0 -34
- package/dist/src/gateway/live-dashboard-protocol.js +0 -114
- package/dist/src/gateway/live-dashboard-protocol.js.map +0 -1
- package/dist/src/gateway/live-dashboard-server.d.ts +0 -33
- package/dist/src/gateway/live-dashboard-server.js +0 -144
- package/dist/src/gateway/live-dashboard-server.js.map +0 -1
- package/dist/src/gateway/live-dashboard-stream.d.ts +0 -46
- package/dist/src/gateway/live-dashboard-stream.js +0 -234
- package/dist/src/gateway/live-dashboard-stream.js.map +0 -1
- package/dist/src/gateway/live-dashboard.d.ts +0 -28
- package/dist/src/gateway/live-dashboard.js +0 -154
- package/dist/src/gateway/live-dashboard.js.map +0 -1
- package/dist/src/gateway/locale.d.ts +0 -4
- package/dist/src/gateway/locale.js +0 -10
- package/dist/src/gateway/locale.js.map +0 -1
- package/dist/src/gateway/progress-watch-machine.d.ts +0 -45
- package/dist/src/gateway/progress-watch-machine.js +0 -70
- package/dist/src/gateway/progress-watch-machine.js.map +0 -1
- package/docs/CONFIGURATION.zh-CN.md +0 -97
- package/docs/DASHBOARD.md +0 -98
- package/docs/DASHBOARD.zh-CN.md +0 -49
- 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
|
|
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,178 @@
|
|
|
12
10
|
[](LICENSE)
|
|
13
11
|
[](package.json)
|
|
14
12
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
```bash
|
|
18
|
-
npm install -g agent-embassy
|
|
19
|
-
```
|
|
20
|
-
|
|
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.
|
|
33
|
-
|
|
34
|
-
```bash
|
|
35
|
-
embassy serve
|
|
36
|
-
```
|
|
37
|
-
|
|
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
|
|
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.
|
|
43
14
|
|
|
44
|
-
|
|
15
|
+
## Install
|
|
45
16
|
|
|
46
17
|
```bash
|
|
47
|
-
|
|
18
|
+
npm install -g agent-embassy
|
|
19
|
+
embassy service install
|
|
48
20
|
```
|
|
49
21
|
|
|
50
|
-
|
|
51
|
-
|
|
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.
|
|
22
|
+
`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`.
|
|
53
23
|
|
|
54
|
-
|
|
24
|
+
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.
|
|
55
25
|
|
|
56
|
-
|
|
26
|
+
## Your first message in four commands
|
|
57
27
|
|
|
58
|
-
|
|
28
|
+
**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
29
|
|
|
60
30
|
```bash
|
|
61
|
-
embassy
|
|
31
|
+
embassy register-codex --alias codex-reviewer@your-host
|
|
62
32
|
```
|
|
63
33
|
|
|
64
|
-
|
|
34
|
+
**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
35
|
|
|
66
36
|
```bash
|
|
67
|
-
embassy health
|
|
68
37
|
embassy status
|
|
69
38
|
```
|
|
70
39
|
|
|
71
|
-
`status`
|
|
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:
|
|
79
|
-
|
|
80
|
-
```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:
|
|
40
|
+
**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.
|
|
99
41
|
|
|
100
42
|
```bash
|
|
101
|
-
embassy
|
|
102
|
-
|
|
103
|
-
|
|
43
|
+
embassy send --from codex-reviewer@your-host --to advisor@your-host --expects-reply <<'MSG'
|
|
44
|
+
Please review the current approach and identify the main risk.
|
|
45
|
+
MSG
|
|
104
46
|
```
|
|
105
47
|
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
### 3. Select a Claude destination
|
|
109
|
-
|
|
110
|
-
Pick one name from `availablePeers`:
|
|
48
|
+
**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
49
|
|
|
112
50
|
```bash
|
|
113
|
-
embassy
|
|
51
|
+
embassy send --conversation conv_<token> --from advisor@your-host <<'MSG'
|
|
52
|
+
The main risk is the double-write window; gate it behind the flag.
|
|
53
|
+
MSG
|
|
114
54
|
```
|
|
115
55
|
|
|
116
|
-
|
|
56
|
+
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
57
|
|
|
118
|
-
|
|
58
|
+
## After any Claude Code or Codex CLI update
|
|
119
59
|
|
|
120
60
|
```bash
|
|
121
|
-
embassy
|
|
61
|
+
embassy check
|
|
122
62
|
```
|
|
123
63
|
|
|
124
|
-
|
|
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.
|
|
127
|
-
|
|
128
|
-
### 4. Send a message
|
|
129
|
-
|
|
130
|
-
From the registered Codex task, send via stdin:
|
|
131
|
-
|
|
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
|
|
139
|
-
```
|
|
64
|
+
`check` is the upstream-drift tripwire. It registers an ephemeral shell peer of its own — kept out of the durable state document and the federation catalog, expiring on its own; its only trace is the native advertisement to Claude sessions, released with it, and a broker that dies mid-check can leave that record until the alias is next registered and released — 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.
|
|
140
65
|
|
|
141
|
-
|
|
66
|
+
```text
|
|
67
|
+
embassy check 50066f60 → codex-reviewer@this-mac
|
|
142
68
|
|
|
143
|
-
|
|
69
|
+
ok register peer-check-b0c963c9@this-mac (ephemeral, 2 min) 6 ms
|
|
70
|
+
ok send accepted, conversation …89abcdef 15 ms
|
|
71
|
+
ok delivered the peer's transport accepted it 256 ms
|
|
72
|
+
ok reply codex-reviewer@this-mac echoed 50066f60 1407 ms
|
|
73
|
+
ok cleanup temporary check identity removed
|
|
144
74
|
|
|
145
|
-
|
|
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
|
|
75
|
+
check passed
|
|
152
76
|
```
|
|
153
77
|
|
|
154
|
-
|
|
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:
|
|
78
|
+
Install the skill where each agent discovers skills — Codex tasks can then be prompted with `$embassy-peer`, and Claude Code finds it as a user skill:
|
|
159
79
|
|
|
160
80
|
```bash
|
|
161
|
-
embassy
|
|
162
|
-
|
|
163
|
-
--alias codex-reviewer@this-mac <<'MSG'
|
|
164
|
-
Please expand on the migration risk.
|
|
165
|
-
MSG
|
|
81
|
+
cp -R "$(npm root -g)/agent-embassy/skills/embassy-peer" ~/.codex/skills/
|
|
82
|
+
cp -R "$(npm root -g)/agent-embassy/skills/embassy-peer" ~/.claude/skills/
|
|
166
83
|
```
|
|
167
84
|
|
|
168
|
-
|
|
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.
|
|
85
|
+
## Shell-peer fallback
|
|
176
86
|
|
|
177
|
-
|
|
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.
|
|
87
|
+
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.
|
|
181
88
|
|
|
182
|
-
|
|
89
|
+
## Federation
|
|
183
90
|
|
|
184
|
-
`
|
|
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.
|
|
91
|
+
`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).
|
|
193
92
|
|
|
194
|
-
|
|
93
|
+
## Observability
|
|
195
94
|
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
## How it works
|
|
95
|
+
`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 but the unchanged JSON snapshot when piped or with `--json`, so `embassy status --json | jq .routes` and every script keep working. `--recent <n>` (1–100, default 10) sizes the message list.
|
|
199
96
|
|
|
200
97
|
```text
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
98
|
+
embassy 3.0.0 broker ok · pid 41213 · snapshot just now
|
|
99
|
+
state dir /Users/you/.local/state/agent-embassy
|
|
100
|
+
sessions scanned 3s ago
|
|
101
|
+
|
|
102
|
+
connectors
|
|
103
|
+
claude ok
|
|
104
|
+
codex ok
|
|
105
|
+
|
|
106
|
+
sessions
|
|
107
|
+
session state route last seen
|
|
108
|
+
advisor@this-mac busy routed 3s ago
|
|
109
|
+
|
|
110
|
+
routes
|
|
111
|
+
alias provider state queue last seen
|
|
112
|
+
advisor@this-mac claude busy 2 discovered 3s
|
|
113
|
+
codex-reviewer@this-mac codex idle 0 12s ago
|
|
114
|
+
|
|
115
|
+
recent (3 of 3)
|
|
116
|
+
12s ago advisor@this-mac → codex-reviewer@this-mac queued
|
|
117
|
+
2m ago codex-reviewer@this-mac → advisor@this-mac delivered 210 ms
|
|
118
|
+
The risk is the double-write window; I would gate it behind…
|
|
119
|
+
5m ago advisor@this-mac → codex-reviewer@this-mac delivered 61 ms
|
|
120
|
+
Please review the migration risk before the freeze.
|
|
209
121
|
```
|
|
210
122
|
|
|
211
|
-
|
|
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.
|
|
214
|
-
|
|
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.
|
|
123
|
+
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:
|
|
233
124
|
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
125
|
+
```text
|
|
126
|
+
embassy 3.0.0 broker degraded · pid 41213 · snapshot just now
|
|
127
|
+
state dir /Users/you/.local/state/agent-embassy
|
|
128
|
+
sessions scanned 3s ago
|
|
129
|
+
|
|
130
|
+
connectors
|
|
131
|
+
claude ok
|
|
132
|
+
codex degraded MANAGED_CODEX_UNAVAILABLE
|
|
133
|
+
Either a process outside Embassy holds the managed Codex control socket — quit it — or 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).
|
|
134
|
+
peer-release@this-mac stale (token or await loop gone)
|
|
135
|
+
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`.
|
|
136
|
+
|
|
137
|
+
sessions
|
|
138
|
+
session state route last seen
|
|
139
|
+
advisor@this-mac busy routed 3s ago
|
|
140
|
+
|
|
141
|
+
routes
|
|
142
|
+
alias provider state queue last seen
|
|
143
|
+
advisor@this-mac claude busy 2 discovered 3s
|
|
144
|
+
codex-reviewer@this-mac codex stale 1 30m ago
|
|
145
|
+
peer-release@this-mac peer idle 2 never
|
|
146
|
+
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.
|
|
147
|
+
|
|
148
|
+
recent (3 of 3)
|
|
149
|
+
12s ago advisor@this-mac → codex-reviewer@this-mac queued
|
|
150
|
+
2m ago codex-reviewer@this-mac → advisor@this-mac delivered 210 ms
|
|
151
|
+
The risk is the double-write window; I would gate it behind…
|
|
152
|
+
5m ago advisor@this-mac → codex-reviewer@this-mac delivered 61 ms
|
|
153
|
+
Please review the migration risk before the freeze.
|
|
154
|
+
|
|
155
|
+
alerts
|
|
156
|
+
PEER_TUNNEL_UNAVAILABLE studio 45s ago
|
|
157
|
+
The SSH tunnel to that node is down; check the node is reachable and its broker is running.
|
|
243
158
|
```
|
|
244
159
|
|
|
245
|
-
|
|
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).
|
|
160
|
+
`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 seventeen commands.
|
|
275
161
|
|
|
276
162
|
## Safety in one minute
|
|
277
163
|
|
|
278
|
-
- **
|
|
279
|
-
- **
|
|
280
|
-
- **
|
|
281
|
-
- **
|
|
282
|
-
|
|
283
|
-
|
|
164
|
+
- **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.
|
|
165
|
+
- **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`.
|
|
166
|
+
- **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.
|
|
167
|
+
- **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.
|
|
168
|
+
|
|
169
|
+
See [SECURITY.md](SECURITY.md) for the boundary in depth and how to report a vulnerability.
|
|
284
170
|
|
|
285
|
-
|
|
171
|
+
<!-- tested-with: filled by the PM after the cutover drill -->
|
|
286
172
|
|
|
287
|
-
##
|
|
173
|
+
## Upgrading from 2.x
|
|
288
174
|
|
|
289
|
-
|
|
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.
|
|
175
|
+
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
176
|
|
|
294
177
|
## Documentation
|
|
295
178
|
|
|
296
179
|
| Document | What it covers |
|
|
297
180
|
| --- | --- |
|
|
298
|
-
| [Architecture](docs/GATEWAY-ARCHITECTURE.md) |
|
|
181
|
+
| [Architecture](docs/GATEWAY-ARCHITECTURE.md) | Topology, adapters, control plane, federation, protocol versions, and the OS-boundary permission model |
|
|
299
182
|
| [Delivery](docs/DELIVERY.md) | Delivery semantics, tokens, settlement states, and retry rules |
|
|
300
|
-
| [Configuration](docs/CONFIGURATION.md) | Environment variables,
|
|
301
|
-
| [
|
|
302
|
-
| [Security policy](SECURITY.md) | How to report a vulnerability, and the boundary in depth |
|
|
183
|
+
| [Configuration](docs/CONFIGURATION.md) | Environment variables, `nodes.json`, the launchd service, and addressing |
|
|
184
|
+
| [Security policy](SECURITY.md) | The boundary in depth, and how to report a vulnerability |
|
|
303
185
|
| [Contributing](CONTRIBUTING.md) | Where changes go, and how to run the deterministic suite |
|
|
304
186
|
| [Changelog](CHANGELOG.md) | What each release contains |
|
|
305
187
|
| [Agent skill](skills/embassy-peer/SKILL.md) | The workflow an agent follows to operate Embassy |
|