RemoteTTYs¶
Remotely access the terminal on your home Mac from a browser, no NAT traversal needed. Run Claude Code, Codex, vim, or any CLI tool and command directly.
Notice
This project is for personal use and experimentation only β do NOT deploy it in production environments. You are solely responsible for securing your own data and connections. When exposing the relay to the public internet, always use a reverse proxy with HTTPS (e.g. Caddy) to encrypt all traffic.
How It Works¶
graph LR
A["π₯ Local Machine<br/>rttys-agent<br/>(Go, no open ports)"] -- "Outbound WSS" --> B["βοΈ Remote Server<br/>rttys-relay<br/>(Node.js)"]
C["π Browser<br/>Web UI<br/>(ghostty-web)"] -- "HTTPS + WSS" --> B
- Agent runs on your local machines and connects outbound to the relay β no open ports, no NAT traversal needed
- Relay routes messages between agents and browsers without ever reading terminal content
- Web UI renders terminals using ghostty-web (Ghostty's VT100 parser compiled to WebAssembly)
Features¶
- Multiple machines in one dashboard with online/offline status
- Multiple terminal sessions per machine with tabs
- Scrollback replay on browser reconnect (1MB buffer per session)
- Multi-user authentication with JWT (httpOnly cookie + CSRF protection)
- Agent token management for machine authorization
- Ed25519 challenge-response for server identity verification
- Machine fingerprint binding to prevent token reuse across machines
- Audit logging (login, connections, session lifecycle)
- Single Go binary agent β zero dependencies on target machines
- Daemon mode with auto-reconnect (exponential backoff)
Security Model¶
The agent-to-server connection is protected by three layers:
- Token authentication at HTTP layer β the agent sends its token in the
X-TokenHTTP header during WebSocket upgrade. Invalid tokens are rejected before the WebSocket connection is established. - Ed25519 challenge-response β after the WebSocket is established, the server signs the agent's token with its Ed25519 private key and sends it as a challenge. The agent verifies the signature using the pre-configured server public key. Data is only sent after verification passes.
- Machine fingerprint binding β the agent reports a SHA-256 hash of the machine's unique ID. The server records it on first connection and rejects mismatches on subsequent connections, preventing token reuse on different machines.
Project Structure¶
remotettys/
βββ agent/ # Go β local agent binary
βββ packages/
β βββ relay/ # TypeScript β WebSocket relay + REST API
β βββ web/ # React + Vite β browser terminal UI
βββ Dockerfile # Multi-stage build for server
βββ docker-compose.yml # Production deployment
βββ Makefile # Build all components
βββ package.json # npm workspaces