Skynet modems#

Skynet is a virtual modem running on top of websockets. It is centralized, based on a server operated by the project’s author, Oliver S. (gollark). The project itself was started in 2018, and the current version as of March 22nd, 2021, is version 2.

The virtual modem is much like your typical ComputerCraft modem, except that:

  • It is inter-platform: computers can communicate across servers, and even with other devices on the Internet; however, note that from a security perspective, making your devices communicating with a server you own directly is better.

  • There is no arbitrary limit to the number of channels a host can open.

  • A channel identifier can either be a number or a string. Note that "5" and 5 are two different channels.

For joining the network, the client connects to the connect endpoint. As of February 26th, 2021, this URL is wss:// (previously wss://

The websocket is used for a request/response protocol with server push for events. Modem messages used in both parts of the protocols are used as a table containing the following fields:

  • channel: the channel identifier on which the message should be posted or is to be posted.

  • meta (optional): a metadata table using strings as keys and any CBOR-encodable values as values.

  • time (only in received messages): the time at which the message has been posted; set by the server to the UNIX timestamp in the UTC timezone when received.

  • data: the data of the message, as a CBOR-encodable value.

On the request/response part, the client sends a request as a CBOR-encoded sequence of two elements: the request type as a string, and the argument. The requests can be the following:

  • {"open", channel} where channel represents the channel identifier: this opens the channel, which will cause server pushes in case a message is sent by another host on the channel with that identifier.

  • {"close", channel} where channel represents the channel identifier: this closes the channel if it was previously opened by the client; if it wasn’t opened, this request does not do anything.

  • {"send", message} where message is the message table: this sends a message on a channel, regardless of if the channel was previously opened by the client or not.

If there was an error while decoding the message, the server answers with a CBOR-encoded sequence being {"error", "deserialization_failure", message}, where message is a detailed error message provided by the deserializer. Otherwise, the server does not answer.


As there is no websocket message identifier and no acknowledgment in case of a successfully sent message, in case the modem driver has sent several messages, it cannot determine which one is erroneous.

However, as the websocket is used in a connectionless fashion, the connection can still be used, but the messages sent to it must be used as datagrams. This makes the error messages actually useless, and only useful when testing a Skynet implementation manually, as shared logs.

When a message is sent on a channel that the client has opened, the server pushes a message to the client as a CBOR-encoded sequence containing the following: {"message", message}, where message is a message table.

Skynet has a special channel, named "*", which corresponds to the wildcard channel. This channel can be used as a normal channel to send messages to and listening to messages on, except that when listening to the wildcard channel, all messages are received.

See Lua-CBOR, the Skynet source (including a Rust implementation of the server and a Lua implementation of the client) and Gollark's description of Skynet for reference. For experimenting, Gollark has made a web client for Skynet.