Decision Records

Project record

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

#DecisionStatus
0001Use RustAccepted
0002Diff-based wire protocol, not VT byte replaySuperseded by 0013
0003Single server, many sessionsAccepted
0004libghostty-vt is the canonical gridAccepted
0005Relationship to zmx and zmoshAccepted
0006Input event types re-export libghostty-vt’s atomsAccepted (amended by 0024)
0007Mosh-class transport semantics and satellite forward-compatAccepted (forward-compat)
0008Use libghostty-vt’s types directly; stop reimplementing themAccepted (amended by 0024)
0009phux vs coder/mux: positioningAccepted
0010phux is TUI-first, non-TUI not precluded; tmux control mode reserved as compat optionAccepted (forward-compat)
0011phux-protocol and phux-core are independent; IdBridge is their only meeting pointAccepted
0012Window layout is a binary split tree, not n-aryAccepted
0013Libghostty bytes on the wire; structured input remainsAccepted (supersedes 0002)
0014Server-side Terminal placement: per-pane PaneActor on a LocalSetAccepted
0015Protocol layering: L1 substrate, L2 collections, L3 metadataAccepted (L2 tier dissolved by 0030)
0016TerminalId as the wire primary; PaneId is a consumer-side aliasAccepted
0017The reference TUI is not protocol-privilegedAccepted (refines 0010)
0018Lazy state synchronization is the wire’s long-arc shapeAccepted (builds on 0013)
0019Multi-pane TUI rendering: layout persistence, wire shape, and chromeAccepted
0020Layered render: ratatui chrome over libghostty pane interiorsAccepted
0021Control-plane commands and client-side selector resolutionAccepted (builds on 0017)
0022phux as a tool for agentsAccepted
0023Config UX: pure-config, defaults as a live base layerAccepted (TUI-local, builds on 0017)
0024The wire protocol owns its input atomsAccepted (amends 0006, 0008)
0025Browser web client over a WebSocket transportAccepted (builds on 0017, 0024)
0026Overlays: one theme, a real stack, and a single dispatch pathAccepted (builds on 0020)
0027Terminals are referenced, not owned: views, links, and L3 tagsAccepted (builds on 0017, 0015)
0028Runtime log controlAccepted (forward-compat, builds on 0024)
0029One cursor authority and a repaint schedulerAccepted (forward-compat, extends 0020)
0030Engine-delegated wire and projection consumersAccepted (supersedes the L2 tier of 0015)
0031Remote-consumer authentication and encryption (no SSH tunnel)Proposed
0032Graceful server upgrade (sessions survive a binary update)Accepted
0033Input authority leases and process signals (“take the wheel + kill”)Accepted
0034Kitty graphics / image passthrough through the cell rendererProposed
0035Agent-asked event: a pending human-answerable question on the wireAccepted
0036Agent-asked detection sourcesAccepted
0037Overlay-network reachability for remote self-host consumersAccepted (forward-compat, builds on 0007, 0031)
0038Hub-to-satellite authenticationAccepted (builds on 0031)
0039Layered config: an ordered extends stack with explicit array appendAccepted
0040Agent identity and lifecycle are an L3 metadata recordAccepted
0041Managed plugin installs: snapshot fetches, system tools, one lockfileAccepted
0042Launch executor: a CLI verb that spawns an integration templateAccepted
0043State-diff output mode and loss-tolerant reference advanceAccepted
0044Dedicated input lane: route input off the single runtime threadAccepted
0045Client-side copy-mode over the consumer’s own engineAccepted (builds on 0030, supersedes the abi epic’s server-side selection frames)
0046The server derives agent state; detection is level-triggeredAccepted (extends 0040; implements 0029’s repaint accumulator)
0047CI metrics recorded to an orphan ci-metrics branchAccepted
0048Drag-to-resize panes and default outer-terminal mouse captureAccepted
0049Client-local focus and advisory agent attentionAccepted (reaffirms 0019)
0050Explicit spawn ownership, client-owned placementAccepted
0051Outbound dial-out (connector) transport modeAccepted (walks through 0037’s deferred door; builds on 0031, 0038)
0052Connector route identity, registration, and config surfaceAccepted (settles 0051 open questions 1/4/5)
0053Acknowledged idempotent input batchesAccepted (builds on 0021, 0024, and 0044)
0054Worktree-bound sessions by name conventionAccepted (composes existing verbs; adds no server state, consistent with 0009)
0055Always-on server and ssh-bootstrapped enrollmentProposed (makes 0031/0037 usable; mirrors 0038’s pin posture)
0056Cross-session Terminal moveAccepted (opens the door 0050 left shut for existing Terminals; layout stays L3 per 0019)
0057A minimal reference relay in-treeAccepted (implements 0051 and ADR-0052; backs 0051’s trust-honesty claim)
0058Right-click context menus for panes, windows, and sessionsAccepted
0059Sandboxed chunked file uploadAccepted (builds on 0007, 0021, and 0031)

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.