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.
- package/CHANGELOG.md +77 -0
- package/CONTRIBUTING.md +23 -36
- package/README.md +123 -222
- package/SECURITY.md +72 -93
- 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 +45 -17
- 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 +7 -19
- package/dist/src/gateway/claude-peer.js.map +1 -1
- package/dist/src/gateway/cli.d.ts +17 -7
- package/dist/src/gateway/cli.js +945 -265
- 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 +66 -80
- package/dist/src/gateway/control.js +92 -147
- 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 +13 -11
- package/dist/src/gateway/peer-protocol.js +14 -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 +11 -7
- package/dist/src/gateway/providers.js +49 -50
- package/dist/src/gateway/providers.js.map +1 -1
- package/dist/src/gateway/server.d.ts +4 -14
- package/dist/src/gateway/server.js +32 -54
- 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 +119 -38
- package/dist/src/gateway/service.js +754 -798
- package/dist/src/gateway/service.js.map +1 -1
- package/dist/src/gateway/status-view.d.ts +119 -0
- package/dist/src/gateway/status-view.js +484 -0
- package/dist/src/gateway/status-view.js.map +1 -0
- package/dist/src/gateway/store.d.ts +106 -21
- package/dist/src/gateway/store.js +463 -537
- package/dist/src/gateway/store.js.map +1 -1
- package/dist/src/gateway/types.d.ts +64 -102
- package/dist/src/gateway/types.js +40 -86
- package/dist/src/gateway/types.js.map +1 -1
- package/docs/CONFIGURATION.md +174 -45
- package/docs/DELIVERY.md +11 -11
- package/docs/GATEWAY-ARCHITECTURE.md +292 -384
- package/package.json +4 -12
- package/skills/embassy-peer/SKILL.md +69 -92
- 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/claude-helper-client.d.ts +0 -2
- package/dist/src/gateway/claude-helper-client.js +0 -2
- package/dist/src/gateway/claude-helper-client.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,197 @@
|
|
|
12
10
|
[](LICENSE)
|
|
13
11
|
[](package.json)
|
|
14
12
|
|
|
15
|
-
|
|
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
|
-
|
|
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
|
|
25
|
+
which -a embassy
|
|
26
|
+
embassy --version
|
|
27
|
+
ssh <node> 'which -a embassy; embassy --version'
|
|
36
28
|
```
|
|
37
29
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
42
|
+
## Your first message in four commands
|
|
55
43
|
|
|
56
|
-
|
|
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
|
|
47
|
+
embassy register-codex --alias codex-reviewer@your-host
|
|
62
48
|
```
|
|
63
49
|
|
|
64
|
-
|
|
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`
|
|
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
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
74
|
+
## After any Claude Code or Codex CLI update
|
|
119
75
|
|
|
120
76
|
```bash
|
|
121
|
-
embassy
|
|
77
|
+
embassy check
|
|
122
78
|
```
|
|
123
79
|
|
|
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.
|
|
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
|
-
|
|
82
|
+
```text
|
|
83
|
+
embassy check 50066f60 → codex-reviewer@this-mac
|
|
129
84
|
|
|
130
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
147
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
111
|
+
## Observability
|
|
197
112
|
|
|
198
|
-
|
|
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
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
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
|
-
|
|
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
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
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 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).
|
|
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
|
-
|
|
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
|
-
- **
|
|
279
|
-
- **
|
|
280
|
-
- **
|
|
281
|
-
- **
|
|
282
|
-
- **
|
|
283
|
-
|
|
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
|
-
|
|
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
|
-
##
|
|
192
|
+
## Upgrading from 2.x
|
|
288
193
|
|
|
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.
|
|
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) |
|
|
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,
|
|
301
|
-
| [
|
|
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 |
|