# Design Tradeoffs
## `nix` forkpty vs. `portable-pty`
**Chosen**: `nix` (low-level, no Windows abstraction).
`nix` gives us direct access to `forkpty`, `termios`, and Unix signals.
`portable-pty` adds a Windows abstraction layer that we don't need
(macOS-first design). When Linux support is added, `nix` works there too.
## `vte` vs. custom ANSI parser
**Chosen**: `vte` (battle-tested, used by Alacritty/Kitty).
ANSI escape parsing is surprisingly complex — nested escape sequences,
device control strings, re-entrant state transitions. A custom parser
would be error-prone and hard to maintain. `vte` is the de-facto
standard and has been fuzzed extensively.
## `glyphon` vs. raw CoreText / Skia
**Chosen**: `glyphon` (wgpu-native, portability).
- CoreText would lock us to macOS with no migration path.
- Skia is heavy (500k+ lines) and complex to integrate.
- `glyphon` + `swash` gives us font shaping, caching, SDF rendering,
and works on any wgpu backend.
Cost: `glyphon` adds ~30 transitive dependencies. Acceptable for a GPU
renderer.
## Per-row text runs
**Chosen**: one `glyphon::Buffer` per visible row.
Per-row buffers keep redraw work bounded to visible rows and let us cache
text/style signatures independently. This is a better fit for terminal
scrollback and selection than one large shaped text buffer.
## Window + Surface lifetime management
`wgpu::Surface<'window>` must not outlive its window handle. Panasyn
wraps the `winit::Window` in `Arc` and passes an owned clone into
`Instance::create_surface`, allowing wgpu to retain a valid handle source
without lifetime extension tricks.
## Thread model: PTY reader thread
**Chosen**: Dedicated thread + `winit::EventLoopProxy`.
Alternative: async IO on the main thread via `mio`/`tokio`.
The thread approach is simpler, more maintainable, and avoids
pulling in a large async runtime. The cost is a 64 KB buffer
per thread and one channel send per PTY read.