@mmmbuto/nexuscrew 0.8.36 → 0.8.37
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/README.md
CHANGED
|
@@ -3,578 +3,139 @@
|
|
|
3
3
|
[](https://www.npmjs.com/package/@mmmbuto/nexuscrew)
|
|
4
4
|
[](LICENSE)
|
|
5
5
|
[](https://nodejs.org)
|
|
6
|
-
[](#
|
|
6
|
+
[](#platforms)
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
NexusCrew
|
|
8
|
+
**Your tmux fleet. Everywhere.**
|
|
9
|
+
|
|
10
|
+
NexusCrew turns live tmux sessions, AI CLI workers and connected machines into
|
|
11
|
+
one local-first browser control plane. Your terminals stay real, your tools
|
|
12
|
+
stay yours, and your infrastructure stays under your control.
|
|
11
13
|
|
|
12
14
|
<p align="center">
|
|
13
|
-
<img src="docs/img/fleet-deck-desktop.png" width="960" alt="NexusCrew desktop
|
|
15
|
+
<img src="docs/img/fleet-deck-desktop.png" width="960" alt="NexusCrew desktop deck with multiple live tmux sessions">
|
|
14
16
|
</p>
|
|
15
17
|
|
|
16
|
-
|
|
17
|
-
ownership to tmux. It has no hosted control service, user account system, or public network
|
|
18
|
-
listener.
|
|
19
|
-
|
|
20
|
-
## Overview
|
|
21
|
-
|
|
22
|
-
| Area | What NexusCrew provides |
|
|
23
|
-
|---|---|
|
|
24
|
-
| Terminal | Real PTY attachment to live tmux sessions through WebSocket and xterm.js |
|
|
25
|
-
| Workspaces | Named decks, tiled desktop layouts, mobile session view, saved ordering, pins and per-cell composer state |
|
|
26
|
-
| Fleet | Reusable cells, engines, providers, models, permission policies, prompts, boot state and live working status |
|
|
27
|
-
| Nodes | One-link pairing and owner-qualified routing over supervised OpenSSH connections |
|
|
28
|
-
| Operations | Background service, boot integration, diagnostics, stable npm updates and selective backup |
|
|
29
|
-
| AI integration | A stdio MCP bridge for operator communication, deck discovery and cell-to-cell delivery |
|
|
30
|
-
|
|
31
|
-
The browser is a client, not the session host:
|
|
32
|
-
|
|
33
|
-
```text
|
|
34
|
-
Browser PWA
|
|
35
|
-
│ authenticated HTTP + WebSocket on loopback
|
|
36
|
-
▼
|
|
37
|
-
NexusCrew ── real PTY ── tmux sessions
|
|
38
|
-
│
|
|
39
|
-
├── supervised OpenSSH ── remote NexusCrew nodes
|
|
40
|
-
│
|
|
41
|
-
└── stdio MCP bridge ── Claude Code / Codex / Codex-VL / Pi
|
|
42
|
-
```
|
|
43
|
-
|
|
44
|
-
## Install
|
|
45
|
-
|
|
46
|
-
### Requirements
|
|
18
|
+
## One control plane. Every screen.
|
|
47
19
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
- Linux x64/ARM64, macOS x64/ARM64, or Android ARM64 through Termux
|
|
20
|
+
The desktop deck keeps the whole fleet visible. Open any cell from a phone and
|
|
21
|
+
NexusCrew gives the same live tmux session a touch-first terminal without
|
|
22
|
+
moving the session away from its host.
|
|
52
23
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
Install Node.js, tmux and OpenSSH with your distribution package manager, then:
|
|
59
|
-
|
|
60
|
-
```bash
|
|
61
|
-
npm install -g @mmmbuto/nexuscrew
|
|
62
|
-
nexuscrew
|
|
63
|
-
```
|
|
64
|
-
|
|
65
|
-
### macOS
|
|
66
|
-
|
|
67
|
-
```bash
|
|
68
|
-
brew install node tmux
|
|
69
|
-
npm install -g @mmmbuto/nexuscrew
|
|
70
|
-
nexuscrew
|
|
71
|
-
```
|
|
24
|
+
<p align="center">
|
|
25
|
+
<img src="docs/img/session-mobile.png" width="360" alt="NexusCrew mobile terminal connected to a real tmux session with touch controls">
|
|
26
|
+
<br>
|
|
27
|
+
<sub><strong>Real tmux on mobile.</strong> Terminal keys, dictation and file handoff stay within reach.</sub>
|
|
28
|
+
</p>
|
|
72
29
|
|
|
73
|
-
|
|
30
|
+
## Install in 30 seconds
|
|
74
31
|
|
|
75
32
|
```bash
|
|
76
|
-
pkg update
|
|
77
|
-
pkg install nodejs-lts tmux openssh
|
|
78
33
|
npm install -g @mmmbuto/nexuscrew
|
|
79
34
|
nexuscrew
|
|
80
35
|
```
|
|
81
36
|
|
|
82
|
-
The first run creates
|
|
83
|
-
|
|
84
|
-
and exit.
|
|
85
|
-
|
|
86
|
-
On Android, `nexuscrew doctor` also verifies the Termux execution bridge used by current app
|
|
87
|
-
builds. NexusCrew carries forward only a validated `libtermux-exec` preload from the active
|
|
88
|
-
Termux prefix; arbitrary loader injection remains excluded from Fleet environments.
|
|
37
|
+
The first run creates a loopback-only runtime, starts it in the background and
|
|
38
|
+
opens the authenticated PWA.
|
|
89
39
|
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
40
|
+
| Platform | Prerequisites |
|
|
41
|
+
|---|---|
|
|
42
|
+
| Linux | Node.js 18+, tmux 3.4+, OpenSSH |
|
|
43
|
+
| macOS | `brew install node tmux` |
|
|
44
|
+
| Android / Termux | `pkg install nodejs-lts tmux openssh` |
|
|
95
45
|
|
|
96
|
-
|
|
97
|
-
|
|
46
|
+
NexusCrew ships scriptless PTY prebuilds for Linux x64/ARM64, macOS x64/ARM64
|
|
47
|
+
and Android ARM64. A normal global install does not need a compiler or native
|
|
48
|
+
install-script approval.
|
|
98
49
|
|
|
99
|
-
|
|
50
|
+
[Full installation guide →](docs/INSTALLATION.md)
|
|
100
51
|
|
|
101
|
-
|
|
102
|
-
headless hosts and VPS installations.
|
|
52
|
+
## What NexusCrew gives you
|
|
103
53
|
|
|
104
|
-
|
|
|
105
|
-
|---|---|
|
|
106
|
-
| `nexuscrew` | Start or reuse the background runtime and print a short status |
|
|
107
|
-
| `nexuscrew init [--dry-run] [--port PORT]` | Initialize missing local stores idempotently or preview the operation |
|
|
108
|
-
| `nexuscrew show` | Start when needed and open the authenticated PWA |
|
|
109
|
-
| `nexuscrew show token` | Print the authenticated browser link without opening it |
|
|
110
|
-
| `nexuscrew status` | Show service, port, role and node status |
|
|
111
|
-
| `nexuscrew stop` | Stop NexusCrew and its managed tunnels without stopping tmux sessions |
|
|
112
|
-
| `nexuscrew restart` | Restart NexusCrew and restore autostart node links without stopping tmux |
|
|
113
|
-
| `nexuscrew boot` | Enable startup persistence |
|
|
114
|
-
| `nexuscrew boot off` | Disable startup persistence while leaving the current runtime alive |
|
|
115
|
-
| `nexuscrew doctor` | Check Node, PTY, tmux, SSH, service and platform integration |
|
|
116
|
-
| `nexuscrew nodes list [--json]` | List direct hubs, connected clients and routed read-only peers |
|
|
117
|
-
| `nexuscrew nodes inspect <name\|nodeId>` | Inspect a peer by stable identity |
|
|
118
|
-
| `nexuscrew nodes edit <name\|nodeId> ...` | Change the canonical label or direction-specific connection settings |
|
|
119
|
-
| `nexuscrew nodes up\|down\|connect\|disconnect\|restart\|reconnect <name\|nodeId>` | Manage a direct node link without requiring the PWA |
|
|
120
|
-
| `nexuscrew nodes share <name\|nodeId> on\|off` | Publish or withdraw a direct node from the authorized network |
|
|
121
|
-
| `nexuscrew nodes remove <name\|nodeId> --yes` | Revoke/forget a direct peer after explicit confirmation |
|
|
122
|
-
| `nexuscrew nodes invite --ssh <target>` | Create a one-time pairing link from a headless hub |
|
|
123
|
-
| `nexuscrew nodes pair\|join` | Read a one-time pairing link from stdin and join headlessly |
|
|
124
|
-
| `nexuscrew help` | Show command help |
|
|
125
|
-
| `nexuscrew version` | Show the installed version |
|
|
126
|
-
|
|
127
|
-
Boot integration uses a user systemd service on Linux, a LaunchAgent on macOS, and a
|
|
128
|
-
Termux:Boot script on Android. Termux users must install the Termux:Boot app and open it once;
|
|
129
|
-
the CLI can validate the script but cannot prove Android app activation.
|
|
130
|
-
|
|
131
|
-
Cells marked `boot:true` are started when that platform boot integration runs. This is startup
|
|
132
|
-
persistence, not a watchdog for the tmux server itself: if the entire tmux server disappears
|
|
133
|
-
later, the boot companion is not automatically rerun.
|
|
134
|
-
|
|
135
|
-
## Fleet: cells, engines and providers
|
|
136
|
-
|
|
137
|
-
A **cell** is a reusable worker definition: tmux session name, working directory, engine,
|
|
138
|
-
model, permission policy, optional system prompt, optional Shell command and boot state. Starting
|
|
139
|
-
a stopped cell opens the same launch sheet on desktop and mobile, so the effective settings can
|
|
140
|
-
be reviewed before the process starts.
|
|
141
|
-
|
|
142
|
-
An **engine** describes how a CLI is launched. Clean installations include these base adapters:
|
|
143
|
-
|
|
144
|
-
- Claude Code
|
|
145
|
-
- Codex
|
|
146
|
-
- Codex-VL
|
|
147
|
-
- Pi
|
|
148
|
-
- Agy — Linux and macOS only (auth delegated to Agy's local login; `standard`/`unsafe` permission policies). On Android/Termux use the Shell adapter with a per-cell `agy` command.
|
|
149
|
-
- Shell
|
|
150
|
-
|
|
151
|
-
The provider catalog is scoped to the selected CLI rather than to a machine-specific setup:
|
|
152
|
-
|
|
153
|
-
| CLI | Built-in provider choices |
|
|
54
|
+
| | |
|
|
154
55
|
|---|---|
|
|
155
|
-
|
|
|
156
|
-
|
|
|
157
|
-
|
|
|
158
|
-
|
|
|
159
|
-
|
|
|
160
|
-
|
|
161
|
-
Custom Codex-compatible endpoints use the real Responses wire API; NexusCrew does not silently
|
|
162
|
-
fall back to Chat Completions. Custom argv-based engines are also supported and are launched
|
|
163
|
-
directly without a shell after trust-boundary validation.
|
|
164
|
-
|
|
165
|
-
The Shell engine resolves `$SHELL` or a trusted platform shell when the cell starts; executable
|
|
166
|
-
paths are not stored in Fleet definitions or backups. Leaving its command empty opens an
|
|
167
|
-
interactive login shell. A configured command is passed as one opaque argument through the
|
|
168
|
-
private launch broker, runs once without restart supervision, and then leaves the cell stopped.
|
|
169
|
-
Known POSIX shells use an interactive login invocation (`-lic`) so the user's configured PATH is
|
|
170
|
-
available; custom shells retain the conservative `-lc` contract. Shell does not accept prompts,
|
|
171
|
-
models or unsafe permission policy.
|
|
172
|
-
|
|
173
|
-
OpenRouter is first-class for Claude Code and Codex-VL. Claude uses OpenRouter's Anthropic
|
|
174
|
-
Messages compatibility endpoint, while Codex-VL uses the beta, stateless Responses endpoint
|
|
175
|
-
with direct command-based authentication and no shell. Because provider/model compatibility can
|
|
176
|
-
change independently, the selected OpenRouter model remains explicit. The packaged Kimi K3
|
|
177
|
-
profile pins its one-million-token metadata instead of falling back to a smaller generic window.
|
|
178
|
-
|
|
179
|
-
Kimi Code is a separate Claude Code provider for Kimi membership keys. It defaults to `k3[1m]`,
|
|
180
|
-
uses `https://api.kimi.com/coding/`, and runs with an isolated Claude configuration so a native
|
|
181
|
-
Anthropic account remains untouched. A Kimi Code membership key is not interchangeable with a
|
|
182
|
-
Moonshot pay-as-you-go API key.
|
|
183
|
-
|
|
184
|
-
Alibaba Token Plan Personal is a separate managed profile for Claude Code, Codex-VL and Pi. It
|
|
185
|
-
uses only `ALIBABA_CODE_API_KEY`, defaults to `qwen3.8-max-preview`, and has no OpenAI or
|
|
186
|
-
pay-as-you-go fallback. The npm package also includes the portable `alibaba-token-media` skill
|
|
187
|
-
for dry-run-first Wan image/edit and HappyHorse video workflows. Claude Code, Codex, Codex-VL
|
|
188
|
-
and Pi can invoke its dependency-free Python CLI directly; Pi is not assumed to support MCP
|
|
189
|
-
natively. The media skill requires Python 3. Media generation always requires explicit Credit
|
|
190
|
-
consent and never runs during installation, tests, or startup.
|
|
191
|
-
|
|
192
|
-
The package also includes the portable [`fill-forms`](skills/fill-forms/SKILL.md) skill for
|
|
193
|
-
inspecting, filling and visually validating local PDF and DOCX forms. It supports named
|
|
194
|
-
AcroForm fields, coordinate overlays, checkboxes, character boxes and explicitly authorised
|
|
195
|
-
signature images. Its scripts never install dependencies automatically, never overwrite the
|
|
196
|
-
blank source and do not send documents anywhere. Canonical instructions are in English while
|
|
197
|
-
user-facing guidance follows the user's language; field values and document wording are not
|
|
198
|
-
translated without an explicit request. Optional Python dependencies are not bundled and remain
|
|
199
|
-
subject to their own licences.
|
|
200
|
-
|
|
201
|
-
Permission handling is explicit per cell and engine:
|
|
202
|
-
|
|
203
|
-
- Claude engines can use standard permissions or `--dangerously-skip-permissions`.
|
|
204
|
-
- Codex and Codex-VL can use standard permissions or
|
|
205
|
-
`--dangerously-bypass-approvals-and-sandbox`.
|
|
206
|
-
- Pi uses its native permission behavior.
|
|
207
|
-
|
|
208
|
-
Provider keys are resolved on the node that launches the process. NexusCrew can use the
|
|
209
|
-
service environment, compatible user-owned provider files, or an optional node-local
|
|
210
|
-
write-only credential store. The PWA reports whether a variable is configured but never
|
|
211
|
-
returns its value. Keys are excluded from Fleet definitions, backups, API responses, tmux
|
|
212
|
-
state, process arguments, temporary files and logs.
|
|
213
|
-
|
|
214
|
-
Built-in providers with a fixed variable expose a dedicated **KEY** section in the engine editor.
|
|
215
|
-
It shows only the variable name, configured source and affected engines on the selected node.
|
|
216
|
-
Replacing or removing a shared key warns which engines use it; the entered value is transient in
|
|
217
|
-
the browser and is written only to the node-local credential store.
|
|
218
|
-
|
|
219
|
-
### Built-in Fleet ownership
|
|
220
|
-
|
|
221
|
-
NexusCrew is the only Fleet manager. Cell and engine definitions, lifecycle, boot ownership,
|
|
222
|
-
restart supervision and write-only credentials are all handled by the built-in runtime; no
|
|
223
|
-
external `fleet` executable is discovered or invoked. `nexuscrew-fleet.service` is the optional
|
|
224
|
-
NexusCrew boot companion and starts only cells marked `boot:true`.
|
|
225
|
-
|
|
226
|
-
Set `NEXUSCREW_FLEET=0` to disable Fleet entirely.
|
|
227
|
-
|
|
228
|
-
## Workspaces and terminal behavior
|
|
229
|
-
|
|
230
|
-
Desktop decks place multiple live terminals in a saved tiled layout. Decks remain attached to
|
|
231
|
-
the current PWA by default; `↗` detaches one into another browser window. Session and deck order
|
|
232
|
-
can be changed with pointer drag-and-drop or keyboard controls and is saved automatically.
|
|
233
|
-
|
|
234
|
-
The top deck bar groups workspaces by owner node. Clicking a node name expands or collapses its
|
|
235
|
-
decks; newly seen nodes start collapsed so connected-but-idle machines remain available without
|
|
236
|
-
occupying the bar. Every deck carries a compact activity dot, and collapse choices are stored in
|
|
237
|
-
the current browser and synchronized across its open NexusCrew windows.
|
|
238
|
-
|
|
239
|
-
On mobile, locations are independently collapsible and filterable by all, pinned, active, off,
|
|
240
|
-
or technical sessions. The same owner-qualified ordering model is used by compact and expanded
|
|
241
|
-
desktop views. Managed terminals use the logical Fleet cell name as their visible title; tmux
|
|
242
|
-
session and route identifiers remain technical context rather than the primary heading.
|
|
56
|
+
| **Live terminals** | Attach to real tmux sessions through a real PTY, WebSocket and xterm.js. |
|
|
57
|
+
| **Persistent workspaces** | Arrange sessions into decks with saved layouts, ordering, pins and per-cell drafts. |
|
|
58
|
+
| **Multi-node Fleet** | See and control authorized cells across Linux, macOS and Android nodes. |
|
|
59
|
+
| **AI-ready cells** | Launch Claude Code, Codex, Codex-VL, Pi, Agy or a trusted shell with explicit providers and policies. |
|
|
60
|
+
| **Mobile-native control** | Scroll tmux history, use terminal keys, dictate prompts and move files from a phone. |
|
|
61
|
+
| **Operator alerts** | Receive visual, push and optional on-device spoken notifications. |
|
|
243
62
|
|
|
244
|
-
|
|
245
|
-
<img src="docs/img/fleet-mobile.gif" width="420" alt="NexusCrew mobile Fleet view with managed cells and session controls">
|
|
246
|
-
</p>
|
|
247
|
-
|
|
248
|
-
Terminal attachment uses `tmux attach -f ignore-size` by default. A phone or narrow browser
|
|
249
|
-
therefore cannot resize a session held by another terminal client. Mobile controls expose
|
|
250
|
-
copy-mode scrolling, window and pane navigation, Escape, Ctrl-C and detach. Long text and
|
|
251
|
-
multiline prompts use the terminal application's bracketed-paste mode; clipboard images and
|
|
252
|
-
dropped files are stored in the selected session inbox and their paths are inserted without
|
|
253
|
-
submitting Enter.
|
|
254
|
-
|
|
255
|
-
The two-row mobile key bar can also show a full-height Enter key beside Page Up/Page Down, so
|
|
256
|
-
interactive terminal choices can be confirmed without opening the software keyboard. By default,
|
|
257
|
-
key-bar and speech-to-text actions keep that keyboard closed, while a nearby double tap inside the
|
|
258
|
-
terminal or a direct tap in the composer textarea explicitly opens it. The composer send button
|
|
259
|
-
and the composer history/size controls work without focusing the textarea. **Settings → Input** can change the
|
|
260
|
-
terminal gesture, hide the Enter key, or allow key-bar and voice actions to retain the keyboard.
|
|
261
|
-
The key bar also has a
|
|
262
|
-
**compact** layout (one row with an expand toggle that temporarily reveals the full key set
|
|
263
|
-
without changing the preference). Mobile finger drags always browse tmux history, including when
|
|
264
|
-
the attached TUI uses an alternate screen; desktop wheel events in writable alternate-screen TUIs
|
|
265
|
-
remain application-owned Page Up/Page Down, while normal and readonly terminals use tmux scroll.
|
|
266
|
-
These preferences are browser-local and are synchronized between open NexusCrew windows for
|
|
267
|
-
the same origin.
|
|
268
|
-
|
|
269
|
-
The input composer can expand for longer prompts. Each owner-qualified tmux cell keeps its own
|
|
270
|
-
draft, size preference and bounded prompt history in the current browser, including safe
|
|
271
|
-
ArrowUp/ArrowDown recall at textarea boundaries. This browser-local state is not federated or
|
|
272
|
-
included in Fleet backups and can be cleared from Settings → System.
|
|
273
|
-
|
|
274
|
-
## Notifications and optional spoken alerts
|
|
275
|
-
|
|
276
|
-
Live cell notifications appear as in-app toasts and can also use Web Push when that browser and
|
|
277
|
-
operating system support it. Push delivery remains best-effort and requires the browser permission;
|
|
278
|
-
on iOS it also requires an installed PWA. The service worker cannot synthesize speech, so a hidden
|
|
279
|
-
or closed PWA uses only its normal system-notification path.
|
|
280
|
-
|
|
281
|
-
**Settings → System → Read notifications aloud** adds browser-local speech for new live
|
|
282
|
-
notifications. It is off by default, remains editable when server settings are read-only, uses the
|
|
283
|
-
device's system voice in the current UI language, and sends no notification text to a speech
|
|
284
|
-
service. Enabling it runs an audible test. NexusCrew reports success only after the browser emits
|
|
285
|
-
both speech start and end; if the native engine stays silent or errors, the UI reports that voice
|
|
286
|
-
is unavailable. Credential-shaped values and private home paths are redacted before speech. The
|
|
287
|
-
test must succeed once per page session, including after a reload.
|
|
288
|
-
|
|
289
|
-
Speech runs only while that document is visible and has operating-system focus. Blur, background,
|
|
290
|
-
opt-out and unmount cancel the current utterance and clear pending work; skipped notifications are
|
|
291
|
-
not replayed when focus returns. Duplicate live frames are suppressed for 60 seconds, at most two
|
|
292
|
-
normal alerts remain pending, and a high-urgency alert interrupts the current queue. A 30-second
|
|
293
|
-
watchdog cancels a stuck browser utterance and advances to the next alert.
|
|
294
|
-
|
|
295
|
-
Focus provides one speaker among NexusCrew windows on the same device. Two separately opted-in
|
|
296
|
-
devices may both speak when each PWA is visible and focused; this is intentional for a per-device
|
|
297
|
-
preference. Spoken alerts are optional and do not replace the toast's accessibility status, so
|
|
298
|
-
screen-reader users can leave speech disabled if their assistive technology already announces it.
|
|
299
|
-
Depending on the operating system, an enabled Web Push notification may still coexist with the
|
|
300
|
-
visible toast and spoken alert.
|
|
301
|
-
|
|
302
|
-
## Connect nodes through SSH
|
|
303
|
-
|
|
304
|
-
Every installation starts as a local node. A node joins another NexusCrew installation with a
|
|
305
|
-
single pairing link or QR code:
|
|
306
|
-
|
|
307
|
-
1. On the reachable installation, open **Settings → Nodes → Invite a node**.
|
|
308
|
-
2. Provide the OpenSSH target that the other device can use, such as `user@host` or a local
|
|
309
|
-
SSH config alias. SSH ports, identities, agents, ProxyJump and host-key policy stay in the
|
|
310
|
-
user's OpenSSH configuration.
|
|
311
|
-
3. On the joining device, open **Settings → Nodes**, paste the complete pairing link, and choose
|
|
312
|
-
**Test and connect**. The link is a pairing payload; it is not a browser address to open.
|
|
313
|
-
4. If the portable address cannot select the correct key, open **Advanced / edit** and replace
|
|
314
|
-
it with the SSH alias that already works from that device.
|
|
315
|
-
|
|
316
|
-
Advanced settings keep the local display label separate from the local route handle. The route
|
|
317
|
-
defaults to a readable slug plus a stable node-ID suffix, so devices that all report the hostname
|
|
318
|
-
`localhost` still receive distinct handles. If a hub reports a collision, NexusCrew applies its
|
|
319
|
-
deterministic suggestion and lets the device retry with the same invitation.
|
|
320
|
-
|
|
321
|
-
NexusCrew creates one supervised `ssh` process for the hub connection and proves the forwarded
|
|
322
|
-
TCP endpoint before reporting success. It does not generate SSH keys, edit `authorized_keys`,
|
|
323
|
-
or use `autossh` as a hidden second supervisor.
|
|
324
|
-
|
|
325
|
-
Newly joined devices are private by default. Enabling **Share this device through the selected
|
|
326
|
-
hub** adds a verified reverse channel to the existing SSH process. The hub then decides whether
|
|
327
|
-
authorized peers see the whole network, only the hub, or an explicit subset. Clients do not
|
|
328
|
-
need direct SSH reachability to one another.
|
|
329
|
-
|
|
330
|
-
Reverse ports are reserved across active and pending pairings, probed before use and protected
|
|
331
|
-
by a persistent uniqueness check. Share is stored as desired state: failed activation rolls back
|
|
332
|
-
to private. Deactivation first saves private intent, then asks the hub to withdraw the node over
|
|
333
|
-
the still-live private forward, and only after that acknowledgement removes the reverse channel.
|
|
334
|
-
If the hub cannot acknowledge the revocation, Settings refreshes to the saved private state and
|
|
335
|
-
shows that hub reconciliation is still pending; bounded boot retries continue without claiming
|
|
336
|
-
that remote removal already completed. A stale same-name peer or a late allocation collision
|
|
337
|
-
returns an actionable conflict instead of silently creating a duplicate record or consuming the
|
|
338
|
-
invitation.
|
|
339
|
-
|
|
340
|
-
Private pairing is administrative inventory, not operational publication. A paired client can
|
|
341
|
-
remain listed as **private** in Settings so it can be reconnected or shared again, but it is absent
|
|
342
|
-
from routable topology, owner/deck bars and MCP cell/deck discovery. Temporary loss of reachability
|
|
343
|
-
does not revoke consent: an authorized node remains visible as stale/offline until a successful
|
|
344
|
-
authoritative refresh either restores it or confirms its withdrawal.
|
|
345
|
-
|
|
346
|
-
The Share control reports desired publication separately from verified tunnel reachability. If a
|
|
347
|
-
detached process survives an upgrade with stale `-R` arguments, **Reconnect and reconcile** applies
|
|
348
|
-
the current checkbox state without changing consent and replaces only the verified NexusCrew
|
|
349
|
-
supervisor when its saved command differs. The checkbox itself remains usable while disconnected.
|
|
350
|
-
|
|
351
|
-
OpenSSH key restrictions still apply after global `AllowTcpForwarding` is enabled. A shared client
|
|
352
|
-
needs its accepted hub key to allow the exact negotiated reverse listener, for example
|
|
353
|
-
`permitlisten="127.0.0.1:44002"`; the actionable tunnel diagnostic prints the actual required port.
|
|
354
|
-
NexusCrew never edits `authorized_keys`, so this policy remains an explicit hub-operator action.
|
|
355
|
-
|
|
356
|
-
Node groups can be reordered independently in each browser from both desktop and mobile lists.
|
|
357
|
-
Their human-readable label has one server-backed source: rename from Settings or a roster and the
|
|
358
|
-
same canonical label appears everywhere without changing the technical route name, node identity,
|
|
359
|
-
credentials, Share state or deck identity.
|
|
360
|
-
|
|
361
|
-
For routed nodes that the current installation does not own, Settings → Nodes offers a local
|
|
362
|
-
alias instead of a remote rename. The alias is private to the viewing installation, follows the
|
|
363
|
-
stable instance identity and never changes or federates the remote label, route or owner.
|
|
364
|
-
|
|
365
|
-
Pairing links contain a short-lived one-time invite and routing fields, but no SSH private key,
|
|
366
|
-
provider key or PWA token. Node and deck identities remain owner-qualified across the network,
|
|
367
|
-
and every routed HTTP or WebSocket request rechecks authorization, hop count and cycle rules.
|
|
368
|
-
|
|
369
|
-
## Access and security model
|
|
370
|
-
|
|
371
|
-
NexusCrew listens only on `127.0.0.1`. To use a remote installation, bring its loopback port to
|
|
372
|
-
your device through SSH or a VPN you control:
|
|
63
|
+
The browser is a client, not the session host:
|
|
373
64
|
|
|
374
|
-
```
|
|
375
|
-
|
|
65
|
+
```text
|
|
66
|
+
Browser PWA
|
|
67
|
+
│ authenticated HTTP + WebSocket on loopback
|
|
68
|
+
▼
|
|
69
|
+
NexusCrew ── real PTY ── tmux sessions
|
|
70
|
+
│
|
|
71
|
+
├── supervised OpenSSH ── remote NexusCrew nodes
|
|
72
|
+
│
|
|
73
|
+
└── stdio MCP bridge ── AI CLI workers
|
|
376
74
|
```
|
|
377
75
|
|
|
378
|
-
|
|
379
|
-
user-only file and travels in the URL fragment (`#token=...`), so it is not sent in the initial
|
|
380
|
-
HTTP request or written to server access logs.
|
|
381
|
-
|
|
382
|
-
The security boundary is intentionally narrow:
|
|
383
|
-
|
|
384
|
-
- loopback bind only; non-loopback binds are rejected
|
|
385
|
-
- local bearer token for every API and WebSocket connection
|
|
386
|
-
- tmux remains the session authority
|
|
387
|
-
- OpenSSH remains the network and identity authority
|
|
388
|
-
- provider credentials remain on the node that uses them
|
|
389
|
-
- file operations reject traversal and symlink escapes
|
|
390
|
-
- Fleet and federation mutations are schema-validated and ACL-checked
|
|
391
|
-
|
|
392
|
-
Direct public exposure through a reverse proxy, public port forward or network bind is not a
|
|
393
|
-
supported deployment model.
|
|
394
|
-
|
|
395
|
-
## Backup and updates
|
|
76
|
+
## Local-first by design
|
|
396
77
|
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
home instead of copying device-specific absolute paths. A legacy or foreign path is shown as an
|
|
401
|
-
explicit repair action and is never silently remapped. Archives contain credential variable
|
|
402
|
-
names, never credential values, tokens or live tmux state.
|
|
78
|
+
NexusCrew has no hosted control service, required account or public listener.
|
|
79
|
+
It binds to `127.0.0.1`, authenticates the PWA with a local token and leaves
|
|
80
|
+
session ownership to tmux.
|
|
403
81
|
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
82
|
+
- OpenSSH remains the network and identity authority.
|
|
83
|
+
- Provider credentials stay on the node that uses them.
|
|
84
|
+
- Pairing links contain no SSH private key, provider key or PWA token.
|
|
85
|
+
- File operations reject traversal and symlink escapes.
|
|
86
|
+
- Updates preserve tmux sessions and roll back when health checks fail.
|
|
409
87
|
|
|
410
|
-
|
|
411
|
-
the shared tmux server. Lifecycle commands fail closed when that protection cannot be verified.
|
|
88
|
+
Remote access is intentionally carried through SSH or a VPN you control:
|
|
412
89
|
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
Settings → Diagnostics shows a bounded in-memory event buffer for the local installation or an
|
|
416
|
-
authorized routed node. Verbose collection is explicit and expires after 5, 15, 30 or 60 minutes;
|
|
417
|
-
operational warnings and errors remain available when verbose mode is off. The view supports
|
|
418
|
-
level/component filtering, pause, autoscroll, copy, JSON export and explicit clear.
|
|
419
|
-
|
|
420
|
-
Records are structured and redacted before storage. Raw terminal content, prompts, command lines,
|
|
421
|
-
environment values, tokens, credentials and filesystem paths are not accepted as diagnostic
|
|
422
|
-
metadata. Fleet launch failures include only closed `code` and `phase` values so preflight,
|
|
423
|
-
broker, tmux, readiness and client-spawn failures can be distinguished safely. The buffer is not
|
|
424
|
-
a reader for service journals or log files.
|
|
425
|
-
|
|
426
|
-
## MCP bridge
|
|
427
|
-
|
|
428
|
-
`nexuscrew mcp` exposes the local authenticated runtime as a dependency-free stdio MCP server.
|
|
429
|
-
It is intended for AI sessions running inside managed tmux cells.
|
|
430
|
-
|
|
431
|
-
| Tool | Purpose |
|
|
432
|
-
|---|---|
|
|
433
|
-
| `nc_notify` | Send a PWA notification to the operator |
|
|
434
|
-
| `nc_ask` | Ask a non-blocking question and return the answer to the calling session |
|
|
435
|
-
| `nc_send_file` | Place a file from the caller's home in its downloadable outbox |
|
|
436
|
-
| `nc_status` | Read live tmux and Fleet status |
|
|
437
|
-
| `nc_inbox` | List files received by the caller |
|
|
438
|
-
| `nc_deck` | Discover owner-qualified decks containing the calling tmux session |
|
|
439
|
-
| `nc_cells` | List authorized active and inactive Fleet cells across visible nodes |
|
|
440
|
-
| `nc_cell_diagnostics` | Read the redacted Shell command and latest bounded start/spawn failure for one exact local cell |
|
|
441
|
-
| `nc_send_cell` | Submit bounded text to one exact active cell returned by `nc_cells` |
|
|
442
|
-
| `nc_identity` | Read-only identity diagnostics; callable with no session and no token |
|
|
443
|
-
|
|
444
|
-
Cell delivery uses bracketed paste followed by a separate Enter. A `submitted` receipt confirms
|
|
445
|
-
delivery to the target TUI, not acceptance or completion by its model. There is no silent
|
|
446
|
-
offline queue.
|
|
447
|
-
|
|
448
|
-
`nc_identity` returns only non-sensitive data: the `source` the caller was resolved from
|
|
449
|
-
(`tmux`, `NEXUSCREW_MCP_SESSION`, or `missing`), boolean presence of the identity env vars,
|
|
450
|
-
a stable `code` (`OK`, `NEXUSCREW_MCP_IDENTITY_MISSING`, `NEXUSCREW_MCP_IDENTITY_INVALID`) and
|
|
451
|
-
a remediation hint. It never calls an HTTP API or reads the token, so it works even when the
|
|
452
|
-
identity is missing — use it to diagnose why the identity-gated tools fail closed.
|
|
453
|
-
|
|
454
|
-
Register the bridge in Claude Code:
|
|
455
|
-
|
|
456
|
-
```json
|
|
457
|
-
{
|
|
458
|
-
"mcpServers": {
|
|
459
|
-
"nexuscrew": {
|
|
460
|
-
"command": "nexuscrew",
|
|
461
|
-
"args": ["mcp"]
|
|
462
|
-
}
|
|
463
|
-
}
|
|
464
|
-
}
|
|
465
|
-
```
|
|
466
|
-
|
|
467
|
-
Or in Codex / Codex-VL (`env_vars` allowlists variable **names** only — no values are copied
|
|
468
|
-
into the CLI or config file):
|
|
469
|
-
|
|
470
|
-
```toml
|
|
471
|
-
[mcp_servers.nexuscrew]
|
|
472
|
-
command = "nexuscrew"
|
|
473
|
-
args = ["mcp"]
|
|
474
|
-
env_vars = ["NEXUSCREW_MCP_SESSION", "TMUX", "TMUX_PANE"]
|
|
90
|
+
```bash
|
|
91
|
+
ssh -L 41820:127.0.0.1:41820 user@your-host
|
|
475
92
|
```
|
|
476
93
|
|
|
477
|
-
|
|
94
|
+
[Security model →](docs/SECURITY.md)
|
|
478
95
|
|
|
479
|
-
|
|
480
|
-
codex-vl mcp add nexuscrew \
|
|
481
|
-
--env-var NEXUSCREW_MCP_SESSION \
|
|
482
|
-
--env-var TMUX \
|
|
483
|
-
--env-var TMUX_PANE \
|
|
484
|
-
-- nexuscrew mcp
|
|
485
|
-
```
|
|
96
|
+
## Documentation
|
|
486
97
|
|
|
487
|
-
|
|
488
|
-
then from the `NEXUSCREW_MCP_SESSION` fallback, then not at all. Codex/Codex-VL launch MCP stdio
|
|
489
|
-
processes with a cleared environment, so those clients must explicitly allowlist the identity
|
|
490
|
-
env vars for the server to observe them; otherwise the identity-gated tools (`nc_ask`, `nc_send_file`,
|
|
491
|
-
`nc_deck`, `nc_cell_diagnostics`, `nc_send_cell`, `nc_inbox`) stay fail-closed with a stable
|
|
492
|
-
`NEXUSCREW_MCP_IDENTITY_*` code, while `nc_notify` degrades to an unknown sender.
|
|
493
|
-
|
|
494
|
-
`nc_cell_diagnostics` accepts an exact owner-qualified ID returned by `nc_cells`, but only when
|
|
495
|
-
that target belongs to the local node and the caller is an active local Fleet cell. It does not
|
|
496
|
-
query remote nodes or add commands to the federated directory. The returned command is bounded
|
|
497
|
-
and credential-redacted; the failure is a closed `{status, code, phase}` cause rather than raw
|
|
498
|
-
stderr, paths, environment values, prompts or tokens.
|
|
499
|
-
|
|
500
|
-
## Optional MCP companions
|
|
501
|
-
|
|
502
|
-
NexusCrew can work alongside separate local-first MCP servers for durable
|
|
503
|
-
structured memory, searchable document memory, bounded worker delegation and
|
|
504
|
-
mail access. They are optional projects rather than hidden NexusCrew
|
|
505
|
-
dependencies: the AI should discover its existing tools first, recommend a
|
|
506
|
-
companion only for a capability the user actually requested, and ask before
|
|
507
|
-
installing or changing client configuration.
|
|
508
|
-
|
|
509
|
-
See [MCP_COMPANIONS.md](MCP_COMPANIONS.md) for the capability guide and
|
|
510
|
-
[`mcp-companions.json`](mcp-companions.json) for the machine-readable catalog.
|
|
511
|
-
The npm package also includes generic [`memory`](skills/memory/SKILL.md),
|
|
512
|
-
[`vl-msa`](skills/vl-msa/SKILL.md), [`crew`](skills/crew/SKILL.md) and
|
|
513
|
-
[`mail-assistant`](skills/mail-assistant/SKILL.md) skills. Their instructions
|
|
514
|
-
are written in English, while user-facing output follows the user's explicit
|
|
515
|
-
preference or request language; Mail reply drafts follow the email thread by
|
|
516
|
-
default.
|
|
517
|
-
|
|
518
|
-
`fill-forms` is a separate bundled local document skill, not an MCP companion.
|
|
519
|
-
It is documented in [Fleet: cells, engines and providers](#fleet-cells-engines-and-providers)
|
|
520
|
-
and carries no automatic installation or external-service behaviour.
|
|
521
|
-
|
|
522
|
-
## Configuration
|
|
523
|
-
|
|
524
|
-
Runtime state is local to the current user:
|
|
525
|
-
|
|
526
|
-
| Path | Contents |
|
|
98
|
+
| Guide | Covers |
|
|
527
99
|
|---|---|
|
|
528
|
-
|
|
|
529
|
-
|
|
|
530
|
-
|
|
|
531
|
-
|
|
|
532
|
-
|
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
100
|
+
| [Documentation index](docs/README.md) | Start here for every guide |
|
|
101
|
+
| [Installation](docs/INSTALLATION.md) | Linux, macOS, Termux, first run and upgrades |
|
|
102
|
+
| [Fleet and terminals](docs/FLEET.md) | Cells, engines, providers, decks and mobile input |
|
|
103
|
+
| [Connect nodes](docs/NODES.md) | Pairing, SSH routes, sharing and routed aliases |
|
|
104
|
+
| [Notifications](docs/NOTIFICATIONS.md) | Toasts, Web Push and optional spoken alerts |
|
|
105
|
+
| [MCP bridge](docs/MCP.md) | Operator tools, cell delivery and client setup |
|
|
106
|
+
| [Configuration](docs/CONFIGURATION.md) | Files, environment overrides and local settings |
|
|
107
|
+
| [Operations](docs/OPERATIONS.md) | CLI, boot, backup, updates and diagnostics |
|
|
108
|
+
| [Security](docs/SECURITY.md) | Trust boundaries, tokens and credential handling |
|
|
109
|
+
|
|
110
|
+
The repository also includes [MCP companion guidance](MCP_COMPANIONS.md),
|
|
111
|
+
the machine-readable [`mcp-companions.json`](mcp-companions.json), and portable
|
|
112
|
+
skills for memory, searchable document memory, bounded worker delegation,
|
|
113
|
+
mail assistance and form filling.
|
|
114
|
+
|
|
115
|
+
## Platforms
|
|
116
|
+
|
|
117
|
+
| Platform | Architectures | Background integration |
|
|
118
|
+
|---|---|---|
|
|
119
|
+
| Linux | x64, ARM64 | systemd user service or detached runtime |
|
|
120
|
+
| macOS | x64, ARM64 | LaunchAgent or detached runtime |
|
|
121
|
+
| Android / Termux | ARM64 | detached runtime and optional Termux:Boot |
|
|
122
|
+
|
|
123
|
+
Run `nexuscrew doctor` after installation or when moving configuration between
|
|
124
|
+
devices.
|
|
553
125
|
|
|
554
126
|
## Development
|
|
555
127
|
|
|
556
128
|
```bash
|
|
557
|
-
npm test
|
|
558
|
-
npm run build
|
|
129
|
+
npm test
|
|
130
|
+
npm run build
|
|
559
131
|
node bin/nexuscrew.js serve
|
|
560
132
|
```
|
|
561
133
|
|
|
562
|
-
Tests that exercise tmux use private sockets and
|
|
563
|
-
operator's tmux server.
|
|
564
|
-
|
|
565
|
-
## Roadmap
|
|
566
|
-
|
|
567
|
-
The current companion catalog is documentation and agent guidance only. A future optional MCP
|
|
568
|
-
gateway could expose one NexusCrew endpoint with explicit, per-tool federation through shared
|
|
569
|
-
nodes. Credentials and execution would remain on the owner node, with owner-qualified tool
|
|
570
|
-
identities and read/mutate ACLs. The gateway is planned work and is **not part of this release**.
|
|
134
|
+
Tests that exercise tmux use private sockets and never attach to or terminate
|
|
135
|
+
the operator's tmux server.
|
|
571
136
|
|
|
572
137
|
See [CHANGELOG.md](CHANGELOG.md) for released changes.
|
|
573
138
|
|
|
574
|
-
## Status
|
|
575
|
-
|
|
576
|
-
The current stable release is **v0.8.36** on npm and GitHub.
|
|
577
|
-
|
|
578
139
|
## License
|
|
579
140
|
|
|
580
141
|
Apache-2.0 © 2026 Davide A. Guglielmi (DioNanos)
|