feat(tui): user commands bound to key chords
Customization groundwork for a tmux/zellij-style ecosystem, in three parts.
User commands (commands section): named argv programs, each optionally bound to key chords through the existing chord grammar, the cmux-tui equivalent of tmux bind-key ... command. A bound chord runs the argv as a new PTY tab in the active pane through the mux run command. The child inherits CMUX_TUI_SOCKET, so a command script can drive the public CLI against its own session. Alt/Super chords are modeless; other chords run after the prefix. Chords follow last-write-wins with the keys section, the prefix stays reserved, ids are reserved only after validation, chords cap at 8 per command and only successful binds consume the cap, the list caps at 32, and commands appear in the Ctrl-b ? modal under their configured names. Implementation: Action::UserCommand(UserCommandIndex) reuses the existing chord resolution, routing, and admission plumbing; classified composite with route frontend command config + run in spec/inventory.json; surface-only clients reject the action at dispatch and at execution.
Pane presentation: theme.border_style (single/rounded/thick/double/none; none blanks the border cells so panes separate by whitespace, geometry unchanged), pane.padding (0-4 cells applied in pane_parts_for_rect, the single content-geometry source, so PTY sizing, hit testing, selection, and viewport crops follow), and theme.dim_inactive (unfocused terminal panes get the DIM attribute via a set_style patch that preserves cell colors).
Status bar (status_bar.*, theme.status_bg/status_fg): visible:false gives the row back to the panes with transient messages still overlaying; left/right take ordered segments with {session} {workspace} {screen} {screens} {title} {user} interpolation (single-pass, inserted values never rescanned) or run argv widgets, the tmux #() equivalent. Each command segment runs on its own worker with its own interval; capture is threadless (non-blocking pipe on Unix in the command's own process group, kill-on-close job object plus size-bounded temp file on Windows with suspended-start assignment), output keeps a bounded tail, escape sequences strip, workers coalesce redraw pokes and idle on a condvar, reload retires workers within one poll tick through a bounded handle list, shutdown joins them, and a child stuck in uninterruptible kernel I/O is held (never stacked behind) until the kernel releases it. Resolved segments cache behind an input fingerprint that includes the title only when a template uses it.
Docs: docs/configuration.md, docs/keyboard.md, example examples/user-commands.json.
Review disposition: fifteen local $autoreview rounds (gpt-5.6-sol, high) ran against successive heads; every finding through round 15 is fixed in this branch except three, disposed as follows. (1) Dim-inactive "replaces cell styles" (rounds 6 and 15): refuted — ratatui's Cell::set_style patches (fg/bg None keep the cell's colors, only the DIM modifier is added), and a tmux capture-pane -e dogfood shows truecolor SGRs present together with ESC[2m. (2) Spawn-vs-stop ordering: round 14 required holding the raise lock across spawn, round 15 flagged exactly that as a shutdown hazard; the shipped design uses an unlocked pre-spawn check plus first-tick kill, a bounded window in which the only thing that can run is a command the user had configured moments earlier (documented in code). (3) Semantic-destination intents for user-command tabs (CodeRabbit): deliberate parity with the existing file-sidebar editor launch and CLI run; noted as a follow-up.
Dogfood on hosted macOS binaries, driven in tmux (keys plus injected SGR mouse), verified per feature, including a ticking clock segment and a script-bound key mutating the session through the CLI. Pre-existing bugs found and filed separately: #10394 (Kitty budget retry noise after split), #10395 (eprintln corrupts the TUI frame), #10426 (flaky pointer-paint test on cold parallel runs).