Implemented in #20 (OSC 7501 program status: records, clear, feature detection, component links). Rex detection landed separately in #19.
Support the Program Status Protocol (OSC 7501)#18
Support the Program Status Protocol (OSC 7501), a generic terminal escape sequence that lets a program tell the terminal whether it is idle, working (with optional progress), blocked (on permission, question or auth), done, or in error, with a short message. Rex (Superlogical) shows it as tab spinners, blocked marks and session-picker indicators. Terminals that don't know it ignore it.
Ashlar owns the terminal session and already speaks the neighbouring sequences (OSC 8, OSC 52, OSC 11/4 palette queries), so it's the right layer to get the spec's rules right once instead of in every app.
Proposal
- Reactive status primitive, such as
useProgramStatus({ state, progress, msg, title, app })orscreen.status(...). It emits a report when values change, written to stdout outside the frame diff, like the OSC 52 write insrc/core/selection.ts. - Enforce the spec in one place:
- Each report replaces its record completely, so
appandtitleare resent every time. msgandtitleare base64 UTF-8 and must not contain control characters.- A report over the limits is dropped whole: 4096 bytes per sequence, 2048 decoded for
msg, 192 fortitle, 32 forapp.
- Each report replaces its record completely, so
- Lifecycle: clear or finalize the status (
done,errororidle) inmount/unmountand the existing SIGINT, SIGTERM and exit restore path, so every app follows the spec's advice to report before exiting. - Opt-in component links:
<ProgressBar value>feedsprogress(0–100), andSpinner/useStalledmap toworkingwith no percentage.
Optional
- Feature detection: send
OSC 7501 ; ?, thenCSI c; if theCSI creply arrives first, the terminal doesn't support it. This fits the palette query's OSC-response path throughstdin-parser, but it's async whileterminalCapsis computed synchronously from the environment. The spec allows sending without detection. - Also send OSC 9;4 progress for terminals that support only that. The spec allows sending both.
Related
src/core/terminal-caps.ts detects terminals only by TERM_PROGRAM/TERM. Rex renders with Ghostty's engine, so it likely supports sync output, hyperlinks and the Kitty keyboard protocol. That only helps if Rex reports itself as ghostty/xterm-ghostty, which is unverified.
Out of scope
Rex's server API, Lua events and per-program icons are Rex automation or built-in Rex artwork, not rendering. Apps choose their own app id, and ashlar passes it through.