Skip to content

monoverse — Design Spec

An app halfway between a terminal emulator and a graphical server.

monoverse is a rich terminal: a local server runs a child app that paints a screen of styled text and true-pixel graphics over a single PTY-style byte stream and reads input events back. Clean-slate — no ANSI compatibility; apps target the monoverse protocol directly. The plain byte stream means it works over SSH, pipes, and multiplexers with zero special support.


Decisions

Dial Choice Consequence
Concept Rich terminal — text + inline graphics Not a window server; not a plain TTY
Backward compat None — clean-slate protocol No ANSI; new apps only
Interop No fallback; binary always Apps refuse to run without a server; flattening is mono-cat's job, so there's always one server-side speaker
Topology Local, like a terminal emulator Server local, app is a child process
Channel Single plain byte stream Survives SSH / pipes / multiplexers
Framing Length-prefixed binary packets with a type tag Compact, fast to parse
Primitive Rich cells — grid cell holds styled text or part of a graphic region Familiar grid mental model, graphics-capable
Pixels↔cells Pixels within cells Graphic reserves a cell rectangle, renders at true pixel res inside it
State model Immediate mode App paints each frame; server owns no widget tree
Redraw Dirty regions only; server retains last framebuffer App resends only changed cells/rects
Region identity None — re-declare the rect each frame State is the framebuffer; coords are the address. RGBA patches a sub-rect, JPEG re-sends the whole rect
Pixel format RGBA or JPEG, chosen per blit, no negotiation Server supports both, decodes to one uniform RGBA framebuffer
Input Structured event stream up the byte stream Key/mouse/click/resize read like stdin; no server-side widgets in v1
Surfaces Single live surface, no server scrollback One screen's framebuffer only; history is the app's job. Multiplexing is tmux's job
Mux seam Reserve a surface-id field, hardwired to 0 in v1 Forward-compat for multi-surface later, no v1 complexity
Geometry Live negotiation; app refuses to run without a server Server reports grid (cols×rows), cell px (w×h), HiDPI scale on init / change / request
Resize Server emits a resize event; app redraws Consistent with immediate mode
Language Zig Emulator + server + reference client
First app An interactive shell Dogfoods the entire stack

Protocol

A bidirectional byte stream of length-prefixed, type-tagged binary frames; every frame carries the v1 surface-id (0). PTY in raw mode so bytes pass unmangled.

App → server (paint). text-run (styled run at row,col); blit (pixels — RGBA or JPEG — into a cell-rect, addressing pixels within it); clear (rect); present (commit frame). The app emits paint ops only for cells/rects that changed; the server's retained framebuffer holds the rest. A blit's rect is its identity — re-blit a smaller rect to patch (RGBA), or the whole rect for JPEG.

Server → app (events). handshake, geometry (grid cols×rows, cell px w×h, HiDPI scale — sent on init, on change, and on request), key, mouse (move/button/click at a coordinate), scroll, focus. Events are low-level: a clicked button is just a click coordinate the app resolves against what it painted — no server-side widgets in v1.

The handshake is mandatory; with no server-side speaker (real GUI server or the headless mono-cat flattener), the app errors out. There is no serverless mode.

Reference shell

The first app and de-facto conformance test: reads command lines, renders styled output, blits an image inline when a command produces one, handles resize/mouse, and owns its own scrollback (the server has none — it repaints the viewport from its history buffer on scroll).


Rough milestones

  1. Protocol crate — frame types, encoder/decoder, handshake (Zig).
  2. Server v0 — open a window, run a child over a PTY, paint text frames, emit key/resize events.
  3. Graphics — graphic regions, pixel blit, dirty-region retention.
  4. Mouse — click/move events end-to-end.
  5. Reference shell — text + one inline-image command; owns its scrollback.
  6. mono-cat — headless pseudo-server: handshake + flatten frames to text.
  7. Conformance demo — a tiny app exercising every frame type.