Docs menu

Wire: sockets and framing

How TermSurf bytes move: local Unix domain sockets, length-prefixed protobuf frames, and the TERMSURF_* env clients use to find the host.

What this is

TermSurf IPC is Unix domain socket traffic on your machine—not a public TCP server and not free-form JSON per tool. The payload of each frame is a protobuf TermSurfMessage. Field tables live on Messages; this page is only transport and discovery.

Roles on the wire

  client (ahweb / TermSurf app)
        │  connect(TERMSURF_SOCKET)
        │  framed TermSurfMessage
        ▼
     host (ahterm)
        │  --ipc-socket / --listen-socket (spawned helper)
        ▼
  engine helper (ah-chromiumd)
  • Client — connects to the host socket; does not embed Chromium. Examples: ahweb, ahcalc.
  • Host — owns panes and the client-facing socket path; routes work to engine helpers and composites surfaces.
  • Engine helper — product path is Chromium (ah-chromiumd). Connects to the host with --ipc-socket=; may also --listen-socket= for additional local IPC clients. Same framed protobuf language.

Connect

Inside Astrohacker TermSurf, the host injects environment for pane clients:

  1. Read TERMSURF_SOCKET — a filesystem path to a Unix domain socket. If it is unset, a client such as ahweb cannot open IPC (it is not running inside TermSurf).
  2. UnixStream::connect (or language equivalent) to that path.
  3. Read TERMSURF_PANE_ID so Hello, overlays, and queries name the correct pane.

The host listens; the client connects. There is no public listen port for this protocol. Historical default path shapes under the host’s temp/XDG layout may appear in implementation comments (for example a gui.sock under a termsurf directory)—always prefer the live TERMSURF_SOCKET value the host set for your process.

Frame format

4-byte little-endian unsigned length (u32 LE) of the following payload, then a protobuf-encoded TermSurfMessage.

Write path (conceptual):

  1. Build a TermSurfMessage and serialize it (e.g. prost encode_to_vec).
  2. Let N be the payload length in bytes. Write N as a little-endian u32 (4 bytes).
  3. Write the N payload bytes.

Read path (conceptual):

  1. Accumulate bytes until at least 4 are available.
  2. Parse the first 4 bytes as little-endian N.
  3. Wait until 4 + N bytes are buffered; decode bytes [4, 4+N) as TermSurfMessage; drain that frame and continue.

The same framing is used on client↔host and host↔engine links in the shipped Rust helpers. Do not send bare protobuf without the length prefix.

Protocol environment

Process environment used for protocol discovery and optional traces. Packaging and release knobs (ASTROHACKER_TERMINAL_*) are not the TermSurf wire surface—see monorepo docs/environment.md for the full product taxonomy.

Primary (required for clients)

VariableRole
TERMSURF_SOCKETFilesystem path of the host Unix domain socket. Clients connect here (e.g. ahweb). Unset outside TermSurf → client cannot open IPC.
TERMSURF_PANE_IDPane id for this client process. Identifies which host region the client is bound to (Hello, overlays, queries).

Secondary (optional debug / harness)

Not required to open a socket or complete Hello.

VariableRole
TERMSURF_ENGINE_STARTUP_TRACEEnable engine warmup/startup trace logging.
TERMSURF_ENGINE_STARTUP_TRACE_FILEOptional file path for engine startup traces.
TERMSURF_BROWSER_STARTUP_TRACEHost browser-startup trace.
TERMSURF_GEOMETRY_TRACEGeometry harness / layout traces.
TERMSURF_GEOMETRY_SCENARIONamed geometry scenario for harnesses.
TERMSURF_DEVTOOLS_RESERVATION_TIMEOUT_MSDevTools reservation timeout (milliseconds).
TERMSURF_PDF_INPUT_TRACEPDF input trace toggle.
TERMSURF_PDF_INPUT_TRACE_FILEOptional file for PDF input traces.
TERMSURF_WEBTUI_STATE_TRACE_FILEWebTUI debug state dump path.

Generated protobuf symbol names such as TERMSURF__TERM_SURF_MESSAGE__MSG_* are API constants, not user environment variables.

Lifecycle notes

  • Clients fail closed when TERMSURF_SOCKET is missing.
  • Engine helpers that lose the host GUI connection may exit (EOF on the GUI socket is treated as fatal for the helper in the shipped Chromium path).
  • Stale socket files from a crashed process are removed by listeners before bind when the helper owns a listen path.

Minimal sequence

  1. Host starts a pane client with TERMSURF_SOCKET and TERMSURF_PANE_ID set.
  2. Client connects to the socket.
  3. Client writes a framed HelloRequest (see Messages for fields).
  4. Host replies with a framed HelloReply. Later, BrowserReady may signal a browser connection for the pane.

Payload catalog

Every frame payload is a TermSurfMessage variant. Full field reference: TermSurf messages. Concepts: protocol overview.

Source

  • rust/ahweb/src/ipc.rs — client framing and TERMSURF_SOCKET
  • rust/ah-chromiumd/src/ipc.rs — engine length-prefix write/read loops
  • rust/proto/test-socket/ — small language probes for the same wire shape
  • Monorepo docs/environment.md — full env taxonomy (protocol vs packaging)