Message format
Every message is one JSON object. A request names a command int; include an
id when you want a correlated reply (reads), omit it for fire-and-forget (HID
writes).
hello frame with the protocol version, whether
auth is required, and (on remote.luau) which danger gates are enabled — so a
client can verify compatibility and capability with no round-trip.
Command surface
The full surface below is served byremote.luau (protocol
1.2). The minimal remote_access.lua (protocol 1.1)
serves only the HID / Screen / System / Input / Clipboard / Window rows plus
hello, ping, auth, lua.exec, subscribe, unsubscribe. Send
{ "t": "commands", "id": 1 } to introspect exactly what a given server exposes.
* gated off by default (see Authentication). † sandboxed to the script
directory and gated behind ALLOW_FILE.
system.window reads the active (foreground) window; the window.* commands
list, find, activate, move, and wait on windows. hid.move_smooth glides the
cursor to a point over a duration server-side (one call instead of streaming
hid.move frames); screen.capture_window captures a single window by handle or
title without computing a region.
screen.capture (protocol 1.1.0+) returns a display as a base64 PNG at native
resolution plus its geometry and the cursor position, and screen.displays
enumerates monitors with signed virtual-desktop origins — together the basis for
screenshot-driven, computer-use-style automation.
Async commands (net.*, dialog.*, window.wait*, hid.press,
hid.typewriter, hid.move_smooth) run in a coroutine on the server and reply
when the underlying call completes — always include an id for them.
Screen, Window, and Registry commands depend on platform support — Screen
and Window are limited or absent on Linux, Clipboard is Windows/macOS, and
Registry is Windows-only. See Platforms & limits.
Authentication
Auth is off by default (fine on localhost; risky on a LAN, since the server binds0.0.0.0). To require a token:
remote.luau— set the Auth token field in the script’s settings panel. It is compared over SHA-256 (so timing can’t leak its length or prefix) and is redacted fromui.get/ui.get_allso an authenticated client can’t read it back.remote_access.lua— setAUTH_TOKENat the top of the script before installing.
{ "t": "auth", "token": "..." } first; every
non-handshake command is refused with unauthenticated until it does.
Dangerous surfaces are gated off by default in remote.luau and must be enabled
by editing the file constants (they are deliberately not wire-flippable):
ALLOW_EXEC (shell exec, process kill), ALLOW_FILE (filesystem, TOML files),
ALLOW_REGISTRY (registry writes), and ALLOW_LUA_EXEC (arbitrary Lua via
lua.exec). A gated command returns disabled when its flag is off. Leave these
off unless you trust every client that can reach the port.
Performance
Measured on localhost (Windows host, release build):
Round-trips are sub-millisecond over localhost and a wired LAN — the transport
won’t be your bottleneck.