WebSocket protocol
A running Saiko listens on the loopback address. This is everything a client needs to talk to it.
Finding the server
When Saiko starts it writes control.json into its data folder and removes it when it exits.
%APPDATA%\io.saiko.workspace\control.json{
"host": "127.0.0.1",
"port": 7390,
"token": "9f1c0b6e5a47d2c8e3b1a0f49d7c25e6a8b3d1f04c92e7ab",
"pid": 20388
}portis7390when that is free, and another free port when it is not. Always read it from the file.tokenis new every time Saiko starts. Read the file again after a restart.pidis Saiko's own process id, handy for checking it is still alive.
If the file is missing, or nothing answers on its port, Saiko is not running.
Connecting
Open a plain WebSocket to ws://127.0.0.1:<port>/. There is no TLS and no subprotocol. Frames are UTF-8 text, one JSON object each.
Requests and replies
Every request carries the token. The id is optional, can be any JSON value, and is copied into the reply so you can match them up.
{"token":"9f1c…","id":1,"cmd":"clients"}{"id":1,"ok":true,"result":[{"pid":14212,"name":"Builderman"}]}
{"id":1,"ok":false,"error":"bad token"}Requests on one connection are answered in order, one at a time. A slow inject holds up the requests behind it on that connection, so open a second connection if you need to keep asking things meanwhile. The error messages are the same ones the command line prints.
clients
{"token":"…","cmd":"clients"}The result is the array --get-clients prints: pid for every Roblox client, and name for those with a module that has reported its player.
inject
{"token":"…","cmd":"inject","pid":14212}pid is optional. The reply comes after the module has loaded and had up to twenty seconds to connect.
{"ok":true,"result":{"injected":[{"pid":14212,"connected":true}]}}execute
{"token":"…","cmd":"execute","script":"print('hi')","pid":14212}script is required. pid is optional, and without it every client with a module gets the script. The reply comes once each module has accepted or refused it.
{"ok":true,"result":{"sent":[14212]}}ping
{"token":"…","cmd":"ping"}
{"ok":true,"result":"pong"}Checks that the token is accepted and the server is listening, without touching any client. Ordinary WebSocket pings are answered too.
Limits
Size
A message can be up to 16 MiB, which is more than any script you are likely to send. A larger one closes the connection.
Authentication
A request with a missing or wrong token gets bad token and nothing is done. The connection stays open, so a typo does not cost a reconnect.
Unknown commands
A cmd that does not exist gets an error naming it. Text that is not JSON gets not valid JSON.