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 orsignaltty 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 fornotify,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
- All durable or process-owning state lives in the server.
- Clients hold no authoritative state; on connect they fetch a snapshot then subscribe to events.
- Every resource has an opaque stable ID (UUIDv4 string). Clients never derive identity from labels or indexes.
- 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.
- The protocol is versioned (
signaltty/1); unknown request/event fields are ignored for forward compatibility.
Event flow (attention path)
text
| 1 | agent 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) |