roku-dev-studio-remote-server
v1.0.0
Published
Remote server for Roku Dev Studio - enables remote device control and telnet debug console streaming
Readme
Roku Dev Studio Remote Server
A lightweight Node.js server that runs on a computer at a remote location so the Roku Dev Studio desktop app can control Roku devices over the network. The server discovers Rokus on its own LAN and exposes an HTTP/WebSocket bridge that mirrors all Roku ECP (External Control Protocol) functionality, plus telnet relay and RALE / App Connector access.
Requirements
- Node.js 18 or higher
- Network access to Roku devices on the server's local network
- Port 4951 (default) reachable from wherever the Roku Dev Studio app is running
Install and run
Option A — From npm:
npm install -g roku-dev-studio-remote-server
roku-remote-server # default port 4951
roku-remote-server 4000 # or pick a portOption B — From source (full repo clone):
git clone https://github.com/paramount-engineering/roku-dev-studio.git
cd roku-dev-studio
npm install
npm run remote-server # root script — listens on 4951 by defaultInstallation as a Service (macOS)
To run the server automatically on boot:
1. Create a Launch Agent
A starter com.roku-dev-studio.remote-server.plist ships inside the package. Copy it to your LaunchAgents directory and edit the two paths inside (Node binary and the roku-remote-server.js location on this machine):
# Adjust the source path to wherever you installed the package
cp ./node_modules/roku-dev-studio-remote-server/com.roku-dev-studio.remote-server.plist \
~/Library/LaunchAgents/com.roku-dev-studio.remote-server.plistThe bundled plist looks like this — the inline comments call out which paths you need to replace before loading:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>com.roku-dev-studio.remote-server</string>
<key>ProgramArguments</key>
<array>
<!-- Path to your Node binary -->
<string>/usr/local/bin/node</string>
<!-- Path to the installed roku-remote-server.js -->
<string>/Users/YOUR_USERNAME/remote-server/roku-remote-server.js</string>
<string>4951</string>
</array>
<key>RunAtLoad</key>
<true/>
<key>KeepAlive</key>
<true/>
<key>StandardOutPath</key>
<string>/tmp/roku-remote.log</string>
<key>StandardErrorPath</key>
<string>/tmp/roku-remote.error.log</string>
</dict>
</plist>Rename the Label if you want a different reverse-DNS identifier — it just has to be unique on the box.
2. Load the Launch Agent
launchctl load ~/Library/LaunchAgents/com.roku-dev-studio.remote-server.plist3. Manage the Service
# Start
launchctl start com.roku-dev-studio.remote-server
# Stop
launchctl stop com.roku-dev-studio.remote-server
# Unload (disable)
launchctl unload ~/Library/LaunchAgents/com.roku-dev-studio.remote-server.plist
# Check status
launchctl list | grep roku4. View Logs
tail -f /tmp/roku-remote.log
tail -f /tmp/roku-remote.error.logAPI Documentation (Swagger)
The server includes interactive API documentation powered by Swagger/OpenAPI 3.0.
Access Swagger UI: http://localhost:4951/api-docs

