Decision Records
Architecture Decision Records
TL;DR. Index of every decision that has closed off a design space
in phux. Format and Status: vocabulary defined in
../docs/CONVENTIONS.md. Read these when
you need to know why something is the way it is — the architecture
docs describe what the code is.
We write down decisions so future contributors (including future-us) can understand why the system is the way it is. Format follows Michael Nygard’s template.
Index
| # | Decision | Status |
|---|---|---|
| 0001 | Use Rust | Accepted |
| 0002 | Diff-based wire protocol, not VT byte replay | Superseded by 0013 |
| 0003 | Single server, many sessions | Accepted |
| 0004 | libghostty-vt is the canonical grid | Accepted |
| 0005 | Relationship to zmx and zmosh | Accepted |
| 0006 | Input event types re-export libghostty-vt’s atoms | Accepted (amended by 0024) |
| 0007 | Mosh-class transport semantics and satellite forward-compat | Accepted (forward-compat) |
| 0008 | Use libghostty-vt’s types directly; stop reimplementing them | Accepted (amended by 0024) |
| 0009 | phux vs coder/mux: positioning | Accepted |
| 0010 | phux is TUI-first, non-TUI not precluded; tmux control mode reserved as compat option | Accepted (forward-compat) |
| 0011 | phux-protocol and phux-core are independent; IdBridge is their only meeting point | Accepted |
| 0012 | Window layout is a binary split tree, not n-ary | Accepted |
| 0013 | Libghostty bytes on the wire; structured input remains | Accepted (supersedes 0002) |
| 0014 | Server-side Terminal placement: per-pane PaneActor on a LocalSet | Accepted |
| 0015 | Protocol layering: L1 substrate, L2 collections, L3 metadata | Accepted (L2 tier dissolved by 0030) |
| 0016 | TerminalId as the wire primary; PaneId is a consumer-side alias | Accepted |
| 0017 | The reference TUI is not protocol-privileged | Accepted (refines 0010) |
| 0018 | Lazy state synchronization is the wire’s long-arc shape | Accepted (builds on 0013) |
| 0019 | Multi-pane TUI rendering: layout persistence, wire shape, and chrome | Accepted |
| 0020 | Layered render: ratatui chrome over libghostty pane interiors | Accepted |
| 0021 | Control-plane commands and client-side selector resolution | Accepted (builds on 0017) |
| 0022 | phux as a tool for agents | Accepted |
| 0023 | Config UX: pure-config, defaults as a live base layer | Accepted (TUI-local, builds on 0017) |
| 0024 | The wire protocol owns its input atoms | Accepted (amends 0006, 0008) |
| 0025 | Browser web client over a WebSocket transport | Accepted (builds on 0017, 0024) |
| 0026 | Overlays: one theme, a real stack, and a single dispatch path | Accepted (builds on 0020) |
| 0027 | Terminals are referenced, not owned: views, links, and L3 tags | Accepted (builds on 0017, 0015) |
| 0028 | Runtime log control | Accepted (forward-compat, builds on 0024) |
| 0029 | One cursor authority and a repaint scheduler | Accepted (forward-compat, extends 0020) |
| 0030 | Engine-delegated wire and projection consumers | Accepted (supersedes the L2 tier of 0015) |
When to write an ADR
- Picking between viable approaches with long-term consequences.
- Closing off a design space (deciding against something).
- Anything you’d want to explain to a new contributor on day one.
When NOT to write an ADR
- Bug fixes.
- Refactors that don’t change behavior.
- Anything purely internal to a single function.
Template
# NNNN — Short title
Status: Proposed | Accepted | Deprecated | Superseded by ADR-NNNN
Date: YYYY-MM-DD
## Context
What is the situation that calls for a decision?
## Decision
What was decided.
## Rationale
Why this and not the alternatives.
## Tradeoffs
What we give up.
## Alternatives considered
Brief sketch of the other candidates and why they lost.