English | 中文
Terminal sessions that stay alive — pick up from any device.
ShellAnyWhere adds remote access to your local shell. A lightweight agent runs alongside your terminal, and a relay server bridges connections so you can reach it from anywhere. It pairs well with overlay networks like ZeroTier and Tailscale.
Unlike SSH, sessions survive disconnects — reconnect from any device and resume exactly where you left off. Local and remote screens stay in sync, with local terminal taking priority. No workflow changes required. Works with any terminal tool: Claude Code, Codex, vim, htop, or anything else.
How it works: the agent replaces your login shell via RC config, intercepts the PTY's input and output, and relays them through the server — giving any shell or tool real-time remote access with zero adaptation.
- Sessions stay alive — Close your laptop, open your phone, everything is still there
- Local and remote in sync — Terminal content syncs in real time; local terminal has priority
- Works with any tool — Claude Code, Codex, vim, htop... anything in a terminal, no adaptation needed
- Mobile access — Open a browser, no app needed
- Multi-device — Browser, SSH, or terminal client, all connect to the same live session
- Session sharing — Others can watch your terminal in real time
- Quick setup —
saw-server install+saw-shell install, that's it - Secure — TLS encryption, token auth, self-signed certs auto-generated
- Cross-platform — Windows, Linux, macOS; installs as user-level service (no root needed on Linux/macOS)
demo.mp4
macOS: brew install ejfkdev/tap/saw, or download from Releases for other platforms. Then install as a background service:
saw-server installDownload saw-shell and write the connection config into shell RC files:
saw-shell installThen open a new shell for the config to take effect. The new shell will automatically connect to the server.
The server auto-generates a token on first run. View it at:
- Linux/macOS:
cat ~/.config/ShellAnyWhere/token - Windows:
type %LOCALAPPDATA%\ShellAnyWhere\token
Web browser (including mobile) — open https://<server-ip>:18708, enter the token when prompted.
Terminal client:
saw-client --server <server-address> --token <token>SSH:
First, generate the SSH private key derived from your token:
saw-client ssh-key --server <server-address> --token <token>This saves a private key to ~/.ssh/saw_<host>-<port>_<id> and prints the usage command, e.g.:
ssh -i ~/.ssh/saw_my-server-18708_a1b2c3d4 -p 18708 my-serverSay your computer IP is 192.168.100.100 and saw-server runs on it. You open Ghostty (or any terminal) as usual, run claude or codex — everything works exactly the same. When you step away, open https://192.168.100.100:18708 on your phone, and you see the exact same terminal, fully interactive, ready to continue.
Prerequisites: Rust 1.85+, Node.js 20+
# Build web frontend first (required for server)
cd web && npm ci && npm run build && cd ..
# Build all binaries
cargo build --releaseBinaries are in target/release/: saw-server, saw-shell, saw-client
graph LR
Browser["Web Browser<br>(WebRTC → WSS fallback)"] --> Server["saw-server<br>(relay :18708)"]
SSH["SSH Client<br>(ssh -i)"] --> Server
Client["saw-client<br>(terminal)"] --> Server
Server <--> Shell["saw-shell<br>(agent · PTY)"]
- saw-server — Relay server. Accepts connections from agents and clients via WebSocket, SSH, and optionally WebRTC/QUIC. Embeds a web terminal UI.
- saw-shell — Shell agent. Runs on the remote machine, spawns a PTY, and connects to the server.
- saw-client — Local terminal client. Connects to the server to attach to a remote shell session.
saw-server # Start with defaults (0.0.0.0:18708)
saw-server -l 0.0.0.0:9000 # Custom listen port
saw-server -t my-secret-token # Set auth token
saw-server --no-ssh # Disable SSH
saw-server --cert-file /path/cert \
--key-file /path/key # Enable TLS
saw-server install # Install as system service
saw-server uninstall # Uninstall system servicesaw-server install registers saw-server as a background service that starts on boot and auto-restarts on crash:
| Platform | Mechanism | Privileges |
|---|---|---|
| Linux | systemd (user) | saw-server install |
| macOS | launchd (user) | saw-server install |
| Windows | Windows Service | Run as Administrator |
saw-shell -s my.server:18708 -t abc123 # Connect to server
saw-shell --io-compress # Enable lz4 compression
saw-shell --io-diff # Enable fullscreen diff optimization
saw-shell install -s my.server:18708 -t abc # Write config into shell RC files
saw-shell uninstall # Remove config from shell RC filessaw-client --server my.server:18708 --token abc123 # Connect
saw-client --list --token abc123 # List sessions
saw-client --observe --token abc123 # Read-only mode
saw-client ssh-key --server my.server:18708 --token abc123 # Derive SSH keyConfig priority: CLI args > SAW_ environment variables > config file > defaults
Config file locations:
- Linux/macOS:
~/.config/ShellAnyWhere/ - Logs: Linux
~/.local/state/ShellAnyWhere/, macOS~/Library/Logs/ShellAnyWhere/
Key environment variables:
| Variable | Description |
|---|---|
SAW_SERVER |
Server address (agent & client) |
SAW_TOKEN |
Authentication token |
SAW_LISTEN |
Server listen address |
SAW_SHELL_PATH |
Shell program path (agent) |
SAW_FOCUS_TRACKING |
Enable focus tracking |
SAW_IO_COMPRESS |
Enable lz4 output compression |
SAW_IO_DIFF |
Enable diff optimization |
SAW_CERT_FILE |
TLS certificate path |
SAW_KEY_FILE |
TLS private key path |
SAW_SSH_ENABLED |
Enable SSH protocol |
SAW_SSH_PASSWORD_AUTH |
Enable SSH password auth |
SAW_DATA_DIR |
Data directory |
See config.toml for the full configuration reference with all options and defaults.
├── crates/
│ ├── core/ # Shared library (config, crypto, protocol, transport)
│ ├── server/ # Relay server
│ ├── shell/ # Shell agent
│ └── client/ # Terminal client
├── web/ # Web frontend (React + Vite + WASM terminal)
├── config.toml # Default configuration (embedded in binary)
└── LICENSE # MPL-2.0
