JSPM

  • ESM via JSPM
  • ES Module Entrypoint
  • Export Map
  • Keywords
  • License
  • Repository URL
  • TypeScript Types
  • README
  • Created
  • Published
  • Downloads 5
  • Score
    100M100P100Q89417F
  • License MIT

Decentralized remote shell access via tunnels — Node.js server with node-pty and xterm-headless

Package Exports

  • shell-cluster
  • shell-cluster/src/index.js

This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (shell-cluster) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.

Readme

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

Platform Server (daemon) Client (dashboard) Shell
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.

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  # makes `shellcluster` available globally

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  # or see https://tailscale.com/download

2. Start Tailscale (once per machine)

# Start the daemon (no sudo needed)
tailscaled --tun=userspace-networking

# Login (in another terminal)
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  # this machine uses port 9877

4. Start (each machine)

shellcluster start

5. Open Dashboard (any machine)

shellcluster dashboard
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/version, /api/refresh-peers, WebSocket proxy

Why Decentralized?

Shell Cluster Traditional (SSH + bastion)
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

Command Description
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

OS Config path
macOS ~/Library/Application Support/shell-cluster/config.toml
Linux ~/.config/shell-cluster/config.toml
Windows %LOCALAPPDATA%\shell-cluster\config.toml
[node]
name = "my-macbook"        # Node name, shown in peers and dashboard
label = "shellcluster"     # Tunnel label — same label = same cluster
dashboard_port = 9000      # API + WebSocket proxy port

[tunnel]
backend = "devtunnel"      # Tunnel backend: "devtunnel" or "tailscale"
expiration = "30d"          # Tunnel auto-expiration (devtunnel only)
port = 0                   # Fixed port for shell server (0 = random, set for tailscale)

[shell]
command = ""               # Default shell (empty = auto-detect)

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

Running Tests

npm test            # all tests
npm run test:unit   # unit tests only
npm run test:e2e    # end-to-end tests only

Service Management

Manage the background service installed via easy-service:

easy-service status shellcluster    # Check if running
easy-service stop shellcluster      # Stop
easy-service start shellcluster     # Start again
easy-service restart shellcluster   # Restart
easy-service uninstall shellcluster # Remove the service

Roadmap

  • macOS + Linux support (PTY via node-pty)
  • Windows support (ConPTY via node-pty)
  • Local mode (no tunnel)
  • MS Dev Tunnel backend
  • Tailscale backend (userspace networking)
  • xterm-headless server-side state tracking
  • Session reconnect with full terminal state replay
  • Server-side health checks (HTTP ping every 10s)
  • Auto-register on first start
  • easy-service integration
  • E2E encryption
  • File transfer

License

MIT