Shell Cluster
Decentralized remote shell access across all your machines. No central server required.
Cross-platform (macOS / Windows / Linux) -- each machine runs a lightweight daemon that peers discover automatically via shared tunnel credentials. Connect to any machine's shell from anywhere, like SSH but without managing keys or servers.
中文文档
How It Works
macOS (zsh) Windows (PowerShell) Linux (bash)
┌──────────────┐ ┌──────────────┐ ┌──────────────┐
│ daemon │ │ daemon │ │ daemon │
└──────┬───────┘ └──────┬───────┘ └──────┬───────┘
│ │ │
═════╪═════════ Tunnel (P2P, no server) ═════════════════╪═════
│ │ │
CLI / Web Dashboard (from any machine, any OS)
No central server. Every node is equal. Nodes discover each other by querying the tunnel provider's API for tunnels tagged with a shared label -- all under the same account. No relay, no coordinator, no single point of failure.
Platform Support
| macOS | Yes | Yes | zsh, bash, fish, ... |
| Windows | Yes | Yes | pwsh (PS 7+), PowerShell, cmd, Git Bash, ... |
| Linux | Yes | Yes | bash, zsh, fish, ... |
Install
Requires Node.js 18+.
Install globally
npm install -g shell-cluster
Try without installing (macOS/Linux only)
npx shell-cluster start --no-tunnel --port 9876
Note: npx does not work on Windows due to node-pty native addon file locking. Use npm install -g instead.
Install as a background service (recommended)
Use easy-service to run shell-cluster as a persistent background service that auto-starts on login. No admin/sudo required.
easy-service install shellcluster -- shellcluster start
This creates a native user-level service (LaunchAgent on macOS, systemd --user on Linux, Task Scheduler on Windows).
Install from local source
git clone git@github.com:billxc/shell-cluster.git
cd shell-cluster
npm install
npm link
Quick Start
Option A: Using Dev Tunnel (default)
1. Install
npm install -g shell-cluster
2. Login to Dev Tunnel (once per machine)
devtunnel user login
Use the same Microsoft account on all machines.
3. Start (each machine)
shellcluster start
On first run, if no config exists, a default config is created with hostname as node name. The daemon checks that devtunnel is installed and logged in before starting.
4. Open Dashboard (any machine)
shellcluster dashboard
Opens your browser — left sidebar shows all discovered peers, right side is a full xterm.js terminal. Click a peer to open a shell, manage multiple sessions in tabs. Use the Discover button to trigger an immediate peer refresh.
Option B: Using Tailscale
Tailscale runs in userspace-networking mode — no sudo, no TUN device, no impact on your normal network.
1. Install
npm install -g shell-cluster
brew install tailscale
2. Start Tailscale (once per machine)
tailscaled --tun=userspace-networking
tailscale login
Use the same Tailscale account on all machines.
3. Configure shell-cluster to use Tailscale
shellcluster config tunnel.backend tailscale
shellcluster config tunnel.port 9876
All machines in the same cluster should use the same port. If the port conflicts on a specific machine, encode a custom port in the Tailscale hostname:
tailscale set --hostname=my-mac-p9877
4. Start (each machine)
shellcluster start
5. Open Dashboard (any machine)
shellcluster dashboard
Run as a background service (recommended)
easy-service install shellcluster -- shellcluster start
The daemon runs in the background and auto-starts on login.
Architecture
- node-pty for cross-platform PTY management
- xterm-headless on server for full terminal state tracking per session
- SerializeAddon for perfect state replay on reconnect (replaces raw scrollback buffer)
- WebSocket
/raw endpoint: binary frames for PTY data, JSON text frames for control
- HTTP
/sessions endpoint: list active sessions
- Dashboard API (port 9000):
/api/peers, /api/refresh-peers, WebSocket proxy
Why Decentralized?
| Central server | None | Bastion host required |
| Key management | None (tunnel auth) | SSH keys on every machine |
| NAT traversal | Built-in via tunnel | Port forwarding / VPN |
| Discovery | Automatic | Manual inventory |
| Single point of failure | None | Bastion goes down = no access |
| Cross-platform | macOS + Windows + Linux | SSH server setup varies per OS |
Command Reference
shellcluster start | Start daemon (tunnel + shell server + discovery + dashboard API) |
shellcluster start --no-tunnel --port 9876 | Start in local mode (no tunnel) |
shellcluster start --dashboard-port 19000 | Use custom dashboard API port |
shellcluster register | Register this machine to the cluster |
shellcluster unregister | Remove this machine from the cluster |
shellcluster peers | List discovered peers |
shellcluster config | Show config path and all values |
shellcluster config <key> [value] | Get or set a config value (e.g. node.name) |
shellcluster dashboard | Open web dashboard |
-v / --verbose | Enable debug logging |
Configuration
| macOS | ~/Library/Application Support/shell-cluster/config.toml |
| Linux | ~/.config/shell-cluster/config.toml |
| Windows | %APPDATA%\shell-cluster\config.toml |
[node]
name = "my-macbook"
label = "shellcluster"
dashboard_port = 9000
[tunnel]
backend = "devtunnel"
expiration = "30d"
port = 0
[shell]
command = ""
Development
See archived/DESIGN.md for architecture details.
git clone git@github.com:billxc/shell-cluster.git
cd shell-cluster
npm install
node src/cli.js start --no-tunnel --port 9876
Service Management
Manage the background service installed via easy-service:
easy-service status shellcluster
easy-service stop shellcluster
easy-service start shellcluster
easy-service restart shellcluster
easy-service uninstall shellcluster
Roadmap
License
MIT