The GoTTY terminal-over-WebSocket protocol

Files
README.md

gotty #

An OCaml codec for the protocol GoTTY speaks to its browser client: a terminal carried over a WebSocket.

GoTTY is a Go program by Iwasaki Yudai that shares a terminal over HTTP. This library was written from scratch in OCaml and contains no GoTTY code, vendored or translated. Where the wire format is in doubt, GoTTY's own webtty/message_types.go decides, along with the clients known to work with it.

Installation #

Install with opam:

$ opam install gotty

If opam cannot find the package, it may not yet be released in the public opam-repository. Add the overlay repository, then install it:

$ opam repo add samoht https://tangled.org/gazagnaire.org/opam-overlay.git
$ opam update
$ opam install gotty

Usage #

A message is one WebSocket text frame. Its first byte gives the message type and the rest of the frame is the payload. Use Gotty.of_string to decode a frame the server sent and Gotty.string_of_outgoing to encode one for it. The frame that opens a session comes from Gotty.init.

In the frame below, the first byte 1 is GoTTY's server Output type and the rest, aGVsbG8=, is the base64 encoding of hello:

let frame = "1aGVsbG8="

let () =
  match Gotty.of_string frame with
  | Ok (Gotty.Output bytes) -> assert (String.equal bytes "hello")
  | Ok _ -> failwith "expected terminal output"
  | Error e -> failwith e

Note that the two directions differ. The server sends terminal output in base64, while the client sends keystrokes raw. It is an easy detail to get wrong in a hand-written client.

Scope #

The library does no I/O. It turns frame bodies into values and back, and the caller owns the WebSocket, the terminal and the event loop. I use the same code from a CLI, from tests and from a unikernel. For the transport, pair it with a WebSocket client such as nox-websocket-eio.

Only the client side exists. You can talk to a GoTTY server with it, but you cannot build one.

Versions #

The message type bytes are the ones GoTTY v2 uses. In version 1 every type byte was one lower, so traffic from a v1 server decodes as nothing but Unknown messages. If a connection opens and the terminal stays blank, check the server version first.

License #

ISC. See LICENSE.md.