Why flagstaff
flagstaff against ora, log-update, boxen and cli-table3, one capability per row, every cell linked to the test, grade or source that proves it.
ora, log-update, boxen and cli-table3 each draw one thing well on a terminal. flagstaff draws
the same four things — through drop-in paths graded by each one's own test suite — on one
frame loop, and adds what a terminal-only library has no reason to have: a text form of every
component for pipes, CI logs and screen readers, and one event per state change for an agent
reading --json.
The table below is the whole comparison. Every mark links to its evidence: a test in this
repository for ours, and for theirs the source file of the exact version compat-oracle grades,
or that package's own test suite. scripts/capabilities-lock.test.ts fails the build when a
cited test no longer contains the title it is cited for, when a source no longer contains the
line it is quoted for, or when a source we say lacks something has gained it.
✓ yes · ◐ partial, with what is missing · ✗ no · — does not apply. Every mark links to its evidence: our test or grade, or the incumbent’s source at the version compat-oracle grades.
Output in every environment
One line per state change on a pipe
A log file or an agent reading a pipe gets each state once, as text, instead of repainted frames or erase sequences.
flagstaff- flagstaff: yes
A box that prints its text off a terminal
Off a terminal the box component writes
title: text, so a log or an agent reads the message rather than border characters.flagstaff- flagstaff: yes
log-update- log-update: does not applydraws no boxes
A table that prints header-and-value pairs off a terminal
Off a terminal each row is written as
header: valuepairs, which a log, an agent or a screen reader can read without the grid.flagstaff- flagstaff: yes
A screen-reader mode, on a terminal too
With
CLI_ACCESSIBLE=1the output policy chooses the accessible mode ahead of the terminal check, so a component hoisted withhoist()prints its plain text once per state and never redraws; theflagstaff/oradrop-in keeps ora's behaviour instead.flagstaff- flagstaff: yes
log-update- log-update: noredraws on any stream
Agents and automation
--json: one NDJSON event per state transitionA component hoisted with
{ json: true }writes each transition as a JSON object on stderr and leaves stdout for the result, so an agent parses state instead of scraping a terminal.flagstaff- flagstaff: yes
ora- ora: no
log-update- log-update: no
boxen- boxen: no
cli-table3- cli-table3: no
An injectable clock for animation
A test drives frames with
manualClock()instead of patching global timers, so a spinner's terminal output is the same bytes on every run.flagstaff- flagstaff: yes
A checker for plugins before they ship
npx flagstaff check ./plugin.mjsrenders every contribution in all five modes side by side, and exits 1 with a code and a fix on a refusal.flagstaff- flagstaff: yes
cli-table3- cli-table3: noships no command
One render engine
Spinner, progress, tasks, box and table on one loop
Every component is hoisted, updated and lowered the same way, and every one gets the same five output modes.
flagstaff- flagstaff: yes
boxen- boxen: noa box only
cli-table3- cli-table3: noa table only
Custom styles through a validated plugin registry
A spinner or border style is registered once, validated against the published JSON schema, and every component that draws one can use it by name.
flagstaff- flagstaff: yes
Every style must carry a text form
A spinner or component without a static projection is refused at registration with
E_NO_STATIC_PROJECTION, so nothing registered can only animate.flagstaff- flagstaff: yes
log-update- log-update: does not applyhas no styles
Safety and correctness
Cursor restored on SIGINT, SIGTERM and SIGHUP
A spinner killed with Ctrl+C gives the cursor back and the process still terminates.
flagstaff- flagstaff: yes
Borders stay aligned around wide (CJK) characters
Rows are measured in terminal columns, so a double-width character does not push a border out of line.
flagstaff- flagstaff: yes
boxen- boxen: yes
cli-table3- cli-table3: yes
Weight
Every runtime dependency from the same repository
Installing it adds closeout, linegauge, paratext and roundel, released from this repository through one pipeline, and nothing else.
flagstaff- flagstaff: yes
Compatibility
Passes ora's own test suite
flagstaff/orais graded by ora 9.4.1's own tests, unedited, so changing the import keeps ora's behaviour.Passes log-update's own test suite
flagstaff/log-updateis graded by log-update 8.0.0's own tests, which render every frame through a terminal emulator and assert the screen.Passes boxen's own test suite
flagstaff/boxenis graded by boxen 8.0.1's own tests, each a snapshot of the exact characters the box comes out as.Passes cli-table3's own test suite
flagstaff/cli-table3is graded by the cases of cli-table3 0.6.5's own suite that go through its public API.
Reading it
- "on a pipe", "off a terminal" mean the loop,
hoist(). The four drop-ins keep their incumbents' behaviour to the byte, including off a terminal, because that is what their grade measures. Incremental migration moves a program from one to the other a file at a time. - Parity rows are here too. ora and log-update restore the cursor on a signal; boxen and cli-table3 measure wide characters correctly. A row where they match us is a row a reader would otherwise have to go and check.
- — does not apply is not a soft ✗. A table library that never hides the cursor has nothing to restore; the cell says why.
What is not in the table
A row goes in only when every cell of it can be proved. These were left out:
- Weight. The per-subpath byte figures are asserted by
weight.test.tsand published on Benchmarks, measured the same way on both sides. They are not a yes-or-no capability, so they are not a row. NO_COLOR. flagstaff honours it through roundel's tokens, and roundel's tests prove the rule; no flagstaff test renders a component under it yet. ora's colour comes from chalk 5.6.2, whose colour detection does not readNO_COLOR. See NO_COLOR and accessibility.- Emoji width. The width tests use CJK text; none uses emoji, so the row says CJK.
Plugins
Add spinners, borders, glyphs, colour tokens and components as one plain object, validated at register() and checked before it ships with flagstaff check.
Compatibility
How flagstaff's four drop-ins are graded — each incumbent's own test suite, unedited — the current grades, and the differences that remain.