{"id":49559086,"url":"https://github.com/ejfkdev/shellanywhere","last_synced_at":"2026-05-03T07:02:55.941Z","repository":{"id":355264483,"uuid":"1226602025","full_name":"ejfkdev/ShellAnyWhere","owner":"ejfkdev","description":"Secure remote shell access from any browser — WebRTC/WSS transport, E2EE, multi-session, mobile-friendly web terminal","archived":false,"fork":false,"pushed_at":"2026-05-02T18:35:29.000Z","size":24736,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-05-02T19:09:46.456Z","etag":null,"topics":["e2ee","react","remote-shell","rust","terminal","web-terminal","webrtc","websocket"],"latest_commit_sha":null,"homepage":null,"language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mpl-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ejfkdev.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-05-01T15:55:12.000Z","updated_at":"2026-05-02T18:29:56.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/ejfkdev/ShellAnyWhere","commit_stats":null,"previous_names":["ejfkdev/shellanywhere"],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/ejfkdev/ShellAnyWhere","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ejfkdev%2FShellAnyWhere","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ejfkdev%2FShellAnyWhere/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ejfkdev%2FShellAnyWhere/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ejfkdev%2FShellAnyWhere/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ejfkdev","download_url":"https://codeload.github.com/ejfkdev/ShellAnyWhere/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ejfkdev%2FShellAnyWhere/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32560914,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-03T06:36:36.687Z","status":"ssl_error","status_checked_at":"2026-05-03T06:36:09.306Z","response_time":103,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["e2ee","react","remote-shell","rust","terminal","web-terminal","webrtc","websocket"],"created_at":"2026-05-03T07:02:51.906Z","updated_at":"2026-05-03T07:02:55.919Z","avatar_url":"https://github.com/ejfkdev.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"# ShellAnyWhere\n\nEnglish | [中文](README_CN.md)\n\nTerminal sessions that stay alive — pick up from any device.\n\nShellAnyWhere 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.\n\nUnlike 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.\n\nHow 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.\n\n## Features\n\n- **Sessions stay alive** — Close your laptop, open your phone, everything is still there\n- **Local and remote in sync** — Terminal content syncs in real time; local terminal has priority\n- **Works with any tool** — Claude Code, Codex, vim, htop... anything in a terminal, no adaptation needed\n- **Mobile access** — Open a browser, no app needed\n- **Multi-device** — Browser, SSH, or terminal client, all connect to the same live session\n- **Session sharing** — Others can watch your terminal in real time\n- **Quick setup** — `saw-server install` + `saw-shell install`, that's it\n- **Secure** — TLS encryption, token auth, self-signed certs auto-generated\n- **Cross-platform** — Windows, Linux, macOS; installs as user-level service (no root needed on Linux/macOS)\n\n## Demo\n\n![screenshot](https://raw.githubusercontent.com/ejfkdev/ShellAnyWhere/refs/heads/main/docs/file/demo.jpg)\n\nhttps://github.com/user-attachments/assets/197e9688-e472-439b-a551-760cf281519b\n\n## Quick Start\n\n### 1. Install server\n\nDownload the latest release for your platform from [Releases](https://github.com/ejfkdev/ShellAnyWhere/releases), then install as a background service:\n\n```bash\nsaw-server install          # All platforms: no root/admin needed\n```\n\n### 2. Configure the shell agent\n\nDownload `saw-shell` and write the connection config into shell RC files:\n\n```bash\nsaw-shell install\n```\n\nThen **open a new shell** for the config to take effect. The new shell will automatically connect to the server.\n\n### 3. Access the remote shell\n\nThe server auto-generates a token on first run. View it at:\n\n- Linux/macOS: `cat ~/.config/ShellAnyWhere/token`\n- Windows: `type %LOCALAPPDATA%\\ShellAnyWhere\\token`\n\n**Web browser** (including mobile) — open `https://\u003cserver-ip\u003e:18708`, enter the token when prompted.\n\n**Terminal client:**\n```bash\nsaw-client --server \u003cserver-address\u003e --token \u003ctoken\u003e\n```\n\n**SSH:**\n\nFirst, generate the SSH private key derived from your token:\n```bash\nsaw-client ssh-key --server \u003cserver-address\u003e --token \u003ctoken\u003e\n```\n\nThis saves a private key to `~/.ssh/saw_\u003chost\u003e-\u003cport\u003e_\u003cid\u003e` and prints the usage command, e.g.:\n```bash\nssh -i ~/.ssh/saw_my-server-18708_a1b2c3d4 -p 18708 my-server\n```\n\n### What you get\n\nSay 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.\n\n## Build from Source\n\nPrerequisites: Rust 1.85+, Node.js 20+\n\n```bash\n# Build web frontend first (required for server)\ncd web \u0026\u0026 npm ci \u0026\u0026 npm run build \u0026\u0026 cd ..\n\n# Build all binaries\ncargo build --release\n```\n\nBinaries are in `target/release/`: `saw-server`, `saw-shell`, `saw-client`\n\n## Architecture\n\n```mermaid\ngraph LR\n    Browser[\"Web Browser\u003cbr\u003e(WebRTC → WSS fallback)\"] --\u003e Server[\"saw-server\u003cbr\u003e(relay :18708)\"]\n    SSH[\"SSH Client\u003cbr\u003e(ssh -i)\"] --\u003e Server\n    Client[\"saw-client\u003cbr\u003e(terminal)\"] --\u003e Server\n    Server \u003c--\u003e Shell[\"saw-shell\u003cbr\u003e(agent · PTY)\"]\n```\n\n- **saw-server** — Relay server. Accepts connections from agents and clients via WebSocket, SSH, and optionally WebRTC/QUIC. Embeds a web terminal UI.\n- **saw-shell** — Shell agent. Runs on the remote machine, spawns a PTY, and connects to the server.\n- **saw-client** — Local terminal client. Connects to the server to attach to a remote shell session.\n\n## Components\n\n### saw-server\n\n```bash\nsaw-server                                    # Start with defaults (0.0.0.0:18708)\nsaw-server -l 0.0.0.0:9000                   # Custom listen port\nsaw-server -t my-secret-token                  # Set auth token\nsaw-server --no-ssh                            # Disable SSH\nsaw-server --cert-file /path/cert \\\n            --key-file /path/key               # Enable TLS\nsaw-server install                             # Install as system service\nsaw-server uninstall                           # Uninstall system service\n```\n\n#### Service install\n\n`saw-server install` registers saw-server as a background service that starts on boot and auto-restarts on crash:\n\n| Platform | Mechanism | Privileges |\n|----------|-----------|------------|\n| Linux | systemd (user) | `saw-server install` |\n| macOS | launchd (user) | `saw-server install` |\n| Windows | Windows Service | Run as Administrator |\n\n### saw-shell\n\n```bash\nsaw-shell -s my.server:18708 -t abc123         # Connect to server\nsaw-shell --io-compress                        # Enable lz4 compression\nsaw-shell --io-diff                            # Enable fullscreen diff optimization\nsaw-shell install -s my.server:18708 -t abc      # Write config into shell RC files\nsaw-shell uninstall                               # Remove config from shell RC files\n```\n\n### saw-client\n\n```bash\nsaw-client --server my.server:18708 --token abc123   # Connect\nsaw-client --list --token abc123                      # List sessions\nsaw-client --observe --token abc123                   # Read-only mode\nsaw-client ssh-key --server my.server:18708 --token abc123  # Derive SSH key\n```\n\n## Configuration\n\nConfig priority: **CLI args \u003e SAW\\_ environment variables \u003e config file \u003e defaults**\n\nConfig file locations:\n- Linux/macOS: `~/.config/ShellAnyWhere/`\n- Logs: Linux `~/.local/state/ShellAnyWhere/`, macOS `~/Library/Logs/ShellAnyWhere/`\n\nKey environment variables:\n\n| Variable | Description |\n|----------|-------------|\n| `SAW_SERVER` | Server address (agent \u0026 client) |\n| `SAW_TOKEN` | Authentication token |\n| `SAW_LISTEN` | Server listen address |\n| `SAW_SHELL_PATH` | Shell program path (agent) |\n| `SAW_FOCUS_TRACKING` | Enable focus tracking |\n| `SAW_IO_COMPRESS` | Enable lz4 output compression |\n| `SAW_IO_DIFF` | Enable diff optimization |\n| `SAW_CERT_FILE` | TLS certificate path |\n| `SAW_KEY_FILE` | TLS private key path |\n| `SAW_SSH_ENABLED` | Enable SSH protocol |\n| `SAW_SSH_PASSWORD_AUTH` | Enable SSH password auth |\n| `SAW_DATA_DIR` | Data directory |\n\nSee [config.toml](config.toml) for the full configuration reference with all options and defaults.\n\n## Project Structure\n\n```\n├── crates/\n│   ├── core/       # Shared library (config, crypto, protocol, transport)\n│   ├── server/     # Relay server\n│   ├── shell/      # Shell agent\n│   └── client/     # Terminal client\n├── web/            # Web frontend (React + Vite + WASM terminal)\n├── config.toml     # Default configuration (embedded in binary)\n└── LICENSE         # MPL-2.0\n```\n\n## License\n\n[MPL-2.0](LICENSE)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fejfkdev%2Fshellanywhere","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fejfkdev%2Fshellanywhere","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fejfkdev%2Fshellanywhere/lists"}