Content
# NexusCrew
[](https://www.npmjs.com/package/@mmmbuto/nexuscrew)
[](LICENSE)
[](https://nodejs.org)
[](#platform-support)
NexusCrew is a local-first web control plane for tmux sessions and AI CLI workers. It streams
real PTYs to a browser, organizes sessions into persistent decks, and connects multiple
NexusCrew installations through SSH without replacing tmux or your existing SSH setup.
<p align="center">
<img src="docs/img/fleet-deck-desktop.png" width="960" alt="NexusCrew desktop interface with multiple live tmux sessions arranged in a deck">
</p>
NexusCrew binds to `127.0.0.1`, authenticates the PWA with a local token, and leaves session
ownership to tmux. It has no hosted control service, user account system, or public network
listener.
## Overview
| Area | What NexusCrew provides |
|---|---|
| Terminal | Real PTY attachment to live tmux sessions through WebSocket and xterm.js |
| Workspaces | Named decks, tiled desktop layouts, mobile session view, saved ordering, pins and per-cell composer state |
| Fleet | Reusable cells, engines, providers, models, permission policies, prompts, boot state and live working status |
| Nodes | One-link pairing and owner-qualified routing over supervised OpenSSH connections |
| Operations | Background service, boot integration, diagnostics, stable npm updates and selective backup |
| AI integration | A stdio MCP bridge for operator communication, deck discovery and cell-to-cell delivery |
The browser is a client, not the session host:
```text
Browser PWA
│ authenticated HTTP + WebSocket on loopback
▼
NexusCrew ── real PTY ── tmux sessions
│
├── supervised OpenSSH ── remote NexusCrew nodes
│
└── stdio MCP bridge ── Claude Code / Codex / Codex-VL / Pi
```
## Install
### Requirements
- Node.js 18 or newer
- tmux 3.4 or newer
- OpenSSH client (`ssh`) for node connections and a clean diagnostic result
- Linux x64/ARM64, macOS x64/ARM64, or Android ARM64 through Termux
NexusCrew ships scriptless PTY prebuilds for the supported targets. A normal global install
does not need a compiler or native install-script approval.
### Linux
Install Node.js, tmux and OpenSSH with your distribution package manager, then:
```bash
npm install -g @mmmbuto/nexuscrew
nexuscrew
```
### macOS
```bash
brew install node tmux
npm install -g @mmmbuto/nexuscrew
nexuscrew
```
### Android / Termux
```bash
pkg update
pkg install nodejs-lts tmux openssh
npm install -g @mmmbuto/nexuscrew
nexuscrew
```
The first run creates the loopback-only runtime, starts it in the background, opens the PWA,
and presents the setup wizard. Later runs reuse the configured service, print a compact status,
and exit.
The preferred port is `41820`. If another process owns it, NexusCrew selects the next free
loopback port and records the result.
## CLI
The PWA remains the visual control surface, while the CLI exposes the complete peer workflow for
headless hosts and VPS installations.
| Command | Purpose |
|---|---|
| `nexuscrew` | Start or reuse the background runtime and print a short status |
| `nexuscrew init [--dry-run] [--port PORT]` | Initialize missing local stores idempotently or preview the operation |
| `nexuscrew show` | Start when needed and open the authenticated PWA |
| `nexuscrew show token` | Print the authenticated browser link without opening it |
| `nexuscrew status` | Show service, port, role and node status |
| `nexuscrew stop` | Stop NexusCrew and its managed tunnels without stopping tmux sessions |
| `nexuscrew restart` | Restart NexusCrew and restore autostart node links without stopping tmux |
| `nexuscrew boot` | Enable startup persistence |
| `nexuscrew boot off` | Disable startup persistence while leaving the current runtime alive |
| `nexuscrew doctor` | Check Node, PTY, tmux, SSH, service and platform integration |
| `nexuscrew nodes list [--json]` | List direct hubs, connected clients and routed read-only peers |
| `nexuscrew nodes inspect <name\|nodeId>` | Inspect a peer by stable identity |
| `nexuscrew nodes edit <name\|nodeId> ...` | Change the canonical label or direction-specific connection settings |
| `nexuscrew nodes up\|down\|connect\|disconnect\|restart\|reconnect <name\|nodeId>` | Manage a direct node link without requiring the PWA |
| `nexuscrew nodes share <name\|nodeId> on\|off` | Publish or withdraw a direct node from the authorized network |
| `nexuscrew nodes remove <name\|nodeId> --yes` | Revoke/forget a direct peer after explicit confirmation |
| `nexuscrew nodes invite --ssh <target>` | Create a one-time pairing link from a headless hub |
| `nexuscrew nodes pair\|join` | Read a one-time pairing link from stdin and join headlessly |
| `nexuscrew help` | Show command help |
| `nexuscrew version` | Show the installed version |
Boot integration uses a user systemd service on Linux, a LaunchAgent on macOS, and a
Termux:Boot script on Android. Termux users must install the Termux:Boot app and open it once;
the CLI can validate the script but cannot prove Android app activation.
Cells marked `boot:true` are started when that platform boot integration runs. This is startup
persistence, not a watchdog for the tmux server itself: if the entire tmux server disappears
later, the boot companion is not automatically rerun.
## Fleet: cells, engines and providers
A **cell** is a reusable worker definition: tmux session name, working directory, engine,
model, permission policy, optional system prompt and boot state. Starting a stopped cell opens
the same launch sheet on desktop and mobile, so the effective settings can be reviewed before
the process starts.
An **engine** describes how a CLI is launched. Clean installations include four base adapters:
- Claude Code
- Codex
- Codex-VL
- Pi
The provider catalog is scoped to the selected CLI rather than to a machine-specific setup:
| CLI | Built-in provider choices |
|---|---|
| Claude Code | Anthropic, Alibaba Token Plan Personal, OpenRouter, Kimi Code, Amazon Bedrock, Google Vertex AI, Microsoft Foundry, Ollama Cloud, local Ollama, Z.AI, custom Anthropic-compatible endpoint |
| Codex | OpenAI or ChatGPT login, OpenAI API, Ollama Cloud, local Ollama, LM Studio, custom OpenAI Responses endpoint |
| Codex-VL | OpenAI or ChatGPT login, OpenAI API, Alibaba Token Plan Personal, OpenRouter, Ollama Cloud, local Ollama, LM Studio, custom OpenAI Responses endpoint |
| Pi | Native default, Anthropic, OpenAI API, Alibaba Token Plan Personal, Codex OAuth, Gemini, GitHub Copilot, OpenRouter, Ollama, DeepSeek, Z.AI, custom provider |
Custom Codex-compatible endpoints use the real Responses wire API; NexusCrew does not silently
fall back to Chat Completions. Custom argv-based engines are also supported and are launched
directly without a shell after trust-boundary validation.
OpenRouter is first-class for Claude Code and Codex-VL. Claude uses OpenRouter's Anthropic
Messages compatibility endpoint, while Codex-VL uses the beta, stateless Responses endpoint
with direct command-based authentication and no shell. Because provider/model compatibility can
change independently, the selected OpenRouter model remains explicit. The packaged Kimi K3
profile pins its one-million-token metadata instead of falling back to a smaller generic window.
Kimi Code is a separate Claude Code provider for Kimi membership keys. It defaults to `k3[1m]`,
uses `https://api.kimi.com/coding/`, and runs with an isolated Claude configuration so a native
Anthropic account remains untouched. A Kimi Code membership key is not interchangeable with a
Moonshot pay-as-you-go API key.
Alibaba Token Plan Personal is a separate managed profile for Claude Code, Codex-VL and Pi. It
uses only `ALIBABA_CODE_API_KEY`, defaults to `qwen3.8-max-preview`, and has no OpenAI or
pay-as-you-go fallback. The npm package also includes the portable `alibaba-token-media` skill
for dry-run-first Wan image/edit and HappyHorse video workflows. Claude Code, Codex, Codex-VL
and Pi can invoke its dependency-free Python CLI directly; Pi is not assumed to support MCP
natively. The media skill requires Python 3. Media generation always requires explicit Credit
consent and never runs during installation, tests, or startup.
Permission handling is explicit per cell and engine:
- Claude engines can use standard permissions or `--dangerously-skip-permissions`.
- Codex and Codex-VL can use standard permissions or
`--dangerously-bypass-approvals-and-sandbox`.
- Pi uses its native permission behavior.
Provider keys are resolved on the node that launches the process. NexusCrew can use the
service environment, compatible user-owned provider files, or an optional node-local
write-only credential store. The PWA reports whether a variable is configured but never
returns its value. Keys are excluded from Fleet definitions, backups, API responses, tmux
state, process arguments, temporary files and logs.
Built-in providers with a fixed variable expose a dedicated **KEY** section in the engine editor.
It shows only the variable name, configured source and affected engines on the selected node.
Replacing or removing a shared key warns which engines use it; the entered value is transient in
the browser and is written only to the node-local credential store.
### Built-in Fleet ownership
NexusCrew is the only Fleet manager. Cell and engine definitions, lifecycle, boot ownership,
restart supervision and write-only credentials are all handled by the built-in runtime; no
external `fleet` executable is discovered or invoked. `nexuscrew-fleet.service` is the optional
NexusCrew boot companion and starts only cells marked `boot:true`.
Set `NEXUSCREW_FLEET=0` to disable Fleet entirely.
## Workspaces and terminal behavior
Desktop decks place multiple live terminals in a saved tiled layout. Decks remain attached to
the current PWA by default; `↗` detaches one into another browser window. Session and deck order
can be changed with pointer drag-and-drop or keyboard controls and is saved automatically.
On mobile, locations are independently collapsible and filterable by all, pinned, active, off,
or technical sessions. The same owner-qualified ordering model is used by compact and expanded
desktop views.
<p align="center">
<img src="docs/img/fleet-mobile.gif" width="420" alt="NexusCrew mobile Fleet view with managed cells and session controls">
</p>
Terminal attachment uses `tmux attach -f ignore-size` by default. A phone or narrow browser
therefore cannot resize a session held by another terminal client. Mobile controls expose
copy-mode scrolling, window and pane navigation, Escape, Ctrl-C and detach. Long text and
multiline prompts use the terminal application's bracketed-paste mode; clipboard images and
dropped files are stored in the selected session inbox and their paths are inserted without
submitting Enter.
The input composer can expand for longer prompts. Each owner-qualified tmux cell keeps its own
draft, size preference and bounded prompt history in the current browser, including safe
ArrowUp/ArrowDown recall at textarea boundaries. This browser-local state is not federated or
included in Fleet backups and can be cleared from Settings → System.
## Connect nodes through SSH
Every installation starts as a local node. A node joins another NexusCrew installation with a
single pairing link or QR code:
1. On the reachable installation, open **Settings → Nodes → Invite a node**.
2. Provide the OpenSSH target that the other device can use, such as `user@host` or a local
SSH config alias. SSH ports, identities, agents, ProxyJump and host-key policy stay in the
user's OpenSSH configuration.
3. On the joining device, open **Settings → Nodes**, paste the complete pairing link, and choose
**Test and connect**. The link is a pairing payload; it is not a browser address to open.
4. If the portable address cannot select the correct key, open **Advanced / edit** and replace
it with the SSH alias that already works from that device.
Advanced settings keep the local display label separate from the local route handle. The route
defaults to a readable slug plus a stable node-ID suffix, so devices that all report the hostname
`localhost` still receive distinct handles. If a hub reports a collision, NexusCrew applies its
deterministic suggestion and lets the device retry with the same invitation.
NexusCrew creates one supervised `ssh` process for the hub connection and proves the forwarded
TCP endpoint before reporting success. It does not generate SSH keys, edit `authorized_keys`,
or use `autossh` as a hidden second supervisor.
Newly joined devices are private by default. Enabling **Share this device through the selected
hub** adds a verified reverse channel to the existing SSH process. The hub then decides whether
authorized peers see the whole network, only the hub, or an explicit subset. Clients do not
need direct SSH reachability to one another.
Reverse ports are reserved across active and pending pairings, probed before use and protected
by a persistent uniqueness check. Share is stored as desired state: failed activation rolls back
to private, while a failed deactivation remains private and is reconciled after restart. A stale
same-name peer or a late allocation collision returns an actionable conflict instead of silently
creating a duplicate record or consuming the invitation.
The Share control reports desired publication separately from verified tunnel reachability. If a
detached process survives an upgrade with stale `-R` arguments, **Reconnect and reconcile** applies
the current checkbox state without changing consent and replaces only the verified NexusCrew
supervisor when its saved command differs. The checkbox itself remains usable while disconnected.
OpenSSH key restrictions still apply after global `AllowTcpForwarding` is enabled. A shared client
needs its accepted hub key to allow the exact negotiated reverse listener, for example
`permitlisten="127.0.0.1:44002"`; the actionable tunnel diagnostic prints the actual required port.
NexusCrew never edits `authorized_keys`, so this policy remains an explicit hub-operator action.
Node groups can be reordered independently in each browser from both desktop and mobile lists.
Their human-readable label has one server-backed source: rename from Settings or a roster and the
same canonical label appears everywhere without changing the technical route name, node identity,
credentials, Share state or deck identity.
Pairing links contain a short-lived one-time invite and routing fields, but no SSH private key,
provider key or PWA token. Node and deck identities remain owner-qualified across the network,
and every routed HTTP or WebSocket request rechecks authorization, hop count and cycle rules.
## Access and security model
NexusCrew listens only on `127.0.0.1`. To use a remote installation, bring its loopback port to
your device through SSH or a VPN you control:
```bash
ssh -L 41820:127.0.0.1:41820 user@your-host
```
Then open the authenticated link returned by `nexuscrew show token`. The token is stored in a
user-only file and travels in the URL fragment (`#token=...`), so it is not sent in the initial
HTTP request or written to server access logs.
The security boundary is intentionally narrow:
- loopback bind only; non-loopback binds are rejected
- local bearer token for every API and WebSocket connection
- tmux remains the session authority
- OpenSSH remains the network and identity authority
- provider credentials remain on the node that uses them
- file operations reject traversal and symlink escapes
- Fleet and federation mutations are schema-validated and ACL-checked
Direct public exposure through a reverse proxy, public port forward or network bind is not a
supported deployment model.
## Backup and updates
Settings → Fleet can export and restore selected cells, system prompts and reusable engine
definitions. Restore previews conflicts, supports per-item selection and reports active cells
that need a restart. Archives contain credential variable names, never credential values,
tokens or live tmux state.
Global npm installations can follow the stable `latest` tag automatically. NexusCrew serializes
updates, verifies the new CLI and same-port runtime, and rolls back once to the exact previous
version if health checks fail. It never installs prereleases from `latest` or downgrades. Update
state and manual controls are available in Settings → System; set
`NEXUSCREW_AUTO_UPDATE=0` to disable the scheduler.
On Linux, generated user services use `KillMode=process` so restarting NexusCrew does not stop
the shared tmux server. Lifecycle commands fail closed when that protection cannot be verified.
## MCP bridge
`nexuscrew mcp` exposes the local authenticated runtime as a dependency-free stdio MCP server.
It is intended for AI sessions running inside managed tmux cells.
| Tool | Purpose |
|---|---|
| `nc_notify` | Send a PWA notification to the operator |
| `nc_ask` | Ask a non-blocking question and return the answer to the calling session |
| `nc_send_file` | Place a file from the caller's home in its downloadable outbox |
| `nc_status` | Read live tmux and Fleet status |
| `nc_inbox` | List files received by the caller |
| `nc_deck` | Discover owner-qualified decks containing the calling tmux session |
| `nc_cells` | List authorized active and inactive Fleet cells across visible nodes |
| `nc_send_cell` | Submit bounded text to one exact active cell returned by `nc_cells` |
| `nc_identity` | Read-only identity diagnostics; callable with no session and no token |
Cell delivery uses bracketed paste followed by a separate Enter. A `submitted` receipt confirms
delivery to the target TUI, not acceptance or completion by its model. There is no silent
offline queue.
`nc_identity` returns only non-sensitive data: the `source` the caller was resolved from
(`tmux`, `NEXUSCREW_MCP_SESSION`, or `missing`), boolean presence of the identity env vars,
a stable `code` (`OK`, `NEXUSCREW_MCP_IDENTITY_MISSING`, `NEXUSCREW_MCP_IDENTITY_INVALID`) and
a remediation hint. It never calls an HTTP API or reads the token, so it works even when the
identity is missing — use it to diagnose why the identity-gated tools fail closed.
Register the bridge in Claude Code:
```json
{
"mcpServers": {
"nexuscrew": {
"command": "nexuscrew",
"args": ["mcp"]
}
}
}
```
Or in Codex / Codex-VL (`env_vars` allowlists variable **names** only — no values are copied
into the CLI or config file):
```toml
[mcp_servers.nexuscrew]
command = "nexuscrew"
args = ["mcp"]
env_vars = ["NEXUSCREW_MCP_SESSION", "TMUX", "TMUX_PANE"]
```
The equivalent CLI form on a Codex-VL build that supports `--env-var` (allowlist by name, repeated):
```text
codex-vl mcp add nexuscrew \
--env-var NEXUSCREW_MCP_SESSION \
--env-var TMUX \
--env-var TMUX_PANE \
-- nexuscrew mcp
```
The caller is resolved, in order, from its tmux session (`tmux display-message -p '#S'`),
then from the `NEXUSCREW_MCP_SESSION` fallback, then not at all. Codex/Codex-VL launch MCP stdio
processes with a cleared environment, so those clients must explicitly allowlist the identity
env vars for the server to observe them; otherwise the identity-gated tools (`nc_ask`, `nc_send_file`,
`nc_deck`, `nc_send_cell`, `nc_inbox`) stay fail-closed with a stable
`NEXUSCREW_MCP_IDENTITY_*` code, while `nc_notify` degrades to an unknown sender.
## Configuration
Runtime state is local to the current user:
| Path | Contents |
|---|---|
| `~/.nexuscrew/config.json` | Port, Fleet mode and runtime options |
| `~/.nexuscrew/token` | Local PWA bearer token |
| `~/.nexuscrew/credentials.json` | Optional node-local write-only provider store |
| `~/.nexuscrew/tunnels/` | Managed SSH supervisor state and owner-only logs |
| `~/NexusFiles/<session>/` | Per-session inbox and outbox |
Common environment overrides include `NEXUSCREW_PORT`, `NEXUSCREW_CONFIG_FILE`,
`NEXUSCREW_TOKEN_FILE`, `NEXUSCREW_FILES_ROOT`, `NEXUSCREW_TMUX`,
`NEXUSCREW_FLEET=0`, `NEXUSCREW_READONLY=1`, `NEXUSCREW_AUTO_UPDATE=0`, and
`NEXUSCREW_DEBUG=1`.
## Platform support
| Platform | Architectures | Background integration | PTY provider |
|---|---|---|---|
| Linux | x64, ARM64 | systemd user service or detached runtime | packaged native prebuild |
| macOS | x64, ARM64 | LaunchAgent or detached runtime | packaged native prebuild |
| Android / Termux | ARM64 | detached runtime and optional Termux:Boot | Android ARM64 package |
Run `nexuscrew doctor` after installation or when moving a configuration between devices. A
missing OpenSSH client is a blocking diagnostic; `autossh` is reported separately and remains
optional because NexusCrew supervises OpenSSH directly.
## Development
```bash
npm test # isolated Node tests plus frontend tests
npm run build # build the PWA into frontend/dist
node bin/nexuscrew.js serve
```
Tests that exercise tmux use private sockets and must never attach to or terminate the
operator's tmux server.
## Roadmap
The next architectural track is an optional MCP gateway: one NexusCrew MCP endpoint with a
local catalog of upstream MCP servers and explicit, per-tool federation through shared nodes.
Credentials and execution would remain on the owner node, with owner-qualified tool identities
and read/mutate ACLs. This gateway is planned work and is **not part of the current release**.
See [CHANGELOG.md](CHANGELOG.md) for released changes.
## Status
The current stable release is **v0.8.26** on npm and GitHub.
## License
Apache-2.0 © 2026 Davide A. Guglielmi (DioNanos)
MCP Config
Below is the configuration for this MCP Server. You can copy it directly to Cursor or other MCP clients.
mcp.json
Connection Info
You Might Also Like
No recommendations available