tui4s

Architecture decision records

The decisions that shaped tui4s, with the alternatives that lost and why.

Each record states one decision: the forces, the decision, the alternatives that lost, and the consequences. The ids in the references (D-1 to D-32, D1 to D25, S1 to S8, K29, RR N9) are the ids of the working notes of the project, which are not in the repository. The ADRs keep what a reader needs from them.

#TitleStatusDecision in one line
0001kyo-ui is the DSLAcceptedtui4s has no UI DSL: kyo-ui describes the screen, and tui4s is its terminal runner.
0002jatatui renders the cellsAcceptedjatatui 0.31.0 and its crossterm JNI are the backend; tui-scala never goes on the classpath.
0003Pin Kyo 1.0.0-RC7 and JDK 25AcceptedKyo and kyo-ui stay at RC7 for 0.1, on JDK 25; a tasty-query guard pins what the runner reads.
0004Public Kyo APIs onlyAcceptedNo private[kyo] member and no reflection; the runner copies private rules and the guard pins them.
0005A SOFT frame contract and an own watcher loopAcceptedOne frame per event, 0 splits with no load, at most 1 per 10 000 under load; own watcher loop and a 1 s repair tick.
0006Purity: edge files, lint and a pure painterAcceptedImpure code only in 9 edge files and 15 KEEP sites, checked by scalafix; a pure painter, a release stack, a fiber gauge.
0007Compiler flags from sbt-tpolecatAcceptedWarnings stay warnings on a developer machine; CI adds -Werror.
0008The artifact split: runner, app, testkit and coreAcceptedFour artifacts in one repository and the same packages; tui4s-core is the composite; tui4s.internal is sealed.
0009tui4s-use and tui4s-widgets, cross-builtAcceptedComposables and widgets are plain kyo-ui for the JVM and Scala.js, with no dependency on the core.
0010The flagship assistant is the blueprint of a real appAcceptedOne AI chat app shows the app structure; API keys only; no redirects; no CLI backend in published code.
0011The web target: a standalone Scala.js app and one themeAcceptedThe web app is static Scala.js from the shared module, with no server; one Theme gives both looks.
0012The documentation is example-firstAcceptedEvery public API has a compiled example; doc blocks are tested regions; Docus on Vercel; no PRs in the program.
0013Benchmarks in the repository, with their own buildAcceptedbench/ has its own build; the headline is compactness, expressiveness, correctness and resources; performance on its own page.
0014Release per module, by tag, as 0.1.0-RC1AcceptedOne tag per module, 0.1.0-RC1 while Kyo is RC, a human approves each release; zio, cats and useSignal go before 0.1. ADR 0020 changes the trigger.
0015Packaging: the AOT cache in the start scripts, native-image as an optionAcceptedStart scripts have the flags and use the AOT cache after one run of bin/aot-train; the runner carries native-image metadata; a GraalVM CE smoke job in CI.
0016Process: lean mode and agent rolesAcceptedImplementer, one reviewer, fixer; a skeptic only for concurrency and restore code; the notes leave the repository.
0017Deferred: templates, mouse, the kitty keyboard protocol and WindowsAccepted (deferred)No template interpolator, no mouse, no kitty flags and no supported Windows port in 0.1.
0018pini4s is a vendored Git submoduleAccepted (one part proposed)Optional keyed shared state in vendor/pini4s, used only by the examples; a published artifact later.
0019Upstream issues are drafts that the user postsAcceptedThe session drafts upstream issues; the user posts them; each bug has a workaround with a named exit.
0020Release from the Actions formAcceptedOne run of the form on main checks everything before the tag, and one approval publishes all its modules in order; CHANGELOG.md gives the notes.
0021The rulebook is CONTRIBUTING.mdAcceptedCONTRIBUTING.md is the rulebook for humans and agents; ARCHITECTURE.md tells how the runner works; AGENTS.md is short and imports both.
0022The logo is textAcceptedThe ASCII art of the maintainer is the logotype and its "4" is the isomark; one script makes all the logo assets from the text, and CI checks them.

Format: MADR-lite. Each record has the sections Status, Date, Context, Decision, Alternatives considered, Consequences and References. The text uses ASD-STE100. When a source does not record a reason, the record says "not recorded"; a reason that the record adds is marked PROPOSAL.

Copyright © 2026