docs/01-architecture.md

01 — Architecture & Process Model

Architecture

text
1┌──────────────────────────────────────────────────────────────┐
2│ signaltty session server │
3│ (one process, per user) │
4│ │
5│ ┌────────────┐ ┌──────────────┐ ┌───────────────────────┐ │
6│ │ Workspace │ │ PTY manager │ │ Agent state engine │ │
7│ │ store │ │ (owns PTYs, │ │ (adapters, lifecycle, │ │
8│ │ (tabs, │ │ procs, │ │ attention, notifs) │ │
9│ │ panes, │ │ scrollback) │ │ │ │
10│ │ layouts) │ │ │ │ │ │
11│ └────────────┘ └──────────────┘ └───────────────────────┘ │
12│ ┌────────────┐ ┌──────────────┐ ┌───────────────────────┐ │
13│ │ Git meta │ │ Persistence │ │ IPC router │ │
14│ │ provider │ │ (snapshot + │ │ (Unix socket, pub/sub │ │
15│ │ (cached) │ │ restore) │ │ events, wait) │ │
16│ └────────────┘ └──────────────┘ └───────────────────────┘ │
17└──────────────┬───────────────────────────────┬───────────────┘
18 │ Unix socket │ Unix socket
19 │ $XDG_RUNTIME_DIR/signaltty/ │ (same API)
20 ▼ ▼
21┌──────────────────────────────┐ ┌───────────────────────────┐
22│ Native GUI (GTK4/libadwaita) │ │ CLI (`signaltty`) │
23│ - sidebar, splits, rings │ │ - workspaces/tabs/panes │
24│ - terminal widgets (VTE) │ │ - notify, wait, status │
25│ - desktop notifications │ │ - JSON output, automation │
26└──────────────────────────────┘ └───────────────────────────┘
27 ▲ ▲
28 │ same socket API │ same socket API
29┌──────────────┴───────────────┐ ┌────────────┴──────────────┐
30│ Agent hooks / plugins │ │ Future: GUI-less TUI, │
31│ (Claude/Codex/OpenCode/ │ │ remote bridge, plugins │
32│ Cursor shims calling CLI) │ │ (subprocess, via CLI/API) │
33└──────────────────────────────┘ └───────────────────────────┘

Process model

  • Session server (signaltty-server): exactly one per user by default (socket path is the singleton lock). Owns all PTYs, child processes, scrollback, workspace/tab/pane state, agent lifecycle, attention, persistence, IPC. No GUI code, no rendering. Must run headless (systemd user service or signaltty daemon).
  • GUI (signaltty-gui, Phase 3): a pure client. Renders terminal state streamed from the server, sends input, subscribes to events. Closing or crashing it never touches PTYs or child processes.
  • CLI (signaltty): a pure client of the same API. Used by humans and by agent hooks/plugins for notify, report-agent-session, wait, read, send-input.
  • Agent CLIs (codex, claude, opencode, cursor-agent, …): unmodified third-party binaries running as the foreground process of a pane's PTY. Zero wrapping of their workflows; integration happens via hooks/events/OSC/process info around them, never by reimplementing them.

Client/server rules

  1. All durable or process-owning state lives in the server.
  2. Clients hold no authoritative state; on connect they fetch a snapshot then subscribe to events.
  3. Every resource has an opaque stable ID (UUIDv4 string). Clients never derive identity from labels or indexes.
  4. Multiple clients may attach simultaneously (GUI + CLI, two GUIs). Terminal size arbitration is defined in 04; last-writer-wins for resizes, with the server clamping to sane bounds.
  5. The protocol is versioned (signaltty/1); unknown request/event fields are ignored for forward compatibility.

Event flow (attention path)

text
1agent emits signal ──► server classifies ──► state updated ──► event fanned out
2 (hook POST / OSC / (adapter layer, (lifecycle + (GUI ring +
3 CLI notify / explicit beats attention are sidebar +
4 exit / BEL) heuristic) independent) desktop notif)