The Swagger UI provides:
- Interactive API explorer (Health, Capabilities, Discovery, Device Info, Remote Control, RALE …)
- Request/response examples for every endpoint
- Try-it-out functionality for testing endpoints against a live Roku
- Complete parameter documentation generated from the OpenAPI 3.0 spec at
/api-docs/swagger.json
API Spec Endpoints
| Endpoint | Description |
|----------|-------------|
| /api-docs | Swagger UI interactive documentation |
| /api-docs/swagger.json | OpenAPI 3.0 specification (JSON) |
API Endpoints
Health & Discovery
| Endpoint | Method | Description |
|----------|--------|-------------|
| /health | GET | Server health check |
| /api-docs | GET | Swagger UI documentation |
| /devices | GET | Discover all Roku devices (full scan) |
| /devices/cached | GET | Get cached devices (fast) |
Device Control
All device endpoints use the pattern: /device/:ip/...
| Endpoint | Method | Description |
|----------|--------|-------------|
| /device/:ip/info | GET | Get device info |
| /device/:ip/keypress/:key | POST | Send key press (e.g., Up, Down, Select) |
| /device/:ip/launch/:appId | POST | Launch an app |
| /device/:ip/query/* | GET | Query endpoint (device-info, apps, etc.) |
| /device/:ip/post/* | POST | POST endpoint (sgrendezvous, fwbeacons, etc.) |
| /device/:ip/input-text | POST | Send text input |
| /device/:ip/deeplink | POST | Deep link to content |
| /device/:ip/icon/:appId | GET | Get app icon as base64 |
GET /device/:ip/query/* — short response cache: Successful JSON responses are cached per (device IP, query path) for 500 ms (same value as Roku Dev Studio's minimum Device performance sampling interval). Multiple Dev Studio clients polling the same Roku through this relay therefore share one ECP hit per path within that window. Failed responses are not cached.
Developer Features
| Endpoint | Method | Description |
|----------|--------|-------------|
| /device/:ip/sideload | POST | Sideload a channel package |
| /device/:ip/delete-sideload | POST | Delete sideloaded channel |
| /device/:ip/screenshot | POST | Take screenshot |
RALE (App Connector)
| Endpoint | Method | Description |
|----------|--------|-------------|
| /device/:ip/rale/wake | POST | Wake up TrackerTask |
| /device/:ip/rale/connect | POST | Connect to TrackerTask |
| /device/:ip/rale/command | POST | Send RALE command |
| /device/:ip/rale/disconnect | POST | Disconnect |
Example Usage
Replace <relay-host> with the address (hostname or IP) of the machine running the relay, and <roku-ip> with the device IP as seen on the relay's network.
Discover Devices
curl http://<relay-host>:4951/devicesSend Key Press
curl -X POST http://<relay-host>:4951/device/<roku-ip>/keypress/HomeLaunch an App
curl -X POST http://<relay-host>:4951/device/<roku-ip>/launch/<appId>Query Device Info
curl http://<relay-host>:4951/device/<roku-ip>/query/device-infoGet Installed Apps
curl http://<relay-host>:4951/device/<roku-ip>/query/appsTake Screenshot
curl -X POST http://<relay-host>:4951/device/<roku-ip>/screenshot \
-H "Content-Type: application/json" \
-d '{"password": "your-dev-password"}'Firewall Configuration
Ensure port 4951 (or your custom port) is open on the relay host's firewall.
macOS:
- System Settings → Network → Firewall → Options
- Add Node.js (or this server's binary) to allowed applications.
Or via Terminal:
sudo /usr/libexec/ApplicationFirewall/socketfilterfw --add /usr/local/bin/nodeLinux (ufw):
sudo ufw allow 4951/tcpWindows: allow Node.js (or the server binary) through Windows Defender Firewall via Settings → Privacy & security → Windows Security → Firewall & network protection.
Security Considerations
Network Security: This server should only be accessible from trusted networks. Consider using a VPN or SSH tunnel for remote access.
Authentication: The server currently does not require authentication. For production use, consider adding API key authentication.
Developer Passwords: Developer passwords are sent in API requests. Ensure the connection is secure (use HTTPS or VPN).
Troubleshooting
Server won't start
- Check if port 4951 is already in use:
lsof -i :4951 - Ensure Node.js is installed:
node --version
No devices found
- Ensure Roku devices are on the same network as the relay host
- Check the relay host's firewall settings (see Firewall Configuration)
- Try a fresh subnet scan by hitting the
/devicesendpoint (uncached) instead of/devices/cached
RALE connection fails
- Ensure the sideloaded app has TrackerTask integrated
- Check if the dev app is running on the Roku
- Verify the correct port (default: 49200)
License
Released under the MIT License. This package has no third-party runtime dependencies beyond roku-dev-studio-api.
