nexus-relay 1.6.0__tar.gz

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.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Julien Piron
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.
@@ -0,0 +1,309 @@
1
+ Metadata-Version: 2.4
2
+ Name: nexus-relay
3
+ Version: 1.6.0
4
+ Summary: Shared room for Claude, Codex and Antigravity on one Windows PC: local MCP daemon, each agent woken in its own app (experimental)
5
+ Keywords: mcp,claude,codex,antigravity,multi-agent,windows
6
+ Author: Julien Piron
7
+ License-Expression: MIT
8
+ License-File: LICENSE
9
+ Classifier: Development Status :: 3 - Alpha
10
+ Classifier: Environment :: Win32 (MS Windows)
11
+ Classifier: Operating System :: Microsoft :: Windows
12
+ Classifier: Programming Language :: Python :: 3.14
13
+ Classifier: Topic :: Software Development
14
+ Requires-Dist: mcp>=2.3.0
15
+ Requires-Dist: websocket-client>=1.8.0
16
+ Requires-Python: >=3.14
17
+ Project-URL: Homepage, https://github.com/pironjulien/NexusRelay
18
+ Project-URL: Repository, https://github.com/pironjulien/NexusRelay
19
+ Project-URL: Changelog, https://github.com/pironjulien/NexusRelay/blob/main/CHANGELOG.md
20
+ Project-URL: Issues, https://github.com/pironjulien/NexusRelay/issues
21
+ Description-Content-Type: text/markdown
22
+
23
+ # Nexus Relay
24
+
25
+ <!-- mcp-name: io.github.pironjulien/nexus-relay -->
26
+
27
+ <img src="https://raw.githubusercontent.com/pironjulien/NexusRelay/main/plugins/nexus-relay/logo.png" alt="Nexus Relay icon" width="96">
28
+
29
+ [![PyPI](https://img.shields.io/pypi/v/nexus-relay.svg)](https://pypi.org/project/nexus-relay/)
30
+ [![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](https://github.com/pironjulien/NexusRelay/blob/main/LICENSE)
31
+ ![Python 3.14](https://img.shields.io/badge/python-3.14-blue.svg)
32
+ ![Windows only](https://img.shields.io/badge/platform-Windows-lightgrey.svg)
33
+ ![Status: experimental](https://img.shields.io/badge/status-experimental-orange.svg)
34
+
35
+ **A shared room for Claude, Codex and Antigravity on one Windows PC.** Claude (Claude Code) hands reviews, second
36
+ opinions and tasks to Codex and Antigravity, and gets their answers back, without you copy-pasting between apps. Each
37
+ agent keeps working in its own desktop app, with its own tools, and the relay never takes your mouse, keyboard or
38
+ clipboard.
39
+
40
+ > [!WARNING]
41
+ > **Experimental, Windows only.** Waking Codex drives the Codex desktop app through its local debugging port, and
42
+ > waking Antigravity goes through its sidecar API. Both depend on how those apps look and behave today: an app update
43
+ > can break a wake until the relay's interface maps are refreshed (`survey`). Use at your own risk.
44
+
45
+ ## How it works
46
+
47
+ ```mermaid
48
+ flowchart LR
49
+ C["Claude Code<br/>(host)"] -- "send / wait_reply" --> D["nexus-relay daemon<br/>127.0.0.1:16181"]
50
+ D -- "one immutable JSON<br/>per message" --> B[("~/.nexus/relay")]
51
+ D -- "debug port 9223:<br/>new chat in project<br/>'Nexus Relay'" --> X["Codex app"]
52
+ D -- "sidecar + agentapi" --> A["Antigravity"]
53
+ X -- "read / reply" --> D
54
+ A -- "read / reply" --> D
55
+ ```
56
+
57
+ 1. Claude calls `send(to, text, topic)`. The message is written to the local room, one file per message.
58
+ 2. The daemon rings the recipient with a short note that only cites the message id, never its content: Codex gets a
59
+ new chat in its "Nexus Relay" project, Antigravity gets it through the relay's sidecar.
60
+ 3. The recipient calls `read(id)` and answers with `reply(id, text)`. Claude waits with `wait_reply(id)`.
61
+ 4. Once the exchange is over and the agent's turn has been finished for 10 s, its conversation is archived (never
62
+ deleted).
63
+
64
+ One agent is the host, Claude by default: only the host opens an exchange, and it is never woken (it waits for the
65
+ answers). The other agents can only reply (or post for information), so agents never trigger each other in a loop.
66
+ Without Claude Code, the installer makes the first agent found the host (Codex, then Antigravity); the `host` setting
67
+ changes it.
68
+
69
+ ## Requirements
70
+
71
+ - Windows 10 or 11, no administrator rights ([uv](https://docs.astral.sh/uv/) and Python 3.14 are installed for you).
72
+ - Two of Claude Code, the Codex desktop app and Antigravity (any pair; Claude Code is the host when it is there).
73
+
74
+ ## Quick start
75
+
76
+ 1. Open **PowerShell** and paste:
77
+
78
+ ```powershell
79
+ irm https://raw.githubusercontent.com/pironjulien/NexusRelay/main/get.ps1 | iex
80
+ ```
81
+
82
+ It installs uv if missing, downloads the latest release into `%LOCALAPPDATA%\NexusRelay\app`, creates a local
83
+ token (user variable `NEXUS_MCP_TOKEN`), starts the background daemon (scheduled task "Nexus Relay"), installs the
84
+ Antigravity plugin and sidecar, and declares the server to Claude Code and Codex (the token itself is never written
85
+ in their files). Run it again to update.
86
+ 2. **Restart Claude Code and Codex** (quit them completely). In the Codex app, once: *Add a project*, name
87
+ "Nexus Relay", folder `%USERPROFILE%\.nexus\relay\codex-projet`.
88
+ 3. In Claude Code, ask: *"use Nexus Relay to ask Codex for a second opinion on this file"*. Check both directions with
89
+ `selftest(to="codex")` and `selftest(to="antigravity")`.
90
+
91
+ ### From PyPI (one line, stdio)
92
+
93
+ The same server is on [PyPI](https://pypi.org/project/nexus-relay/) and in the
94
+ [official MCP registry](https://registry.modelcontextprotocol.io/) (`io.github.pironjulien/nexus-relay`). One line
95
+ starts it over stdio for one agent, with no install step:
96
+
97
+ ```powershell
98
+ uvx --python 3.14 nexus-relay
99
+ ```
100
+
101
+ Set `NEXUS_RELAY_AGENT` to the agent the connection speaks for (`claude`, `codex` or `antigravity`). For instance, in
102
+ a client that reads `mcpServers` JSON:
103
+
104
+ ```json
105
+ {
106
+ "mcpServers": {
107
+ "nexus-relay": {
108
+ "command": "uvx",
109
+ "args": ["--python", "3.14", "nexus-relay@latest"],
110
+ "env": { "NEXUS_RELAY_AGENT": "claude" }
111
+ }
112
+ }
113
+ }
114
+ ```
115
+
116
+ It shares the same room (`~\.nexus\relay`) as the daemon. The one-line installer above remains the complete setup:
117
+ background daemon, Antigravity plugin and sidecar, Codex project, token and updates. Under OneDrive, add
118
+ `--link-mode copy` to `uvx` (uv's cache cannot hard-link there).
119
+
120
+ ## Manual install
121
+
122
+ 1. **Settings** (optional file, outside the repository) — `~\.nexus\nexus-relay\settings.json`:
123
+
124
+ ```json
125
+ {
126
+ "token_file": "C:\\path\\to\\nexus-mcp-token.txt",
127
+ "vaults": ["C:\\path\\to\\secrets"],
128
+ "codex_router": "http://127.0.0.1:2455/health/ready",
129
+ "codex_router_start": ["\"C:\\path\\to\\router.exe\" --background"]
130
+ }
131
+ ```
132
+
133
+ `token_file` is needed (or pass `-TokenFile`, set `NEXUS_MCP_TOKEN_FILE`, or let `install.ps1 -Register` create a
134
+ local one).
135
+
136
+ 2. **Install** — creates the virtual environment, registers the daemon, installs the Antigravity plugin and sidecar,
137
+ and runs the tests:
138
+
139
+ ```powershell
140
+ pwsh -NoProfile -File install.ps1
141
+ ```
142
+
143
+ The daemon runs in the background under a small supervisor (`python -m nexus_relay.daemon`), started at logon by
144
+ the scheduled task "Nexus Relay" that `install.ps1` creates and starts. It reads
145
+ `~\.nexus\daemons\specs\nexus-relay.json`, restarts the daemon when it stops, and logs to
146
+ `~\.nexus\nexus-relay\daemon.log`.
147
+
148
+ 3. **Connect the agents** — set the user environment variable `NEXUS_MCP_TOKEN` to the token, then:
149
+
150
+ <details>
151
+ <summary>Claude Code</summary>
152
+
153
+ The `claude/` folder is a Claude Code plugin (MCP server + skill). Its `.mcp.json`:
154
+
155
+ ```json
156
+ {
157
+ "mcpServers": {
158
+ "nexus-relay": {
159
+ "type": "http",
160
+ "url": "http://127.0.0.1:16181/mcp?agent=claude",
161
+ "headers": { "Authorization": "Bearer ${NEXUS_MCP_TOKEN}" }
162
+ }
163
+ }
164
+ }
165
+ ```
166
+ </details>
167
+
168
+ <details>
169
+ <summary>Codex</summary>
170
+
171
+ Use the ready-made plugin in [`codex/`](codex) (MCP server and the `nexus-relay` skill; the bearer token is read
172
+ from the user variable `NEXUS_MCP_TOKEN`), for instance by adding this repository as a plugin marketplace with
173
+ `codex/` as its root. Or add a personal plugin whose `.mcp.json` points to the daemon:
174
+
175
+ ```json
176
+ {
177
+ "mcpServers": {
178
+ "nexus-relay": {
179
+ "url": "http://127.0.0.1:16181/mcp?agent=codex",
180
+ "bearer_token_env_var": "NEXUS_MCP_TOKEN"
181
+ }
182
+ }
183
+ }
184
+ ```
185
+
186
+ Then, once, in the Codex app: *Add a project*, name "Nexus Relay", folder `~\.nexus\relay\codex-projet` (created by
187
+ `install.ps1`). The Codex app must be started with its debugging port (the relay relaunches it with
188
+ `--remote-debugging-port=9223` when Codex is idle and you are not using it).
189
+ </details>
190
+
191
+ <details>
192
+ <summary>Antigravity</summary>
193
+
194
+ Nothing to do: `install.ps1` installs the `nexus-relay` plugin (MCP server, skill and sidecar) under
195
+ `~\.gemini\config\plugins` and the "Nexus Relay" project.
196
+ </details>
197
+
198
+ Then, in Claude Code: *"use Nexus Relay to ask Codex for a review of this diff"*. Check both directions end to end
199
+ with `selftest(to="codex")` and `selftest(to="antigravity")`.
200
+
201
+ ## Tools
202
+
203
+ | Tool | What it does |
204
+ |---|---|
205
+ | `send` | Post a message to `codex` or `antigravity` in a topic (attachments, optional deadline) |
206
+ | `wait_reply` | Wait for the answer (600 s max per call) |
207
+ | `reply` | Answer a message, with its outcome: done, refused, failed |
208
+ | `progress` | Tell the host you are working on it (wakes nobody) |
209
+ | `inbox`, `read` | Unread messages; read one |
210
+ | `track` | Where a message is: posted, rings, read, in progress, answered, late |
211
+ | `close` | Close a topic (its conversations are archived) |
212
+ | `reserve`, `release`, `reservations` | Reserve files before editing them, release them, list who holds what |
213
+ | `file_reservation_paths`, `release_file_reservations` | The same reservations under the [mcp_agent_mail](https://github.com/Dicklesworthstone/mcp_agent_mail) names and parameters |
214
+ | `search`, `summary` | Full-text search of the whole room history (SQLite FTS5 index, accent and case insensitive); summary of a topic |
215
+ | `status` | Unread counts, last wakes, bell threads, Codex port, Antigravity sidecar, quotas |
216
+ | `selftest` | Interface landmarks of both apps; with `to`, a real wake round trip |
217
+ | `where`, `survey` | Where a button or menu is in Codex or Antigravity; refresh an app's interface map |
218
+
219
+ Every tool carries MCP annotations (`readOnlyHint`, `destructiveHint`, …).
220
+
221
+ ## Settings
222
+
223
+ Read from `~\.nexus\nexus-relay\settings.json` (this PC), then from `settings.local.json` at the root of the
224
+ installed folder (shared by the PCs of a synced install), key by key; values may use environment variables
225
+ (`%LOCALAPPDATA%`, `%USERPROFILE%`...), and a list keeps the first existing `token_file`. Variables already set in
226
+ the daemon's environment win.
227
+
228
+ | Variable (daemon) | `settings.json` key | Default | Purpose |
229
+ |---|---|---|---|
230
+ | `NEXUS_MCP_TOKEN` / `NEXUS_MCP_TOKEN_FILE` | `token_file` | — (required) | Bearer token of the local daemon |
231
+ | `NEXUS_RELAY_VAULTS` | `vaults` | none | Folders whose files are never attached to a message |
232
+ | `NEXUS_RELAY_CODEX_ROUTER` | `codex_router` | none | Health URL of a local model router in front of Codex; Codex is not woken while it is down |
233
+ | `NEXUS_RELAY_CODEX_ROUTER_START` | `codex_router_start` | none | Commands that start that router, tried in order (`;`-separated) |
234
+ | `NEXUS_RELAY_HOME` | — | `~\.nexus\relay` | Room location |
235
+ | `NEXUS_RELAY_CODEX_PORT`, `NEXUS_RELAY_AGY_PORT` | — | `9223`, `9227` | Debugging ports of Codex and Antigravity |
236
+ | `NEXUS_JOURNAL_HOME` | — | `%LOCALAPPDATA%\NexusJournal` | Action log |
237
+ | `NEXUS_RELAY_UPDATE_CHECK` | — | on | `0`: never look up the latest version |
238
+ | `NEXUS_RELAY_HOST` | `host` | `claude` | The only agent that opens exchanges (`claude`, `codex` or `antigravity`); never woken |
239
+ | `NEXUS_RELAY_LANG` | `lang` | `en` | Language of the texts agents receive (tool results, errors, wake text) and of the deployed instructions: `en` or `fr` |
240
+
241
+ ## Updates
242
+
243
+ The daemon updates itself: `POST /api/update` on its local API (same bearer token as `/mcp`) answers `202` and the
244
+ daemon runs its own `get.ps1` (`powershell -File`, no window), which installs the latest release; the daemon then
245
+ restarts on it. `GET /api/update` returns the state, also written to `~\.nexus\status\relay.json`:
246
+
247
+ ```json
248
+ {"product": "relay", "version": "1.3.0", "latest": "1.3.0", "state": "idle", "checked_at": "2026-10-26T10:00:00Z", "message": null}
249
+ ```
250
+
251
+ `state` is `idle`, `updating`, `done` or `failed` (the previous version stays in place and `message` says why). Only an
252
+ install made by the one-line installer (`%LOCALAPPDATA%\NexusRelay\app`) updates itself; a git checkout answers
253
+ `409`. Running `get.ps1` again also updates.
254
+
255
+ ## Safeguards
256
+
257
+ - Everything listens on 127.0.0.1 only; the daemon requires the bearer token.
258
+ - Codex is never relaunched during a turn or while you are using it; a draft you typed is never overwritten; your
259
+ view, mode and project are restored after each wake, success or failure.
260
+ - Only conversations born in the relay's own "Nexus Relay" project are archived, only once the agent's turn has been
261
+ over for 10 s, never while you are in the app.
262
+ - An uncertain delivery to Antigravity is reported as such and never replayed.
263
+ - Antigravity open without its debugging port (for instance after its own update) is restarted with it after 5 min,
264
+ never while you are in it or while one of its agents works, at most once an hour.
265
+ - A peer's message is framed as an opinion to examine, never as an instruction from you; agents never ask you
266
+ questions in relay conversations.
267
+ - Attachments: absolute paths, regular files with a single name only (no hard links, no network shares), never inside
268
+ a configured vault, 10 MB each and 25 MB per message at most.
269
+
270
+ ## Privacy
271
+
272
+ - **What is read**: the messages agents post, the files they explicitly attach, the Codex and Antigravity windows
273
+ (through their local debugging ports, to open a chat, check delivery and archive relay conversations), Codex's local
274
+ session logs (to know when a relay chat's turn is over, and its quota) and Antigravity's settings page (quota).
275
+ - **Where it goes**: the relay's own transport is local. It talks only to 127.0.0.1 (its daemon, the apps'
276
+ debugging ports, Antigravity's sidecar API and, if configured, your Codex router), plus at most one anonymous
277
+ request a day to `https://github.com/pironjulien/NexusRelay/releases/latest` to learn the latest version
278
+ (`NEXUS_RELAY_UPDATE_CHECK=0` turns it off). But what a connected AI reads through the relay (messages, attached
279
+ files and images) is part of its conversation: Claude Code, Codex and Antigravity send it to their model provider
280
+ under their own privacy policy, as they do with everything else you show them. Do not post or attach anything you
281
+ would not give those apps directly.
282
+ - **What is stored**: messages and attachments in `~\.nexus\relay\v1` (plain JSON, readable by your user account),
283
+ a search index of those messages in `~\.nexus\relay\v1\index` (SQLite, rebuilt from the messages if deleted),
284
+ interface maps of both apps in `~\.nexus\relay\v1\cartes` (element roles and visible labels, which can include
285
+ conversation titles shown on screen), and one line per action in `%LOCALAPPDATA%\NexusJournal\relay` (never a message's text).
286
+ - **How to remove everything**: delete the scheduled task "Nexus Relay" and stop its `pythonw` processes, then
287
+ delete `~\.nexus\relay`, `~\.nexus\nexus-relay`,
288
+ `~\.nexus\daemons\specs\nexus-relay.json`, `%LOCALAPPDATA%\NexusJournal\relay`, the `nexus-relay` plugin in
289
+ `~\.gemini\config\plugins` and its `sidecars` entry in `~\.gemini\config\config.json`.
290
+
291
+ ## Limits
292
+
293
+ - Windows only; tested with Codex desktop 26.1021 and Antigravity 2.26.
294
+ - Interface automation is fragile by nature: after an app update, run `survey(app)` and `selftest`.
295
+ - The host is never woken: it waits for answers with `wait_reply`. Claude Code cannot be woken at all, so with another
296
+ host, a message to Claude waits in its inbox.
297
+
298
+ ## Development
299
+
300
+ ```powershell
301
+ pwsh -NoProfile -File test.ps1 # ruff, pyright, pytest — offline, never touches the real apps
302
+ ```
303
+
304
+ A copy of the repository (clone, worktree) gets its own virtual environment, so testing it never switches the
305
+ installed relay to that copy.
306
+
307
+ ## License
308
+
309
+ [MIT](https://github.com/pironjulien/NexusRelay/blob/main/LICENSE)
@@ -0,0 +1,287 @@
1
+ # Nexus Relay
2
+
3
+ <!-- mcp-name: io.github.pironjulien/nexus-relay -->
4
+
5
+ <img src="https://raw.githubusercontent.com/pironjulien/NexusRelay/main/plugins/nexus-relay/logo.png" alt="Nexus Relay icon" width="96">
6
+
7
+ [![PyPI](https://img.shields.io/pypi/v/nexus-relay.svg)](https://pypi.org/project/nexus-relay/)
8
+ [![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](https://github.com/pironjulien/NexusRelay/blob/main/LICENSE)
9
+ ![Python 3.14](https://img.shields.io/badge/python-3.14-blue.svg)
10
+ ![Windows only](https://img.shields.io/badge/platform-Windows-lightgrey.svg)
11
+ ![Status: experimental](https://img.shields.io/badge/status-experimental-orange.svg)
12
+
13
+ **A shared room for Claude, Codex and Antigravity on one Windows PC.** Claude (Claude Code) hands reviews, second
14
+ opinions and tasks to Codex and Antigravity, and gets their answers back, without you copy-pasting between apps. Each
15
+ agent keeps working in its own desktop app, with its own tools, and the relay never takes your mouse, keyboard or
16
+ clipboard.
17
+
18
+ > [!WARNING]
19
+ > **Experimental, Windows only.** Waking Codex drives the Codex desktop app through its local debugging port, and
20
+ > waking Antigravity goes through its sidecar API. Both depend on how those apps look and behave today: an app update
21
+ > can break a wake until the relay's interface maps are refreshed (`survey`). Use at your own risk.
22
+
23
+ ## How it works
24
+
25
+ ```mermaid
26
+ flowchart LR
27
+ C["Claude Code<br/>(host)"] -- "send / wait_reply" --> D["nexus-relay daemon<br/>127.0.0.1:16181"]
28
+ D -- "one immutable JSON<br/>per message" --> B[("~/.nexus/relay")]
29
+ D -- "debug port 9223:<br/>new chat in project<br/>'Nexus Relay'" --> X["Codex app"]
30
+ D -- "sidecar + agentapi" --> A["Antigravity"]
31
+ X -- "read / reply" --> D
32
+ A -- "read / reply" --> D
33
+ ```
34
+
35
+ 1. Claude calls `send(to, text, topic)`. The message is written to the local room, one file per message.
36
+ 2. The daemon rings the recipient with a short note that only cites the message id, never its content: Codex gets a
37
+ new chat in its "Nexus Relay" project, Antigravity gets it through the relay's sidecar.
38
+ 3. The recipient calls `read(id)` and answers with `reply(id, text)`. Claude waits with `wait_reply(id)`.
39
+ 4. Once the exchange is over and the agent's turn has been finished for 10 s, its conversation is archived (never
40
+ deleted).
41
+
42
+ One agent is the host, Claude by default: only the host opens an exchange, and it is never woken (it waits for the
43
+ answers). The other agents can only reply (or post for information), so agents never trigger each other in a loop.
44
+ Without Claude Code, the installer makes the first agent found the host (Codex, then Antigravity); the `host` setting
45
+ changes it.
46
+
47
+ ## Requirements
48
+
49
+ - Windows 10 or 11, no administrator rights ([uv](https://docs.astral.sh/uv/) and Python 3.14 are installed for you).
50
+ - Two of Claude Code, the Codex desktop app and Antigravity (any pair; Claude Code is the host when it is there).
51
+
52
+ ## Quick start
53
+
54
+ 1. Open **PowerShell** and paste:
55
+
56
+ ```powershell
57
+ irm https://raw.githubusercontent.com/pironjulien/NexusRelay/main/get.ps1 | iex
58
+ ```
59
+
60
+ It installs uv if missing, downloads the latest release into `%LOCALAPPDATA%\NexusRelay\app`, creates a local
61
+ token (user variable `NEXUS_MCP_TOKEN`), starts the background daemon (scheduled task "Nexus Relay"), installs the
62
+ Antigravity plugin and sidecar, and declares the server to Claude Code and Codex (the token itself is never written
63
+ in their files). Run it again to update.
64
+ 2. **Restart Claude Code and Codex** (quit them completely). In the Codex app, once: *Add a project*, name
65
+ "Nexus Relay", folder `%USERPROFILE%\.nexus\relay\codex-projet`.
66
+ 3. In Claude Code, ask: *"use Nexus Relay to ask Codex for a second opinion on this file"*. Check both directions with
67
+ `selftest(to="codex")` and `selftest(to="antigravity")`.
68
+
69
+ ### From PyPI (one line, stdio)
70
+
71
+ The same server is on [PyPI](https://pypi.org/project/nexus-relay/) and in the
72
+ [official MCP registry](https://registry.modelcontextprotocol.io/) (`io.github.pironjulien/nexus-relay`). One line
73
+ starts it over stdio for one agent, with no install step:
74
+
75
+ ```powershell
76
+ uvx --python 3.14 nexus-relay
77
+ ```
78
+
79
+ Set `NEXUS_RELAY_AGENT` to the agent the connection speaks for (`claude`, `codex` or `antigravity`). For instance, in
80
+ a client that reads `mcpServers` JSON:
81
+
82
+ ```json
83
+ {
84
+ "mcpServers": {
85
+ "nexus-relay": {
86
+ "command": "uvx",
87
+ "args": ["--python", "3.14", "nexus-relay@latest"],
88
+ "env": { "NEXUS_RELAY_AGENT": "claude" }
89
+ }
90
+ }
91
+ }
92
+ ```
93
+
94
+ It shares the same room (`~\.nexus\relay`) as the daemon. The one-line installer above remains the complete setup:
95
+ background daemon, Antigravity plugin and sidecar, Codex project, token and updates. Under OneDrive, add
96
+ `--link-mode copy` to `uvx` (uv's cache cannot hard-link there).
97
+
98
+ ## Manual install
99
+
100
+ 1. **Settings** (optional file, outside the repository) — `~\.nexus\nexus-relay\settings.json`:
101
+
102
+ ```json
103
+ {
104
+ "token_file": "C:\\path\\to\\nexus-mcp-token.txt",
105
+ "vaults": ["C:\\path\\to\\secrets"],
106
+ "codex_router": "http://127.0.0.1:2455/health/ready",
107
+ "codex_router_start": ["\"C:\\path\\to\\router.exe\" --background"]
108
+ }
109
+ ```
110
+
111
+ `token_file` is needed (or pass `-TokenFile`, set `NEXUS_MCP_TOKEN_FILE`, or let `install.ps1 -Register` create a
112
+ local one).
113
+
114
+ 2. **Install** — creates the virtual environment, registers the daemon, installs the Antigravity plugin and sidecar,
115
+ and runs the tests:
116
+
117
+ ```powershell
118
+ pwsh -NoProfile -File install.ps1
119
+ ```
120
+
121
+ The daemon runs in the background under a small supervisor (`python -m nexus_relay.daemon`), started at logon by
122
+ the scheduled task "Nexus Relay" that `install.ps1` creates and starts. It reads
123
+ `~\.nexus\daemons\specs\nexus-relay.json`, restarts the daemon when it stops, and logs to
124
+ `~\.nexus\nexus-relay\daemon.log`.
125
+
126
+ 3. **Connect the agents** — set the user environment variable `NEXUS_MCP_TOKEN` to the token, then:
127
+
128
+ <details>
129
+ <summary>Claude Code</summary>
130
+
131
+ The `claude/` folder is a Claude Code plugin (MCP server + skill). Its `.mcp.json`:
132
+
133
+ ```json
134
+ {
135
+ "mcpServers": {
136
+ "nexus-relay": {
137
+ "type": "http",
138
+ "url": "http://127.0.0.1:16181/mcp?agent=claude",
139
+ "headers": { "Authorization": "Bearer ${NEXUS_MCP_TOKEN}" }
140
+ }
141
+ }
142
+ }
143
+ ```
144
+ </details>
145
+
146
+ <details>
147
+ <summary>Codex</summary>
148
+
149
+ Use the ready-made plugin in [`codex/`](codex) (MCP server and the `nexus-relay` skill; the bearer token is read
150
+ from the user variable `NEXUS_MCP_TOKEN`), for instance by adding this repository as a plugin marketplace with
151
+ `codex/` as its root. Or add a personal plugin whose `.mcp.json` points to the daemon:
152
+
153
+ ```json
154
+ {
155
+ "mcpServers": {
156
+ "nexus-relay": {
157
+ "url": "http://127.0.0.1:16181/mcp?agent=codex",
158
+ "bearer_token_env_var": "NEXUS_MCP_TOKEN"
159
+ }
160
+ }
161
+ }
162
+ ```
163
+
164
+ Then, once, in the Codex app: *Add a project*, name "Nexus Relay", folder `~\.nexus\relay\codex-projet` (created by
165
+ `install.ps1`). The Codex app must be started with its debugging port (the relay relaunches it with
166
+ `--remote-debugging-port=9223` when Codex is idle and you are not using it).
167
+ </details>
168
+
169
+ <details>
170
+ <summary>Antigravity</summary>
171
+
172
+ Nothing to do: `install.ps1` installs the `nexus-relay` plugin (MCP server, skill and sidecar) under
173
+ `~\.gemini\config\plugins` and the "Nexus Relay" project.
174
+ </details>
175
+
176
+ Then, in Claude Code: *"use Nexus Relay to ask Codex for a review of this diff"*. Check both directions end to end
177
+ with `selftest(to="codex")` and `selftest(to="antigravity")`.
178
+
179
+ ## Tools
180
+
181
+ | Tool | What it does |
182
+ |---|---|
183
+ | `send` | Post a message to `codex` or `antigravity` in a topic (attachments, optional deadline) |
184
+ | `wait_reply` | Wait for the answer (600 s max per call) |
185
+ | `reply` | Answer a message, with its outcome: done, refused, failed |
186
+ | `progress` | Tell the host you are working on it (wakes nobody) |
187
+ | `inbox`, `read` | Unread messages; read one |
188
+ | `track` | Where a message is: posted, rings, read, in progress, answered, late |
189
+ | `close` | Close a topic (its conversations are archived) |
190
+ | `reserve`, `release`, `reservations` | Reserve files before editing them, release them, list who holds what |
191
+ | `file_reservation_paths`, `release_file_reservations` | The same reservations under the [mcp_agent_mail](https://github.com/Dicklesworthstone/mcp_agent_mail) names and parameters |
192
+ | `search`, `summary` | Full-text search of the whole room history (SQLite FTS5 index, accent and case insensitive); summary of a topic |
193
+ | `status` | Unread counts, last wakes, bell threads, Codex port, Antigravity sidecar, quotas |
194
+ | `selftest` | Interface landmarks of both apps; with `to`, a real wake round trip |
195
+ | `where`, `survey` | Where a button or menu is in Codex or Antigravity; refresh an app's interface map |
196
+
197
+ Every tool carries MCP annotations (`readOnlyHint`, `destructiveHint`, …).
198
+
199
+ ## Settings
200
+
201
+ Read from `~\.nexus\nexus-relay\settings.json` (this PC), then from `settings.local.json` at the root of the
202
+ installed folder (shared by the PCs of a synced install), key by key; values may use environment variables
203
+ (`%LOCALAPPDATA%`, `%USERPROFILE%`...), and a list keeps the first existing `token_file`. Variables already set in
204
+ the daemon's environment win.
205
+
206
+ | Variable (daemon) | `settings.json` key | Default | Purpose |
207
+ |---|---|---|---|
208
+ | `NEXUS_MCP_TOKEN` / `NEXUS_MCP_TOKEN_FILE` | `token_file` | — (required) | Bearer token of the local daemon |
209
+ | `NEXUS_RELAY_VAULTS` | `vaults` | none | Folders whose files are never attached to a message |
210
+ | `NEXUS_RELAY_CODEX_ROUTER` | `codex_router` | none | Health URL of a local model router in front of Codex; Codex is not woken while it is down |
211
+ | `NEXUS_RELAY_CODEX_ROUTER_START` | `codex_router_start` | none | Commands that start that router, tried in order (`;`-separated) |
212
+ | `NEXUS_RELAY_HOME` | — | `~\.nexus\relay` | Room location |
213
+ | `NEXUS_RELAY_CODEX_PORT`, `NEXUS_RELAY_AGY_PORT` | — | `9223`, `9227` | Debugging ports of Codex and Antigravity |
214
+ | `NEXUS_JOURNAL_HOME` | — | `%LOCALAPPDATA%\NexusJournal` | Action log |
215
+ | `NEXUS_RELAY_UPDATE_CHECK` | — | on | `0`: never look up the latest version |
216
+ | `NEXUS_RELAY_HOST` | `host` | `claude` | The only agent that opens exchanges (`claude`, `codex` or `antigravity`); never woken |
217
+ | `NEXUS_RELAY_LANG` | `lang` | `en` | Language of the texts agents receive (tool results, errors, wake text) and of the deployed instructions: `en` or `fr` |
218
+
219
+ ## Updates
220
+
221
+ The daemon updates itself: `POST /api/update` on its local API (same bearer token as `/mcp`) answers `202` and the
222
+ daemon runs its own `get.ps1` (`powershell -File`, no window), which installs the latest release; the daemon then
223
+ restarts on it. `GET /api/update` returns the state, also written to `~\.nexus\status\relay.json`:
224
+
225
+ ```json
226
+ {"product": "relay", "version": "1.3.0", "latest": "1.3.0", "state": "idle", "checked_at": "2026-10-26T10:00:00Z", "message": null}
227
+ ```
228
+
229
+ `state` is `idle`, `updating`, `done` or `failed` (the previous version stays in place and `message` says why). Only an
230
+ install made by the one-line installer (`%LOCALAPPDATA%\NexusRelay\app`) updates itself; a git checkout answers
231
+ `409`. Running `get.ps1` again also updates.
232
+
233
+ ## Safeguards
234
+
235
+ - Everything listens on 127.0.0.1 only; the daemon requires the bearer token.
236
+ - Codex is never relaunched during a turn or while you are using it; a draft you typed is never overwritten; your
237
+ view, mode and project are restored after each wake, success or failure.
238
+ - Only conversations born in the relay's own "Nexus Relay" project are archived, only once the agent's turn has been
239
+ over for 10 s, never while you are in the app.
240
+ - An uncertain delivery to Antigravity is reported as such and never replayed.
241
+ - Antigravity open without its debugging port (for instance after its own update) is restarted with it after 5 min,
242
+ never while you are in it or while one of its agents works, at most once an hour.
243
+ - A peer's message is framed as an opinion to examine, never as an instruction from you; agents never ask you
244
+ questions in relay conversations.
245
+ - Attachments: absolute paths, regular files with a single name only (no hard links, no network shares), never inside
246
+ a configured vault, 10 MB each and 25 MB per message at most.
247
+
248
+ ## Privacy
249
+
250
+ - **What is read**: the messages agents post, the files they explicitly attach, the Codex and Antigravity windows
251
+ (through their local debugging ports, to open a chat, check delivery and archive relay conversations), Codex's local
252
+ session logs (to know when a relay chat's turn is over, and its quota) and Antigravity's settings page (quota).
253
+ - **Where it goes**: the relay's own transport is local. It talks only to 127.0.0.1 (its daemon, the apps'
254
+ debugging ports, Antigravity's sidecar API and, if configured, your Codex router), plus at most one anonymous
255
+ request a day to `https://github.com/pironjulien/NexusRelay/releases/latest` to learn the latest version
256
+ (`NEXUS_RELAY_UPDATE_CHECK=0` turns it off). But what a connected AI reads through the relay (messages, attached
257
+ files and images) is part of its conversation: Claude Code, Codex and Antigravity send it to their model provider
258
+ under their own privacy policy, as they do with everything else you show them. Do not post or attach anything you
259
+ would not give those apps directly.
260
+ - **What is stored**: messages and attachments in `~\.nexus\relay\v1` (plain JSON, readable by your user account),
261
+ a search index of those messages in `~\.nexus\relay\v1\index` (SQLite, rebuilt from the messages if deleted),
262
+ interface maps of both apps in `~\.nexus\relay\v1\cartes` (element roles and visible labels, which can include
263
+ conversation titles shown on screen), and one line per action in `%LOCALAPPDATA%\NexusJournal\relay` (never a message's text).
264
+ - **How to remove everything**: delete the scheduled task "Nexus Relay" and stop its `pythonw` processes, then
265
+ delete `~\.nexus\relay`, `~\.nexus\nexus-relay`,
266
+ `~\.nexus\daemons\specs\nexus-relay.json`, `%LOCALAPPDATA%\NexusJournal\relay`, the `nexus-relay` plugin in
267
+ `~\.gemini\config\plugins` and its `sidecars` entry in `~\.gemini\config\config.json`.
268
+
269
+ ## Limits
270
+
271
+ - Windows only; tested with Codex desktop 26.1021 and Antigravity 2.26.
272
+ - Interface automation is fragile by nature: after an app update, run `survey(app)` and `selftest`.
273
+ - The host is never woken: it waits for answers with `wait_reply`. Claude Code cannot be woken at all, so with another
274
+ host, a message to Claude waits in its inbox.
275
+
276
+ ## Development
277
+
278
+ ```powershell
279
+ pwsh -NoProfile -File test.ps1 # ruff, pyright, pytest — offline, never touches the real apps
280
+ ```
281
+
282
+ A copy of the repository (clone, worktree) gets its own virtual environment, so testing it never switches the
283
+ installed relay to that copy.
284
+
285
+ ## License
286
+
287
+ [MIT](https://github.com/pironjulien/NexusRelay/blob/main/LICENSE)