agent-embassy 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +61 -0
- package/CONTRIBUTING.md +122 -0
- package/LICENSE +21 -0
- package/README.md +185 -0
- package/README.zh-CN.md +185 -0
- package/SECURITY.md +224 -0
- package/assets/live-dashboard/app.css +1610 -0
- package/assets/mark-seal.svg +7 -0
- package/assets/mark.svg +7 -0
- package/assets/social-preview.png +0 -0
- package/assets/vendor/react/LICENSE +21 -0
- package/assets/vendor/react/react-dom.production.min.js +267 -0
- package/assets/vendor/react/react.production.min.js +31 -0
- package/dist/src/errors.d.ts +5 -0
- package/dist/src/errors.js +11 -0
- package/dist/src/errors.js.map +1 -0
- package/dist/src/gateway/claude-compatibility-scratch.d.ts +18 -0
- package/dist/src/gateway/claude-compatibility-scratch.js +158 -0
- package/dist/src/gateway/claude-compatibility-scratch.js.map +1 -0
- package/dist/src/gateway/claude-helper-client.d.ts +43 -0
- package/dist/src/gateway/claude-helper-client.js +212 -0
- package/dist/src/gateway/claude-helper-client.js.map +1 -0
- package/dist/src/gateway/claude-helper-protocol.d.ts +172 -0
- package/dist/src/gateway/claude-helper-protocol.js +373 -0
- package/dist/src/gateway/claude-helper-protocol.js.map +1 -0
- package/dist/src/gateway/claude-helper-supervisor.d.ts +74 -0
- package/dist/src/gateway/claude-helper-supervisor.js +497 -0
- package/dist/src/gateway/claude-helper-supervisor.js.map +1 -0
- package/dist/src/gateway/claude-helper.d.ts +1 -0
- package/dist/src/gateway/claude-helper.js +269 -0
- package/dist/src/gateway/claude-helper.js.map +1 -0
- package/dist/src/gateway/claude-peer.d.ts +273 -0
- package/dist/src/gateway/claude-peer.js +2359 -0
- package/dist/src/gateway/claude-peer.js.map +1 -0
- package/dist/src/gateway/claude-runtime.d.ts +40 -0
- package/dist/src/gateway/claude-runtime.js +302 -0
- package/dist/src/gateway/claude-runtime.js.map +1 -0
- package/dist/src/gateway/cli-copy.d.ts +8 -0
- package/dist/src/gateway/cli-copy.en.d.ts +13 -0
- package/dist/src/gateway/cli-copy.en.js +43 -0
- package/dist/src/gateway/cli-copy.en.js.map +1 -0
- package/dist/src/gateway/cli-copy.js +19 -0
- package/dist/src/gateway/cli-copy.js.map +1 -0
- package/dist/src/gateway/cli-copy.zh-CN.d.ts +13 -0
- package/dist/src/gateway/cli-copy.zh-CN.js +43 -0
- package/dist/src/gateway/cli-copy.zh-CN.js.map +1 -0
- package/dist/src/gateway/cli.d.ts +44 -0
- package/dist/src/gateway/cli.js +969 -0
- package/dist/src/gateway/cli.js.map +1 -0
- package/dist/src/gateway/codex-app-server.d.ts +310 -0
- package/dist/src/gateway/codex-app-server.js +1746 -0
- package/dist/src/gateway/codex-app-server.js.map +1 -0
- package/dist/src/gateway/codex-local-transport.d.ts +81 -0
- package/dist/src/gateway/codex-local-transport.js +617 -0
- package/dist/src/gateway/codex-local-transport.js.map +1 -0
- package/dist/src/gateway/codex-registration-generation.d.ts +5 -0
- package/dist/src/gateway/codex-registration-generation.js +19 -0
- package/dist/src/gateway/codex-registration-generation.js.map +1 -0
- package/dist/src/gateway/codex-registration-succession.d.ts +209 -0
- package/dist/src/gateway/codex-registration-succession.js +588 -0
- package/dist/src/gateway/codex-registration-succession.js.map +1 -0
- package/dist/src/gateway/compatibility.d.ts +70 -0
- package/dist/src/gateway/compatibility.js +252 -0
- package/dist/src/gateway/compatibility.js.map +1 -0
- package/dist/src/gateway/config.d.ts +24 -0
- package/dist/src/gateway/config.js +130 -0
- package/dist/src/gateway/config.js.map +1 -0
- package/dist/src/gateway/control.d.ts +308 -0
- package/dist/src/gateway/control.js +1573 -0
- package/dist/src/gateway/control.js.map +1 -0
- package/dist/src/gateway/dashboard-copy.d.ts +7 -0
- package/dist/src/gateway/dashboard-copy.en.d.ts +506 -0
- package/dist/src/gateway/dashboard-copy.en.js +507 -0
- package/dist/src/gateway/dashboard-copy.en.js.map +1 -0
- package/dist/src/gateway/dashboard-copy.js +516 -0
- package/dist/src/gateway/dashboard-copy.js.map +1 -0
- package/dist/src/gateway/dashboard-copy.zh-CN.d.ts +506 -0
- package/dist/src/gateway/dashboard-copy.zh-CN.js +507 -0
- package/dist/src/gateway/dashboard-copy.zh-CN.js.map +1 -0
- package/dist/src/gateway/dashboard-model.d.ts +207 -0
- package/dist/src/gateway/dashboard-model.js +720 -0
- package/dist/src/gateway/dashboard-model.js.map +1 -0
- package/dist/src/gateway/dashboard.d.ts +26 -0
- package/dist/src/gateway/dashboard.js +941 -0
- package/dist/src/gateway/dashboard.js.map +1 -0
- package/dist/src/gateway/delivery-machine.d.ts +235 -0
- package/dist/src/gateway/delivery-machine.js +540 -0
- package/dist/src/gateway/delivery-machine.js.map +1 -0
- package/dist/src/gateway/instance-lease.d.ts +21 -0
- package/dist/src/gateway/instance-lease.js +549 -0
- package/dist/src/gateway/instance-lease.js.map +1 -0
- package/dist/src/gateway/live-dashboard-app/app.js +2914 -0
- package/dist/src/gateway/live-dashboard-assets.d.ts +10 -0
- package/dist/src/gateway/live-dashboard-assets.js +73 -0
- package/dist/src/gateway/live-dashboard-assets.js.map +1 -0
- package/dist/src/gateway/live-dashboard-bootstrap.d.ts +36 -0
- package/dist/src/gateway/live-dashboard-bootstrap.js +176 -0
- package/dist/src/gateway/live-dashboard-bootstrap.js.map +1 -0
- package/dist/src/gateway/live-dashboard-command.d.ts +54 -0
- package/dist/src/gateway/live-dashboard-command.js +324 -0
- package/dist/src/gateway/live-dashboard-command.js.map +1 -0
- package/dist/src/gateway/live-dashboard-http.d.ts +41 -0
- package/dist/src/gateway/live-dashboard-http.js +445 -0
- package/dist/src/gateway/live-dashboard-http.js.map +1 -0
- package/dist/src/gateway/live-dashboard-protocol.d.ts +38 -0
- package/dist/src/gateway/live-dashboard-protocol.js +156 -0
- package/dist/src/gateway/live-dashboard-protocol.js.map +1 -0
- package/dist/src/gateway/live-dashboard-server.d.ts +33 -0
- package/dist/src/gateway/live-dashboard-server.js +130 -0
- package/dist/src/gateway/live-dashboard-server.js.map +1 -0
- package/dist/src/gateway/live-dashboard-stream.d.ts +46 -0
- package/dist/src/gateway/live-dashboard-stream.js +233 -0
- package/dist/src/gateway/live-dashboard-stream.js.map +1 -0
- package/dist/src/gateway/live-dashboard.d.ts +31 -0
- package/dist/src/gateway/live-dashboard.js +190 -0
- package/dist/src/gateway/live-dashboard.js.map +1 -0
- package/dist/src/gateway/locale.d.ts +4 -0
- package/dist/src/gateway/locale.js +10 -0
- package/dist/src/gateway/locale.js.map +1 -0
- package/dist/src/gateway/progress-watch-machine.d.ts +97 -0
- package/dist/src/gateway/progress-watch-machine.js +172 -0
- package/dist/src/gateway/progress-watch-machine.js.map +1 -0
- package/dist/src/gateway/providers.d.ts +287 -0
- package/dist/src/gateway/providers.js +2451 -0
- package/dist/src/gateway/providers.js.map +1 -0
- package/dist/src/gateway/server.d.ts +57 -0
- package/dist/src/gateway/server.js +264 -0
- package/dist/src/gateway/server.js.map +1 -0
- package/dist/src/gateway/service.d.ts +449 -0
- package/dist/src/gateway/service.js +4831 -0
- package/dist/src/gateway/service.js.map +1 -0
- package/dist/src/gateway/store.d.ts +340 -0
- package/dist/src/gateway/store.js +4047 -0
- package/dist/src/gateway/store.js.map +1 -0
- package/dist/src/gateway/types.d.ts +514 -0
- package/dist/src/gateway/types.js +414 -0
- package/dist/src/gateway/types.js.map +1 -0
- package/dist/src/mutex.d.ts +4 -0
- package/dist/src/mutex.js +23 -0
- package/dist/src/mutex.js.map +1 -0
- package/docs/DESIGN.md +134 -0
- package/docs/GATEWAY-ARCHITECTURE.md +858 -0
- package/package.json +80 -0
- package/skills/embassy-peer/SKILL.md +198 -0
- package/skills/embassy-peer/agents/openai.yaml +4 -0
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project are documented in this file.
|
|
4
|
+
|
|
5
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
|
6
|
+
|
|
7
|
+
## [1.0.0] - 2026-08-09
|
|
8
|
+
|
|
9
|
+
### Added
|
|
10
|
+
|
|
11
|
+
- **Multi-pair consent graph** — a pair is one explicit permission edge between one Claude session and one Codex task, and pairs are many-to-many: one Claude session may hold edges to several Codex tasks and one Codex task to several Claude sessions (128 pairs by default, 256 hard cap). `embassy pair` / `embassy unpair` name both ends explicitly and carry the inherited `CODEX_THREAD_ID` as attestation; `select-claude` / `unselect-claude` remain as one-task shorthands that fail closed when the Codex end is ambiguous. Without an edge, a sender settles terminally as `SENDER_NOT_PAIRED`; `embassy serve --inbound open` stays the only directional no-edge exception and grants only a bounded correlated reply capability. Each registered task's native advertisement is owned by a supervised real-PID helper process; the broker remains the sole owner of state, queues, and dispatch. The snapshot carries first-class `pairs[]` with per-edge counters, and the live dashboard renders the consent topology with exact two-endpoint pair/unpair actions.
|
|
12
|
+
- **Progress watches** — opt-in, owner-held conversation supervision for long-running work: open with a leading `TRACK:` body or `--track [--idle-minutes n]` on a send. Any activity — including the worker's thread-status transitions, as proof-of-life — resets the idle clock; a genuinely quiet conversation receives at most two gateway-authored bilingual nudges with backoff before settling `unresponsive`. Only the owner ends tracking, with a correlated `DONE:` message or `embassy untrack --conversation <token>`. Watches persist broker restarts (conversation capability degrades to route-level and is journaled) and surface in a body-free Progress Supervision dashboard card in both locales.
|
|
13
|
+
- **Compatibility tiers and on-machine certification** — `EMBASSY_COMPAT_POLICY=observed` (default) admits an unknown same-major provider build only after its bounded schema probe passes; `strict` admits only the release's certified inventory. Three explicit tiers: certified, schema-attested, incompatible, with durable per-surface attestations. `embassy compat-check` runs bounded no-traffic probes; `embassy compat-certify [--codex <alias>] [--with-turn]` adds on-machine wire evidence via a short-lived scratch Claude print session and idle Codex thread operations, reporting per-surface outcomes with distinct exit codes (7 Claude, 8 Codex, 9 both). Certification evidence, including retained failures, renders in the Diagnostics tab; user-owned LaunchAgent recipes (update-triggered certify plus daily check) are documented. Registry probing shares runtime per-record isolation — one malformed live record can never poison boot — and startup state migration commits durably only after provider admission, so a failed upgrade leaves the prior state file byte-exact.
|
|
14
|
+
- **Attempt-then-ack delivery** — native Claude ingress gets an immediate exact dispatch attempt; fast terminal evidence suppresses the `held` frame entirely, true queue or provider deferral sends `held` immediately, and unresolved dispatch acknowledges at a bounded prompt boundary. Clean prewrite retries are bounded; ambiguous writes are never replayed; terminal truth remains first-wins. `delivered` still means released, never read.
|
|
15
|
+
- **Bounded snapshot observability** — suffix-only conversation correlation, body-free operator activity kinds, retained-evidence deadline buckets, and explicit peer-validation state across the static and live bilingual dashboards.
|
|
16
|
+
|
|
17
|
+
- Actionable failure copy for the paths a new operator meets first: state-directory or socket safety violations, unknown delivery tokens, and `wait-delivery` timeouts each explain themselves and name the next command instead of a generic rejection line, in both locales.
|
|
18
|
+
- Auto-update drift is fail-closed but self-explanatory: when the installed Claude Code moves past this build's pin, `serve` refuses with `CLAUDE_VERSION_DRIFT`, names the found and pinned versions, and points at `npm update -g agent-embassy` — tampering-shaped launcher states keep the strict refusal with nothing reflected.
|
|
19
|
+
- **Embassy**, a local, single-user, bidirectional message gateway between running Claude Code sessions and Codex desktop tasks, packaged as `agent-embassy` with CLI binary `embassy`.
|
|
20
|
+
- `embassy serve` — foreground broker that publishes one process-owned `codex-*` peer into Claude Code's live-session registry and opens its own callback socket; never daemonizes; removes both on shutdown.
|
|
21
|
+
- `register-codex` / `unregister-codex` — register or retire a `codex-*` route, run from inside the Codex task itself so it inherits `CODEX_THREAD_ID`.
|
|
22
|
+
- `select-claude` / `unselect-claude` — explicitly select or unselect a discovered Claude destination; Codex-to-Claude sends never select a candidate implicitly.
|
|
23
|
+
- `send-to-claude` / `send-to-codex` / `reply` — bounded, stdin-only message sends (16 KiB max) and conversation-token continuation, in both directions.
|
|
24
|
+
- `health` / `status` / `refresh-dashboard` — liveness check, sanitized snapshot (including `availablePeers`), and dashboard regeneration.
|
|
25
|
+
- `delivery-status` / `wait-delivery` — read one delivery tracker by its opaque `dlv_` token, or wait for it to settle; `wait-delivery` exits `0` only for `delivered`, `6` for any other terminal state, `3` for an unknown token, and `4` for a local wait timeout.
|
|
26
|
+
- Metadata-only, self-contained static dashboards — `gateway-dashboard.html` and `gateway-dashboard.zh-CN.html`, both mode 0600, both atomically rewritten on every publish, cross-linked in the page, with no JavaScript, no server, no external assets, no self-refresh, and no message content shown.
|
|
27
|
+
- Delivery semantics: ordinary queue-while-busy plus exact Claude→Codex `STEER:` admission at App Server's next tool-call boundary, never mid-generation and never by forced interruption. Cleanly unavailable steering falls back to the normal queue; each route retains at most three queued steers and settles the displaced oldest message with an explicit journal event and normal receipt. Normalized terminal receipts remain `delivered`, `unconfirmed` (transport write completed, terminal native evidence unavailable), `ambiguous` (write outcome unknown), `expired`, `failed`, and `cancelled`. Native failure acknowledgements always retain one safe reason code; `EMBASSY_DELIVERY_NOTICES=merged` avoids a duplicate terminal diagnostic user frame by default, while `verbose` restores it and `quiet` suppresses all gateway-authored user-frame notices. Neither `unconfirmed` nor `ambiguous` authorizes a retry.
|
|
28
|
+
- Repo-shipped agent skill (`skills/embassy-peer/SKILL.md`) teaching the full operator/agent workflow — health, registration, sending, replying, queue-state interpretation — without exposing identifiers or message bodies.
|
|
29
|
+
- One host-wide crash-reclaimable owner lease, acquired before provider setup and independent of `EMBASSY_STATE_DIR`, so only one foreground Embassy controller can advertise routes for a login account.
|
|
30
|
+
|
|
31
|
+
- **Live dashboard companion** — `embassy dashboard --live [--lang en|zh-CN]` starts a separate foreground process that streams sanitized metadata to a browser tab on `127.0.0.1`; `embassy serve` remains TCP-free and HTTP-free.
|
|
32
|
+
- **One-use token authentication** — live companion access bootstraps via a 256-bit URL-fragment token exchanged for a path-scoped `HttpOnly` `SameSite=Strict` session cookie with Host, Origin, and sentinel validation.
|
|
33
|
+
- **Bounded browser actions** — the live companion exposes no CORS headers, generic control/provider routes, storage, telemetry, or external assets. Its sole mutation route accepts only confirmed exact two-endpoint pair, unpair, and refresh-discovery actions, with a 1 KiB body cap and six-action-per-minute token bucket; each mutation touches only the edge it names, and it cannot register tasks, send, reply, approve, interrupt, or change settings.
|
|
34
|
+
- **Bilingual dashboards** — the static pair renders in English and Simplified Chinese from one catalog and is switched by an in-page link; `--lang en|zh-CN` is a live-companion flag and is not accepted by `refresh-dashboard`.
|
|
35
|
+
|
|
36
|
+
### Changed
|
|
37
|
+
|
|
38
|
+
- Binary renamed from `claude-codex-gateway` to `embassy`; the old name ships for one release as a deprecated alias.
|
|
39
|
+
- State root moved from `~/.local/state/claude-agent-bridge/gateway` to `~/.local/state/agent-embassy`. This is a clean reset, not a migration — old gateway state is not carried forward. For one release, Embassy bounded-reads only the exact legacy default ownership marker and controller-lock record, then creates and holds that lock so a prototype cannot run alongside v1. A pre-existing legacy lock is preserved and blocks startup; after confirming no prototype process remains, remove that exact stale lock manually, then register and select again.
|
|
40
|
+
- Compatibility pins re-established for this release: Claude Code **2.1.226** / peer protocol 1 (with still-running 2.1.224–2.1.225 sessions remaining discoverable during a patch-upgrade overlap window), and Codex App Server **0.147.0**, resolved by exact path. Under the default `observed` policy an unknown same-major version is admitted only after its bounded schema probe passes; everything else fails closed.
|
|
41
|
+
- The public v1 launcher is macOS-only and local-host-only.
|
|
42
|
+
- Validated native records named `codex-*` are excluded from Claude destination discovery; they are gateway advertisements, not selectable Claude sessions.
|
|
43
|
+
- After Embassy restarts, a persisted Claude binding starts stale. The next authorized, complete discovery may reactivate only the exact same Claude session UUID under the same provider, host, and owner lease, adopting its latest name after workspace/provider revalidation. Changed, missing, incomplete, or ambiguous identity stays stale. Queued text, callbacks, receipt handles, pending replies, and conversation capability are never restored.
|
|
44
|
+
- Re-running `register-codex` replaces a closed or faulted App Server connector; an idle recovered route wakes held work without retrying any ambiguous write.
|
|
45
|
+
- The first successful Codex registration fixes its exact alias, task, and host until it is explicitly succeeded. Exact re-registration remains available for connector recovery. `register-codex --alias <new> --succeeds <current>`, run from inside the successor task on the same host, is the only way to change the registered Codex identity without restarting the broker: Embassy freezes the outgoing route, drains its accepted work to terminal settlement, then publishes the successor on a fresh listener generation. Nothing transfers — no queued body, conversation, reply capability, or delivery token — and a succession that cannot be completed pins the identity fail-closed until manual recovery rather than leaving two live registrations.
|
|
46
|
+
- Failed reactivation of a retained Codex route, or a fresh registration whose cleanup cannot be fully confirmed, pins that exact identity fail-closed until exact retry or confirmed unregister followed by restart.
|
|
47
|
+
- Pairs are additive, bounded, and per-edge: adding an edge never retires another, and removing one invalidates its active conversation capabilities before the change is published. Explicitly requested endpoint replacement (registration succession) atomically settles the outgoing endpoint's accepted work before the replacement is exposed; a half-replaced intermediate state is never published.
|
|
48
|
+
|
|
49
|
+
### Removed
|
|
50
|
+
|
|
51
|
+
- The one-way MCP task lifecycle (the six `claude_task_*` tools) existed only in the unpublished prototype. It was never released publicly and is not present in Embassy v1.
|
|
52
|
+
|
|
53
|
+
### Security
|
|
54
|
+
|
|
55
|
+
- No network surface in the broker: `embassy serve` opens no TCP listener and no HTTP server, makes no provider API call, and sends no telemetry; its control and callback surfaces are private Unix-domain sockets. The opt-in `embassy dashboard --live` companion is the only network listener Embassy can create — a separate foreground process bound to `127.0.0.1` on an ephemeral port, token-authenticated, and limited to the three route-consent actions described above. Delivered content still enters the receiving cloud-backed product as an ordinary model turn.
|
|
56
|
+
- Same-UID containment, not authentication: provider identity is inherited from the process environment (a Codex task's `CODEX_THREAD_ID` or a Claude session's messaging socket, never both), and every mutation is additionally checked against route ownership, exact thread/session generation, source alias, and bounds.
|
|
57
|
+
- Nothing persisted beyond route rebinding: bodies, prompts, replies, raw provider frames, and socket paths are never persisted. Provider-native identifiers (Codex thread ID, Claude session UUID) are kept only inside the closed, mode-0600 private route binding used to re-observe a route after restart.
|
|
58
|
+
- Every registered Codex task is visible to every compatible live Claude session running as the same OS user, but paired mode accepts only sessions holding an explicit pair edge with that exact task — register only when comfortable with every currently running compatible Claude session, and `unregister-codex` when done.
|
|
59
|
+
- Embassy never sets, relaxes, or overrides a Codex task's approval or sandbox policy and never answers an approval request. Claude-initiated turns use the task's existing native policy.
|
|
60
|
+
- Claude-to-Codex reachability does not select that session for outbound Codex-to-Claude delivery. In the opposite direction, Claude's native `crossSessionInbound` control governs messages entering the selected Claude session.
|
|
61
|
+
- Version attestation (a bounded `claude --version` in a scrubbed environment) proves compatibility, not authenticity.
|
package/CONTRIBUTING.md
ADDED
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
# Contributing to Embassy
|
|
2
|
+
|
|
3
|
+
Embassy connects two powerful local agent runtimes across version-pinned native
|
|
4
|
+
interfaces. Small changes can alter permission, privacy, or delivery behavior,
|
|
5
|
+
so contributions should be narrow, testable, and explicit about boundaries.
|
|
6
|
+
|
|
7
|
+
## Development setup
|
|
8
|
+
|
|
9
|
+
Use macOS, Node.js 20 or newer, and the npm version declared in `package.json`.
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
npm ci
|
|
13
|
+
npm run check
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
`npm run check` type-checks and runs the deterministic test suite. Routine tests
|
|
17
|
+
use fake Claude peers, fake App Server transports, and temporary directories;
|
|
18
|
+
they must not contact Anthropic, OpenAI, SSH hosts, live provider sockets, or
|
|
19
|
+
models.
|
|
20
|
+
|
|
21
|
+
## Before opening a pull request
|
|
22
|
+
|
|
23
|
+
- Run `npm run check`.
|
|
24
|
+
- Add deterministic regression coverage for routing, protocol, persistence,
|
|
25
|
+
permission, process-lifecycle, or redaction changes.
|
|
26
|
+
- Keep the pull request focused and explain every security-boundary change.
|
|
27
|
+
- Update README and architecture documentation when public behavior changes.
|
|
28
|
+
- Verify that public files contain no credentials, native IDs, message bodies,
|
|
29
|
+
local state, or personal absolute paths.
|
|
30
|
+
- Do not commit `node_modules`, `dist`, package archives, generated dashboards,
|
|
31
|
+
logs, environment files, or live-validation artifacts.
|
|
32
|
+
|
|
33
|
+
## Architecture rules
|
|
34
|
+
|
|
35
|
+
### Routing and identity
|
|
36
|
+
|
|
37
|
+
- Codex tasks self-register through inherited `CODEX_THREAD_ID` and a
|
|
38
|
+
`codex-*` alias. Never add a thread-ID argument or global task-history scan.
|
|
39
|
+
- Codex-to-Claude sends require a previously selected compatible live session.
|
|
40
|
+
Do not auto-select during send.
|
|
41
|
+
- Exact compatible live same-UID Claude sessions may reach the registered
|
|
42
|
+
native Codex peer without becoming outbound-selected.
|
|
43
|
+
- Claude's session UUID is its stable logical identity. Current names are a
|
|
44
|
+
live index; do not add historical-name routing or PID/socket identity.
|
|
45
|
+
- Preserve current-name collision refusal and endpoint-generation fencing.
|
|
46
|
+
|
|
47
|
+
### Provider adapters
|
|
48
|
+
|
|
49
|
+
Claude Code's cross-session feature is official. Embassy's use of its external
|
|
50
|
+
registry and peer socket shape is an internal, version-pinned adapter. Codex App
|
|
51
|
+
Server is likewise version-pinned. Do not widen either compatibility range
|
|
52
|
+
without a documented review and deterministic fixtures for the new version.
|
|
53
|
+
|
|
54
|
+
The gateway may publish one process-owned `codex-*` peer so Claude's native
|
|
55
|
+
`ListAgents` and `SendMessage` tools can reach Codex. It must never overwrite a
|
|
56
|
+
foreign registry record, claim to be a Claude model session, or unlink a socket
|
|
57
|
+
whose exact generation it no longer owns.
|
|
58
|
+
|
|
59
|
+
App Server calls use a closed allowlist. Do not add a generic RPC method,
|
|
60
|
+
`turn/steer`, approval responses, history retrieval, shell execution, settings
|
|
61
|
+
mutation, or provider authentication. Keep `experimentalApi: true`
|
|
62
|
+
non-configurable and limited to `thread/resume.excludeTurns: true`; every resume
|
|
63
|
+
must require an empty `thread.turns` response.
|
|
64
|
+
|
|
65
|
+
### Permissions
|
|
66
|
+
|
|
67
|
+
Embassy does not set or override a Codex task's persistent approval or sandbox
|
|
68
|
+
policy. Registration is the gateway reachability boundary. The connector may
|
|
69
|
+
observe native route and approval-waiting status, but must not classify policy
|
|
70
|
+
or turn workspace/settings metadata into a second authorization gate.
|
|
71
|
+
|
|
72
|
+
For Codex-to-Claude delivery, Claude's `crossSessionInbound` behavior remains
|
|
73
|
+
native. Do not route around a hold or refusal or fabricate a successful receipt.
|
|
74
|
+
|
|
75
|
+
### Delivery and state
|
|
76
|
+
|
|
77
|
+
- Bodies and reply addresses are transient and bounded.
|
|
78
|
+
- Queue while a Codex task is busy; do not interrupt an unrelated turn.
|
|
79
|
+
- Distinguish gateway acceptance, transport progress, destination acceptance,
|
|
80
|
+
terminal failure, ambiguity, expiry, and restart abandonment.
|
|
81
|
+
- Never retry an ambiguous provider write. Requeue only a confirmed clean
|
|
82
|
+
deferral that has not crossed an ambiguous mutation boundary.
|
|
83
|
+
- Restarts discard bodies and leave restored routes stale until exact
|
|
84
|
+
re-observation.
|
|
85
|
+
- Persist native route identifiers only in the closed private binding schema.
|
|
86
|
+
Keep them out of events, snapshots, dashboard rows, logs, errors, and CLI
|
|
87
|
+
output. The only CLI exception is a UUID explicitly supplied by the user as a
|
|
88
|
+
Claude selector.
|
|
89
|
+
|
|
90
|
+
### Local control surface
|
|
91
|
+
|
|
92
|
+
`embassy serve` may use one private same-user control UDS and publish two inert,
|
|
93
|
+
metadata-only static dashboard files. It must not listen on TCP or HTTP. The
|
|
94
|
+
only reviewed exception is the separately invoked foreground
|
|
95
|
+
`embassy dashboard --live` companion, which binds an authenticated OS-assigned
|
|
96
|
+
port on exact IPv4 loopback and exposes only the reviewed select-Claude,
|
|
97
|
+
unselect-Claude, and refresh-discovery mutations, never a provider or generic
|
|
98
|
+
control method. Do not
|
|
99
|
+
add a wildcard/remote listener, external assets, storage, service workers,
|
|
100
|
+
telemetry, or additional mutation endpoints. Keep the public v1 launcher foreground,
|
|
101
|
+
macOS-only, and local-host-only.
|
|
102
|
+
|
|
103
|
+
## Live validation
|
|
104
|
+
|
|
105
|
+
Do not run a live probe merely because a test would be convenient. Live Claude
|
|
106
|
+
registry discovery, peer connection, provider messaging, App Server turns, and
|
|
107
|
+
SSH attachment are separate external actions.
|
|
108
|
+
|
|
109
|
+
A live action requires an explicit user request that identifies its scope. For
|
|
110
|
+
a message, confirm the exact destination and body, send only once, avoid fanout,
|
|
111
|
+
and do not retry an ambiguous result. Never put real provider traffic in CI.
|
|
112
|
+
|
|
113
|
+
## Reporting security issues
|
|
114
|
+
|
|
115
|
+
Follow [SECURITY.md](SECURITY.md). Use a private GitHub Security Advisory rather
|
|
116
|
+
than a public issue, and replace sensitive local values with synthetic ones.
|
|
117
|
+
|
|
118
|
+
Two platform notes: the suite binds Unix-domain sockets under `TMPDIR`, and
|
|
119
|
+
macOS caps socket paths at ~104 bytes — keep `TMPDIR` short (CI pins
|
|
120
|
+
`TMPDIR=/tmp`; do the same locally if the transport tests hang). On Linux,
|
|
121
|
+
the darwin-only lease and peer-generation tests skip explicitly (the host
|
|
122
|
+
lease spawns macOS's `/usr/bin/lockf`); macOS runs the full suite.
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 YuanpingSong
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
[English](README.md) · [简体中文](README.zh-CN.md)
|
|
2
|
+
|
|
3
|
+
<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">
|
|
5
|
+
</p>
|
|
6
|
+
|
|
7
|
+
# Embassy
|
|
8
|
+
|
|
9
|
+
**A local embassy for your AI agents.**
|
|
10
|
+
|
|
11
|
+
[](https://github.com/YuanpingSong/embassy/actions/workflows/ci.yml)
|
|
12
|
+
[](LICENSE)
|
|
13
|
+
[](package.json)
|
|
14
|
+
|
|
15
|
+
Your [Claude Code](https://code.claude.com) sessions and [Codex](https://chatgpt.com/codex) desktop tasks can't talk to each other. When one needs the other's perspective, you carry context between windows yourself. Embassy is a small local broker that lets them find each other by name and exchange messages in both directions — no plugins, no API keys, no cloud relay.
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
npm install -g agent-embassy
|
|
19
|
+
embassy serve
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
Or from source: `git clone https://github.com/YuanpingSong/embassy && cd embassy && npm ci && npm run build && npm link`.
|
|
23
|
+
|
|
24
|
+
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.
|
|
25
|
+
|
|
26
|
+
## Quickstart
|
|
27
|
+
|
|
28
|
+
**Requirements:** macOS, Node.js 20+, Claude Code 2.1.226 (still-running 2.1.224–2.1.225 sessions remain discoverable), and Codex desktop configured to use the managed standalone App Server 0.147.0. The Claude session you select as a destination needs [`crossSessionInbound`](docs/CONFIGURATION.md) enabled — that is Claude Code's own setting, configured in Claude Code, not in Embassy.
|
|
29
|
+
|
|
30
|
+
> **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.
|
|
31
|
+
|
|
32
|
+
### 1. Start Embassy
|
|
33
|
+
|
|
34
|
+
Run the foreground broker under the same OS account as Claude Code and Codex:
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
embassy serve
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
You should see `"status":"ready"`. In another terminal:
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
embassy health
|
|
44
|
+
embassy status
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
`status` lists `availablePeers` — the live Claude sessions you can select.
|
|
48
|
+
|
|
49
|
+
### 2. Register the Codex task
|
|
50
|
+
|
|
51
|
+
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:
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
embassy register-codex --alias codex-reviewer@this-mac
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
You should see `"accepted":true`. The `codex-` prefix is required for Claude discovery. To retire the task later, run `unregister-codex`.
|
|
58
|
+
|
|
59
|
+
### 3. Select a Claude destination
|
|
60
|
+
|
|
61
|
+
Pick one name from `availablePeers`:
|
|
62
|
+
|
|
63
|
+
```bash
|
|
64
|
+
embassy select-claude --alias advisor@this-mac
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
You should see `"accepted":true`. Registration and selection together form a pair — this Claude session and this Codex task can now exchange messages through Embassy. (`select-claude` is the one-task shorthand; `embassy pair --claude <name@host> --codex <codex-alias>` names both ends explicitly, and many pairs can coexist.)
|
|
68
|
+
|
|
69
|
+
### 4. Send a message
|
|
70
|
+
|
|
71
|
+
From the registered Codex task, send via stdin:
|
|
72
|
+
|
|
73
|
+
```bash
|
|
74
|
+
embassy send-to-claude \
|
|
75
|
+
--from codex-reviewer@this-mac \
|
|
76
|
+
--to advisor@this-mac \
|
|
77
|
+
--expects-reply <<'MSG'
|
|
78
|
+
Please review the current approach and identify the main risk.
|
|
79
|
+
MSG
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
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.
|
|
83
|
+
|
|
84
|
+
### 5. Follow up
|
|
85
|
+
|
|
86
|
+
Either side can continue the conversation:
|
|
87
|
+
|
|
88
|
+
```bash
|
|
89
|
+
embassy reply \
|
|
90
|
+
--conversation conv_<token> \
|
|
91
|
+
--alias codex-reviewer@this-mac <<'MSG'
|
|
92
|
+
Please expand on the migration risk.
|
|
93
|
+
MSG
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
### See it live
|
|
97
|
+
|
|
98
|
+
`embassy dashboard --live` opens a five-tab streaming view in the browser (overview, deliveries, routes, activity, diagnostics). See [Dashboard](docs/DASHBOARD.md) for details.
|
|
99
|
+
|
|
100
|
+
The broker also publishes mode-0600 static snapshots as `gateway-dashboard.html` and `gateway-dashboard.zh-CN.html`. Live dashboard mutations require the same-origin `X-Embassy-Request` sentinel.
|
|
101
|
+
|
|
102
|
+
## How it works
|
|
103
|
+
|
|
104
|
+
```text
|
|
105
|
+
Claude Code sessions Codex desktop task
|
|
106
|
+
(native ListAgents / (native App Server,
|
|
107
|
+
SendMessage tools) existing task policy)
|
|
108
|
+
│ │
|
|
109
|
+
▼ ▼
|
|
110
|
+
┌──────────────────── Embassy ─────────────────────────────┐
|
|
111
|
+
│ explicit routes │ queue while busy │ receipts │ dashboard │
|
|
112
|
+
└───────────────────────────────────────────────────────────┘
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
Embassy publishes each registered Codex task into Claude Code's live-session registry as its own `codex-*` peer. Compatible Claude sessions discover them through their native `ListAgents` and contact them with `SendMessage` — no plugin, MCP server, or settings change required.
|
|
116
|
+
|
|
117
|
+
A pair is one explicit permission edge between one Claude session and one Codex task — and pairs are many-to-many: one Claude session may hold edges to several Codex tasks, and one Codex task to several Claude sessions (bounded at 128 pairs by default). Every edge is created explicitly, with `pair` or the one-task `select-claude` shorthand; nothing is ever implied. Without an edge, a sender settles terminally as `SENDER_NOT_PAIRED`. `embassy serve --inbound open` is the explicit opt-out that restores any-session inbound.
|
|
118
|
+
|
|
119
|
+
Messages queue while the Codex task is busy and start an ordinary 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.
|
|
120
|
+
|
|
121
|
+
Every settled message produces a receipt. `delivered` means terminal provider evidence was observed — toward Codex, the App Server accepted the turn; toward Claude, the message was released into the session's native queue. Neither means the model read or acted on it. `unconfirmed` and `ambiguous` mean evidence is missing; they are terminal states and never auto-retried. See [Delivery](docs/DELIVERY.md) for the full semantics.
|
|
122
|
+
|
|
123
|
+
## The vocabulary
|
|
124
|
+
|
|
125
|
+
Four embassy terms name real features:
|
|
126
|
+
|
|
127
|
+
- **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.
|
|
128
|
+
- **The ledger** is the delivery record: a receipt for every settled message, and a metadata-only dashboard.
|
|
129
|
+
- **The pouch** is transit: bounded bodies, ephemeral inside Embassy, never persisted by it.
|
|
130
|
+
- **Consulates** are the roadmap: the same model extended to Codex tasks on remote hosts over attach-only SSH — designed, and deliberately disabled in v1.
|
|
131
|
+
|
|
132
|
+
## For agents
|
|
133
|
+
|
|
134
|
+
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.
|
|
135
|
+
|
|
136
|
+
## Commands
|
|
137
|
+
|
|
138
|
+
| Command | Run by | Purpose |
|
|
139
|
+
| --- | --- | --- |
|
|
140
|
+
| `serve` | operator | Start the foreground broker and dashboard |
|
|
141
|
+
| `health` / `status` | operator | Check liveness and inspect the sanitized snapshot |
|
|
142
|
+
| `refresh-dashboard` | operator | Regenerate both static dashboard files |
|
|
143
|
+
| `dashboard --live [--lang en\|zh-CN]` | operator | Start the live dashboard companion with bounded route-consent actions; requires a running `embassy serve` |
|
|
144
|
+
| `delivery-status` | either provider | Read one delivery tracker with `embassy delivery-status --token dlv_<token>` |
|
|
145
|
+
| `wait-delivery` | either provider | Wait for that tracker to settle, up to the delivery deadline |
|
|
146
|
+
| `register-codex` / `unregister-codex` | Codex task | Advertise or retire that exact task; for example, `embassy register-codex --alias codex-successor@this-mac --succeeds codex-reviewer@this-mac` hands the registration to a different task |
|
|
147
|
+
| `pair` / `unpair` | operator | Add or remove one explicit Claude↔Codex edge by naming both ends: `embassy pair --claude advisor@this-mac --codex codex-reviewer@this-mac` |
|
|
148
|
+
| `select-claude` / `unselect-claude` | operator | One-task shorthand for `pair`/`unpair`: resolves the Codex end only when it is unambiguous (inherited or sole registered task), otherwise fails closed |
|
|
149
|
+
| `send-to-claude` | registered Codex task | Send one bounded message to a paired Claude session |
|
|
150
|
+
| `send-to-codex` | Claude session | Send one bounded message using the inherited native reply identity |
|
|
151
|
+
| `reply` | either provider | Continue an active conversation by its public token |
|
|
152
|
+
|
|
153
|
+
## Safety in one minute
|
|
154
|
+
|
|
155
|
+
- **Local sockets only.** `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 `127.0.0.1` on an ephemeral port.
|
|
156
|
+
- **Same-UID containment, not authentication.** Caller identity is inherited from the local process environment. Route ownership and generation checks reduce mistakes, but are not a defense against code already running as your OS user.
|
|
157
|
+
- **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.
|
|
158
|
+
- **Bodies never persisted.** Message bodies, prompts, replies, and raw provider frames live only in memory. Metadata-only dashboard files are mode 0600 with no JavaScript.
|
|
159
|
+
|
|
160
|
+
See [SECURITY.md](SECURITY.md) for the full boundary and vulnerability-reporting process.
|
|
161
|
+
|
|
162
|
+
## What Embassy is not
|
|
163
|
+
|
|
164
|
+
- **Not an orchestrator.** It does not spawn agents or manage their work. It starts one turn per routed message and drains its queue when the task goes idle.
|
|
165
|
+
- **Not a hosted service.** Personal, same-machine, same-OS-account software.
|
|
166
|
+
- **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.
|
|
167
|
+
- **Not official.** Not affiliated with or endorsed by Anthropic or OpenAI.
|
|
168
|
+
|
|
169
|
+
## Documentation
|
|
170
|
+
|
|
171
|
+
| Document | What it covers |
|
|
172
|
+
| --- | --- |
|
|
173
|
+
| [Architecture](docs/GATEWAY-ARCHITECTURE.md) | The full design: topology, adapters, control plane, threat model, staged authorization ladder |
|
|
174
|
+
| [Delivery](docs/DELIVERY.md) | Delivery semantics, tokens, settlement states, and retry rules |
|
|
175
|
+
| [Configuration](docs/CONFIGURATION.md) | Environment variables, compatibility contract, and addressing rules |
|
|
176
|
+
| [Dashboard](docs/DASHBOARD.md) | Static and live dashboard setup, security model, and mutation actions |
|
|
177
|
+
| [Migration](docs/MIGRATION.md) | Migrating from the prototype gateway |
|
|
178
|
+
| [Security policy](SECURITY.md) | How to report a vulnerability, and the boundary in depth |
|
|
179
|
+
| [Contributing](CONTRIBUTING.md) | Where changes go, and how to run the deterministic suite |
|
|
180
|
+
| [Changelog](CHANGELOG.md) | What each release contains |
|
|
181
|
+
| [Agent skill](skills/embassy-peer/SKILL.md) | The workflow an agent follows to operate Embassy |
|
|
182
|
+
|
|
183
|
+
## License
|
|
184
|
+
|
|
185
|
+
[MIT](LICENSE)
|
package/README.zh-CN.md
ADDED
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
[English](README.md) · 简体中文
|
|
2
|
+
|
|
3
|
+
<p align="center">
|
|
4
|
+
<img src="https://raw.githubusercontent.com/YuanpingSong/embassy/main/assets/social-preview.png" alt="Embassy — 一个本地网关,用于在 Claude Code 会话与 Codex 桌面任务之间实现双向消息传递" width="720">
|
|
5
|
+
</p>
|
|
6
|
+
|
|
7
|
+
# Embassy
|
|
8
|
+
|
|
9
|
+
**属于你的 AI 代理本地使馆。**
|
|
10
|
+
|
|
11
|
+
[](https://github.com/YuanpingSong/embassy/actions/workflows/ci.yml)
|
|
12
|
+
[](LICENSE)
|
|
13
|
+
[](package.json)
|
|
14
|
+
|
|
15
|
+
你的 [Claude Code](https://code.claude.com) 会话和 [Codex](https://chatgpt.com/codex) 桌面任务彼此无法对话。当一方需要另一方的视角时,你只能在窗口之间手动搬运上下文。Embassy 是一个小型本地代理,让它们按名称互相发现并双向交换消息——无需插件、无需 API 密钥、无需云端中继。
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
npm install -g agent-embassy
|
|
19
|
+
embassy serve
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
或从源码构建:`git clone https://github.com/YuanpingSong/embassy && cd embassy && npm ci && npm run build && npm link`。
|
|
23
|
+
|
|
24
|
+
Embassy 专为单人、单一 macOS 账户以及你已信任以该用户身份运行的代理而设计。本项目是非官方的社区项目,与 Anthropic 或 OpenAI 没有任何关联或背书关系。
|
|
25
|
+
|
|
26
|
+
## 快速开始
|
|
27
|
+
|
|
28
|
+
**前置要求:** macOS、Node.js 20+、Claude Code 2.1.226(仍在运行的 2.1.224–2.1.225 会话保持可发现),以及配置为使用托管独立 App Server 0.147.0 的 Codex 桌面应用。你选择作为目的地的 Claude 会话需要启用 [`crossSessionInbound`](docs/CONFIGURATION.zh-CN.md)——这是 Claude Code 自身的设置,在 Claude Code 中配置,而非在 Embassy 中。
|
|
29
|
+
|
|
30
|
+
> **已知限制:** 仅当 Desktop 使用托管独立 App Server 时,Embassy 才能访问 Codex 任务。在该模式下,任务目前无法连接 Desktop 内置的应用内浏览器(`@Browser` 可加载但无法附着)。将 Desktop 切换回其默认的私有 App Server 会立即恢复内置浏览器——但会使这些任务对 Embassy 不可达。目前未发现其他能力回退,但这并非穷尽的能力对比测试。
|
|
31
|
+
|
|
32
|
+
### 1. 启动 Embassy
|
|
33
|
+
|
|
34
|
+
在与 Claude Code 和 Codex 相同的 OS 账户下运行前台代理:
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
embassy serve
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
你应看到 `"status":"ready"`。在另一个终端中:
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
embassy health
|
|
44
|
+
embassy status
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
`status` 列出 `availablePeers`——你可以选择的在线 Claude 会话。
|
|
48
|
+
|
|
49
|
+
### 2. 注册 Codex 任务
|
|
50
|
+
|
|
51
|
+
让你的 Codex 代理在其当前轮次中以 shell 步骤运行此命令——命令必须在任务内部运行,以便继承该任务的身份:
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
embassy register-codex --alias codex-reviewer@this-mac
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
你应看到 `"accepted":true`。`codex-` 前缀是 Claude 发现所必需的。之后若要注销该任务,运行 `unregister-codex`。
|
|
58
|
+
|
|
59
|
+
### 3. 选择 Claude 目的地
|
|
60
|
+
|
|
61
|
+
从 `availablePeers` 中选择一个名称:
|
|
62
|
+
|
|
63
|
+
```bash
|
|
64
|
+
embassy select-claude --alias advisor@this-mac
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
你应看到 `"accepted":true`。注册和选择共同构成一个配对——现在这个 Claude 会话和这个 Codex 任务可以通过 Embassy 交换消息。(`select-claude` 是单任务场景下的简写;`embassy pair --claude <name@host> --codex <codex-alias>` 显式指定两端,且多个配对可以并存。)
|
|
68
|
+
|
|
69
|
+
### 4. 发送消息
|
|
70
|
+
|
|
71
|
+
从已注册的 Codex 任务中,通过标准输入发送:
|
|
72
|
+
|
|
73
|
+
```bash
|
|
74
|
+
embassy send-to-claude \
|
|
75
|
+
--from codex-reviewer@this-mac \
|
|
76
|
+
--to advisor@this-mac \
|
|
77
|
+
--expects-reply <<'MSG'
|
|
78
|
+
Please review the current approach and identify the main risk.
|
|
79
|
+
MSG
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
你应看到一个 `conv_` 对话令牌和一个 `dlv_` 投递令牌。因为此次发送请求了回复,Claude 的响应会被自动路由回 Codex 任务。反方向上,兼容的 Claude 会话使用其原生的 `ListAgents` 和 `SendMessage` 工具联系 `codex-reviewer`——无需 Embassy 命令。
|
|
83
|
+
|
|
84
|
+
### 5. 后续跟进
|
|
85
|
+
|
|
86
|
+
任一方都可以继续对话:
|
|
87
|
+
|
|
88
|
+
```bash
|
|
89
|
+
embassy reply \
|
|
90
|
+
--conversation conv_<token> \
|
|
91
|
+
--alias codex-reviewer@this-mac <<'MSG'
|
|
92
|
+
Please expand on the migration risk.
|
|
93
|
+
MSG
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
### 实时查看
|
|
97
|
+
|
|
98
|
+
`embassy dashboard --live` 在浏览器中打开一个五选项卡流式视图(总览、投递、路由、活动、诊断)。详见[仪表盘](docs/DASHBOARD.zh-CN.md)。
|
|
99
|
+
|
|
100
|
+
代理还会以 mode 0600 发布静态快照 `gateway-dashboard.html` 与 `gateway-dashboard.zh-CN.html`。实时仪表盘的变更操作必须携带同源 `X-Embassy-Request` 哨兵头。
|
|
101
|
+
|
|
102
|
+
## 工作原理
|
|
103
|
+
|
|
104
|
+
```text
|
|
105
|
+
Claude Code 会话 Codex 桌面任务
|
|
106
|
+
(原生 ListAgents / (原生 App Server,
|
|
107
|
+
SendMessage 工具) 既有任务策略)
|
|
108
|
+
│ │
|
|
109
|
+
▼ ▼
|
|
110
|
+
┌──────────────────── Embassy ─────────────────────────────┐
|
|
111
|
+
│ 显式路由 │ 忙碌排队 │ 回执 │ 仪表盘 │
|
|
112
|
+
└───────────────────────────────────────────────────────────┘
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
Embassy 将每个已注册的 Codex 任务以各自的 `codex-*` 对等方身份发布到 Claude Code 的实时会话注册表中。兼容的 Claude 会话通过原生的 `ListAgents` 发现它们,并通过 `SendMessage` 与之通信——无需插件、MCP 服务器或设置更改。
|
|
116
|
+
|
|
117
|
+
配对是一个 Claude 会话与一个 Codex 任务之间的单一显式权限边,而配对关系是多对多的:一个 Claude 会话可以与多个 Codex 任务建立边,一个 Codex 任务也可以与多个 Claude 会话建立边(默认上限 128 个配对)。每条边都通过 `pair` 或单任务简写 `select-claude` 显式创建;一切都不会被隐式推断。没有边时,发送方以 `SENDER_NOT_PAIRED` 终局结算。`embassy serve --inbound open` 是显式的退出选项,可恢复任意会话入站。
|
|
118
|
+
|
|
119
|
+
消息在 Codex 任务忙碌时排队,并在任务空闲后启动普通轮次。仅在 Claude→Codex 方向,正文以精确 `STEER:` 开头的消息可以在 App Server 的下一个工具调用边界进入当前轮次;若该边界不可用,消息会回到普通队列。
|
|
120
|
+
|
|
121
|
+
每条已结算的消息都会产生回执。`delivered` 表示观测到了终端提供方证据——朝向 Codex,意味着 App Server 接受了该轮次;朝向 Claude,意味着消息已释放到会话的原生队列。两者都不意味着模型已读取或执行。`unconfirmed` 和 `ambiguous` 表示证据缺失;它们是终态,从不自动重试。完整语义详见[投递](docs/DELIVERY.zh-CN.md)。
|
|
122
|
+
|
|
123
|
+
## 核心术语
|
|
124
|
+
|
|
125
|
+
四个 Embassy 术语对应真实功能:
|
|
126
|
+
|
|
127
|
+
- **注册与配对**构成权限模型:Codex 任务通过显式注册发布,每个配对是一条显式的 Claude↔Codex 边——只有配对的两端可以交换消息,且多条边可以并存。没有边意味着 `SENDER_NOT_PAIRED`;一切都是显式的。
|
|
128
|
+
- **账簿**是投递记录:每条已结算消息的回执,以及一个仅包含元数据的仪表盘。
|
|
129
|
+
- **信袋**是传输通道:有界的消息体,在 Embassy 内部是临时的,从不被持久化。
|
|
130
|
+
- **领事馆**是路线图:将同一模型通过仅限 attach 的 SSH 扩展到远程主机上的 Codex 任务——已完成设计,但在 v1 中有意禁用。
|
|
131
|
+
|
|
132
|
+
## 面向代理
|
|
133
|
+
|
|
134
|
+
Embassy 的操作者本身往往就是代理:`register-codex` 在 Codex 任务内部运行,而 Claude 端完全通过原生工具驱动。仓库附带 [`skills/embassy-peer/SKILL.md`](skills/embassy-peer/SKILL.md)——请将你的代理指向该技能,而非向它复述本 README。
|
|
135
|
+
|
|
136
|
+
## 命令一览
|
|
137
|
+
|
|
138
|
+
| 命令 | 执行者 | 用途 |
|
|
139
|
+
| --- | --- | --- |
|
|
140
|
+
| `serve` | 操作员 | 启动前台代理和仪表盘 |
|
|
141
|
+
| `health` / `status` | 操作员 | 检查存活状态并查看脱敏快照 |
|
|
142
|
+
| `refresh-dashboard` | 操作员 | 重新生成两个静态仪表盘文件 |
|
|
143
|
+
| `dashboard --live [--lang en\|zh-CN]` | 操作员 | 启动带有限路由同意操作的实时仪表盘组件;需要 `embassy serve` 正在运行 |
|
|
144
|
+
| `delivery-status` | 任一提供方 | 使用 `embassy delivery-status --token dlv_<token>` 读取单条投递跟踪器 |
|
|
145
|
+
| `wait-delivery` | 任一提供方 | 等待该跟踪器结算,直至投递截止时间 |
|
|
146
|
+
| `register-codex` / `unregister-codex` | Codex 任务 | 通告或注销该任务;例如,`embassy register-codex --alias codex-successor@this-mac --succeeds codex-reviewer@this-mac` 会将注册转交给另一个任务 |
|
|
147
|
+
| `pair` / `unpair` | 操作员 | 显式指定两端来添加或移除一条 Claude↔Codex 边:`embassy pair --claude advisor@this-mac --codex codex-reviewer@this-mac` |
|
|
148
|
+
| `select-claude` / `unselect-claude` | 操作员 | `pair`/`unpair` 的单任务简写:仅在 Codex 端无歧义(继承标识或唯一已注册任务)时解析,否则以关闭状态失败 |
|
|
149
|
+
| `send-to-claude` | 已注册的 Codex 任务 | 向已配对的 Claude 会话发送一条有界消息 |
|
|
150
|
+
| `send-to-codex` | Claude 会话 | 使用继承的原生回复标识发送一条有界消息 |
|
|
151
|
+
| `reply` | 任一提供方 | 通过公开令牌继续一个活跃对话 |
|
|
152
|
+
|
|
153
|
+
## 一分钟了解安全性
|
|
154
|
+
|
|
155
|
+
- **仅限本地套接字。** `embassy serve` 仅监听私有 Unix 域套接字,不发起任何提供商 API 调用。可选启用的 `embassy dashboard --live` 组件是一个独立进程,也是 Embassy 能创建的唯一监听器,绑定到 `127.0.0.1` 上的临时端口。
|
|
156
|
+
- **同 UID 隔离,而非身份认证。** 调用者身份继承自本地进程环境。路由所有权和生成号检查能减少误操作,但不是对已以你的 OS 用户身份运行的代码的防御。
|
|
157
|
+
- **原生权限保持原生。** Embassy 不发送任何 Codex 审批或沙盒覆盖,也不应答任何审批请求。`crossSessionInbound` 仍是 Claude 自身的控制机制;Embassy 无法覆盖它。
|
|
158
|
+
- **消息体从不持久化。** 消息体、提示词、回复和原始提供方帧仅存在于内存中。仅含元数据的仪表盘文件为 mode 0600,不含 JavaScript。
|
|
159
|
+
|
|
160
|
+
完整的安全边界和漏洞报告流程请参见 [SECURITY.md](SECURITY.md)。
|
|
161
|
+
|
|
162
|
+
## Embassy 不是什么
|
|
163
|
+
|
|
164
|
+
- **不是编排器。** 它不生成代理,也不管理它们的工作。它为每条路由消息启动一个轮次,并在任务空闲时排空队列。
|
|
165
|
+
- **不是托管服务。** 面向个人的、同机同账户软件。
|
|
166
|
+
- **不是权限绕过——但它是一条新路径。** 两个代理都不会获得它原本没有的工具,Embassy 也不授予、放宽或应答任何权限。然而,它确实连接了两个此前无法交换文本的产品。这条路径就是产品本身;请以对待任何新输入通道应有的审慎来看待它。
|
|
167
|
+
- **不是官方产品。** 与 Anthropic 或 OpenAI 没有任何关联或背书关系。
|
|
168
|
+
|
|
169
|
+
## 文档索引
|
|
170
|
+
|
|
171
|
+
| 文档 | 涵盖内容 |
|
|
172
|
+
| --- | --- |
|
|
173
|
+
| [架构](docs/GATEWAY-ARCHITECTURE.md) | 完整设计:拓扑、适配器、控制平面、威胁模型、分级授权阶梯 |
|
|
174
|
+
| [投递](docs/DELIVERY.zh-CN.md) | 投递语义、令牌、结算状态与重试规则 |
|
|
175
|
+
| [配置](docs/CONFIGURATION.zh-CN.md) | 环境变量、兼容性约定与寻址规则 |
|
|
176
|
+
| [仪表盘](docs/DASHBOARD.zh-CN.md) | 静态与实时仪表盘设置、安全模型与变更操作 |
|
|
177
|
+
| [迁移](docs/MIGRATION.zh-CN.md) | 从原型网关迁移 |
|
|
178
|
+
| [安全策略](SECURITY.md) | 如何报告漏洞,以及详细的安全边界 |
|
|
179
|
+
| [贡献指南](CONTRIBUTING.md) | 变更的归属位置,以及如何运行确定性测试套件 |
|
|
180
|
+
| [变更日志](CHANGELOG.md) | 每个版本包含的内容 |
|
|
181
|
+
| [代理技能](skills/embassy-peer/SKILL.md) | 代理操作 Embassy 所遵循的工作流 |
|
|
182
|
+
|
|
183
|
+
## 许可证
|
|
184
|
+
|
|
185
|
+
[MIT](LICENSE)
|