waos-dev-protocol 0.2.0

What cargo waos and a running WaOS say to each other: the messages of one run, their frames, and the Unix socket that carries them.
Documentation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# waos-dev-protocol

What `cargo waos` and a running WaOS say to each other: the messages of one run, how they are framed on a stream, and the Unix socket on this machine that carries them. The connection is the run (the design's decision 29): `cargo waos run` connects, sends the program's id and its component, and reads what it writes until it ends; closing the connection, by Ctrl-C or the terminal closing, stops the program, and a later run of the same id replaces it. A run is the program its id names (decision 11 of `docs/proposals/2026-10-23-permissions.md`), which WaOS runs with that program's settings and folders, installed or not. There is no stop message. `waos open <file> --program <id>` connects the same way and sends one `Open`, files to open with the program the id names, which WaOS answers `Opened` or `Refused` (decision 3 of `docs/proposals/2026-10-29-opening.md`, until programs register what opens them). `cargo waos screenshot` connects the same way and sends one `Screenshot` of the program an id names, which WaOS answers `Screenshots`, a `WindowPicture` for each of its windows, numbered from 1 in the order they opened, with the title the program gave it, its size in physical pixels, whether it is in sight, and its last picture as a PNG, none before it showed one; `cargo waos tap`, `type`, `key` and `scroll` send one `Input` to a window of the program, by its number, a `Tap` or a `Scroll` at a point in the window's physical pixels from its top-left, `Text` to commit into what it edits, or a `Key` or a chord by name (`cmd+s`), which WaOS answers `InputDone` once the window shows its next picture, saying whether a new one came. Both are answered `Unreached` and why while no run of `cargo waos run` runs the program, for a program the library opened among them, which no tool reads or drives (the design's decision 60), and for a window the program does not have, a point outside the window, text with nothing in the window edited, and a chord naming no key. The socket is in the user's own folder, so the system's file permissions decide who may connect (decision 30); the network transport for phones carries the same messages.

- **Takes:** a program's id, its `waos-package` `ProgramId`, and its component, from `cargo waos`; a program's id and files to open with it, from `waos open`; a program's id with a screenshot or an input to one of its windows, from `cargo waos`; what the program writes and how it ends, its windows' pictures and what came of an input, from the WaOS app; a `tokio` runtime, on both sides.
- **Provides:** `ToWaOS` and `FromWaOS`, the messages, with `Input`, `WindowPicture` and `Unreached`; `Connection`, which agrees on the protocol's number with the other side first (`PROTOCOL`, `agree_on_protocol`), then sends and receives them as frames over a stream, split into a half that sends and one that receives when one task writes a program's output while another watches for the close; `socket_path`, where a WaOS listens on this machine; `Listener`, the WaOS side's end, which makes the socket's folder, replaces a socket file a WaOS that died left, refuses to start while another WaOS answers, and removes its file when dropped.
- **Used by:** `waos-cli`, for `cargo waos run`, `screenshot`, `tap`, `type`, `key` and `scroll`, and the WaOS app, which serves them and is `waos open`.

The socket's path: `~/Library/Application Support/WaOS/dev.sock` on Apple's systems; `$XDG_RUNTIME_DIR/waos/dev.sock` elsewhere, or `~/.local/share/waos/dev.sock` without one. The folder is made for the user alone (`0700`), and the socket file too (`0600`). macOS allows a socket path 103 bytes long, so a user's name may be 50 bytes.

A frame: a four-byte little-endian count of the message's bytes, then the message as `postcard` encodes it, a component, a program's output and a window's PNG as strings of bytes (`serde_bytes`), which postcard writes as it writes a `Vec<u8>`, so the encoding is the one of a sequence of bytes, read in one copy. Either side refuses a frame over 256 MiB, the receiver on the count alone, before it allocates anything: a component is megabytes, a debug build tens of them, and a count beyond that is a stream that is not ours. After a frame cut short or refused, the connection is done. A variant's place and a field's place is its encoding, so a change to a message adds at the end, and anything else raises the protocol's number; the screenshot and the input, added at the end, raised it to 3 all the same, so a WaOS of an earlier build refuses a `cargo waos` that may send them by number rather than at a message it cannot read. A message's `Debug` leaves out the text typed into a program, which may be a password, and writes a component's and a PNG's sizes rather than their bytes.

The first frame each way is that number, `PROTOCOL`, outside the messages' encoding: a count of four, then the number little-endian, the one shape every build reads. Each side sends its own and reads the other's before anything else; when they differ, each ends the connection with an error naming both numbers, which `cargo waos` prints, so a `cargo waos` and a WaOS of different builds find out rather than misread each other.

On Windows the crate carries the messages and `Connection`, but no transport: its named pipe is step 11.