Remotely view and control your own PC from a browser (desktop or phone): live screen view, mouse/keyboard/touch input, shell commands, and file browsing/transfer, all over an encrypted, NAT-traversing WebRTC connection gated by a shared pairing token.
server/— signaling relay (Node.js). Relays WebRTC handshake messages between the agent and an authenticated client. Never sees your screen, input, command output, or files.agent/— runs on the PC you want to control. Registers with the signaling server; streams the screen, injects mouse/keyboard input, executes shell commands, and serves file listing/download/upload, all over WebRTC DataChannels.client/— a web page (works on desktop and mobile browsers) you open to connect and control the PC. Served by the signaling server, or openclient/index.htmldirectly for local testing.
-
Generate a pairing token (do this once):
node -e "console.log(require('crypto').randomBytes(32).toString('hex'))" -
Server: copy
server/.env.exampletoserver/.env, setPAIRING_TOKENto the value you generated.cd server npm install npm start -
Agent: copy
agent/.env.exampletoagent/.env. SetPAIRING_TOKENto the same value as the server,DEVICE_IDto any name you choose, andSIGNALING_URLto your server's WebSocket URL (ws://localhost:8080for local testing,wss://your-deployed-hostonce deployed).cd agent npm install npm start -
Client: open
http://localhost:8080(served by the signaling server) in a browser, enter the same Device ID and pairing token, click Connect. Once status shows "Connected." you can:- see the live screen and control the mouse/keyboard by interacting with the canvas (touch works too, for phones/tablets)
- run shell commands (the working directory persists across commands,
like a real terminal —
cdactually sticks) - browse files: enter a path and click List, click a folder to navigate into it, click Download on a file, or pick a local file and click Upload to send it to the currently-listed folder
To control from a different device on the same network, use the PC's LAN IP instead of
localhost(find it withipconfig), e.g.http://192.168.1.10:8080. Note: some browser APIs (likecrypto.randomUUID) are restricted to "secure contexts" (HTTPS orlocalhost) — the client already falls back for this, but keep it in mind if you add features that touch other secure-context-only APIs.
- Keep
PAIRING_TOKENsecret — anyone with it and network access to the signaling server can execute commands on your PC. Rotate it by changing both.envfiles and restarting the agent. - Only the signaling handshake goes through the relay server; the actual command/screen/input/file traffic goes over an encrypted (DTLS) WebRTC DataChannel, direct between client and agent where possible.
- Before exposing the signaling server to the internet, deploy it behind
TLS (
wss://) — most hosts (Fly.io, Render, etc.) provide this automatically.
Any small Node.js host works (Fly.io, Render free tier, a cheap VPS). Set
PORT and PAIRING_TOKEN as environment variables there; don't commit
.env.
- Auto-start: scripts to launch the agent silently at Windows logon are
ready in
agent/scripts/(install-autostart.ps1/uninstall-autostart.ps1) but not yet installed — run the install script when you're ready to stop starting the agent manually. - TURN server: STUN-only NAT traversal will fail on some networks
(symmetric NAT is common on mobile/some routers). If the client can't
connect from outside your home network, add a TURN server (self-hosted
coturnor a hosted free tier) and include it in bothagent/src/webrtc.js'sICE_SERVERSandclient/src/app.js'siceServers. - Hardening: token rotation flow, session/connection expiry, and a review of logging are not yet done — fine for personal LAN use, worth doing before relying on this over the open internet long-term.
- File download is buffered entirely in browser memory before saving (fine up to a couple hundred MB; very large files would need streaming to disk instead).