[{"data":1,"prerenderedAt":503},["ShallowReactive",2],{"navigation_docs":3,"-decisions-0001-kyo-ui-is-the-dsl":223,"-decisions-0001-kyo-ui-is-the-dsl-surround":498},[4,26,96,105,202],{"title":5,"icon":6,"path":7,"stem":8,"children":9,"page":25},"Getting started","i-lucide-rocket","\u002Fgetting-started","1.getting-started",[10,15,20],{"title":11,"path":12,"stem":13,"icon":14},"Installation","\u002Fgetting-started\u002Finstallation","1.getting-started\u002F1.installation","i-lucide-download",{"title":16,"path":17,"stem":18,"icon":19},"The first app","\u002Fgetting-started\u002Ffirst-app","1.getting-started\u002F2.first-app","i-lucide-play",{"title":21,"path":22,"stem":23,"icon":24},"The first test","\u002Fgetting-started\u002Ffirst-test","1.getting-started\u002F3.first-test","i-lucide-flask-conical",false,{"title":27,"icon":28,"path":29,"stem":30,"children":31,"page":25},"Guide","i-lucide-book-open","\u002Fguide","2.guide",[32,37,42,47,52,57,62,67,72,77,81,86,91],{"title":33,"path":34,"stem":35,"icon":36},"Components","\u002Fguide\u002Fcomponents","2.guide\u002F01.components","i-lucide-component",{"title":38,"path":39,"stem":40,"icon":41},"Inputs and forms","\u002Fguide\u002Finputs-and-forms","2.guide\u002F02.inputs-and-forms","i-lucide-text-cursor-input",{"title":43,"path":44,"stem":45,"icon":46},"Scrolling and viewports","\u002Fguide\u002Fscrolling","2.guide\u002F03.scrolling","i-lucide-scroll-text",{"title":48,"path":49,"stem":50,"icon":51},"Overlays and layers","\u002Fguide\u002Foverlays","2.guide\u002F04.overlays","i-lucide-layers",{"title":53,"path":54,"stem":55,"icon":56},"Styles and theme","\u002Fguide\u002Fstyles","2.guide\u002F05.styles","i-lucide-palette",{"title":58,"path":59,"stem":60,"icon":61},"Composables","\u002Fguide\u002Fcomposables","2.guide\u002F06.composables","i-lucide-puzzle",{"title":63,"path":64,"stem":65,"icon":66},"Widgets","\u002Fguide\u002Fwidgets","2.guide\u002F07.widgets","i-lucide-blocks",{"title":68,"path":69,"stem":70,"icon":71},"The assistant","\u002Fguide\u002Fassistant","2.guide\u002F08.assistant","i-lucide-message-square",{"title":73,"path":74,"stem":75,"icon":76},"The same app on the web","\u002Fguide\u002Fweb","2.guide\u002F09.web","i-lucide-globe",{"title":78,"path":79,"stem":80,"icon":24},"Testing","\u002Fguide\u002Ftesting","2.guide\u002F10.testing",{"title":82,"path":83,"stem":84,"icon":85},"Running and packaging","\u002Fguide\u002Fpackaging","2.guide\u002F11.packaging","i-lucide-package",{"title":87,"path":88,"stem":89,"icon":90},"The terminal contract","\u002Fguide\u002Fterminal","2.guide\u002F12.terminal","i-lucide-square-terminal",{"title":92,"path":93,"stem":94,"icon":95},"Benchmarks","\u002Fguide\u002Fbenchmarks","2.guide\u002F13.benchmarks","i-lucide-gauge",{"title":97,"icon":98,"path":99,"stem":100,"children":101,"page":25},"AI and agents","i-lucide-bot","\u002Fai","3.ai",[102],{"title":97,"path":103,"stem":104,"icon":98},"\u002Fai\u002Fagents","3.ai\u002F1.agents",{"title":106,"icon":107,"path":108,"stem":109,"children":110},"Decisions","i-lucide-scale","\u002Fdecisions","4.decisions",[111,114,118,122,126,130,134,138,142,146,150,154,158,162,166,170,174,178,182,186,190,194,198],{"title":112,"path":108,"stem":113,"icon":46},"All decisions","4.decisions\u002Findex",{"title":115,"path":116,"stem":117},"0001. kyo-ui is the DSL","\u002Fdecisions\u002F0001-kyo-ui-is-the-dsl","4.decisions\u002F0001-kyo-ui-is-the-dsl",{"title":119,"path":120,"stem":121},"0002. jatatui renders the cells","\u002Fdecisions\u002F0002-jatatui-renders-the-cells","4.decisions\u002F0002-jatatui-renders-the-cells",{"title":123,"path":124,"stem":125},"0003. Pin Kyo 1.0.0-RC7 and JDK 25","\u002Fdecisions\u002F0003-pin-kyo-rc7-and-jdk-25","4.decisions\u002F0003-pin-kyo-rc7-and-jdk-25",{"title":127,"path":128,"stem":129},"0004. Public Kyo APIs only","\u002Fdecisions\u002F0004-public-kyo-apis-only","4.decisions\u002F0004-public-kyo-apis-only",{"title":131,"path":132,"stem":133},"0005. A SOFT frame contract and an own watcher loop","\u002Fdecisions\u002F0005-soft-frame-contract-and-own-watcher-loop","4.decisions\u002F0005-soft-frame-contract-and-own-watcher-loop",{"title":135,"path":136,"stem":137},"0006. Purity: edge files, lint and a pure painter","\u002Fdecisions\u002F0006-purity-edge-files-and-lint","4.decisions\u002F0006-purity-edge-files-and-lint",{"title":139,"path":140,"stem":141},"0007. Compiler flags from sbt-tpolecat","\u002Fdecisions\u002F0007-compiler-flags-from-sbt-tpolecat","4.decisions\u002F0007-compiler-flags-from-sbt-tpolecat",{"title":143,"path":144,"stem":145},"0008. The artifact split: runner, app, testkit and core","\u002Fdecisions\u002F0008-artifact-split-runner-app-testkit-core","4.decisions\u002F0008-artifact-split-runner-app-testkit-core",{"title":147,"path":148,"stem":149},"0009. tui4s-use and tui4s-widgets, cross-built","\u002Fdecisions\u002F0009-use-and-widgets-cross-built","4.decisions\u002F0009-use-and-widgets-cross-built",{"title":151,"path":152,"stem":153},"0010. The flagship assistant is the blueprint of a real app","\u002Fdecisions\u002F0010-the-flagship-assistant-as-blueprint","4.decisions\u002F0010-the-flagship-assistant-as-blueprint",{"title":155,"path":156,"stem":157},"0011. The web target: a standalone Scala.js app and one theme","\u002Fdecisions\u002F0011-web-target-standalone-scalajs-and-one-theme","4.decisions\u002F0011-web-target-standalone-scalajs-and-one-theme",{"title":159,"path":160,"stem":161},"0012. The documentation is example-first","\u002Fdecisions\u002F0012-documentation-is-example-first","4.decisions\u002F0012-documentation-is-example-first",{"title":163,"path":164,"stem":165},"0013. Benchmarks in the repository, with their own build","\u002Fdecisions\u002F0013-benchmarks-in-repo-with-own-build","4.decisions\u002F0013-benchmarks-in-repo-with-own-build",{"title":167,"path":168,"stem":169},"0014. Release per module, by tag, as 0.1.0-RC1","\u002Fdecisions\u002F0014-release-per-module-tags-and-rc1","4.decisions\u002F0014-release-per-module-tags-and-rc1",{"title":171,"path":172,"stem":173},"0015. Packaging: the AOT cache in the start scripts, native-image as an option","\u002Fdecisions\u002F0015-packaging-aot-cache-and-native-image","4.decisions\u002F0015-packaging-aot-cache-and-native-image",{"title":175,"path":176,"stem":177},"0016. Process: lean mode and agent roles","\u002Fdecisions\u002F0016-process-lean-mode-and-agent-roles","4.decisions\u002F0016-process-lean-mode-and-agent-roles",{"title":179,"path":180,"stem":181},"0017. Deferred: templates, mouse, the kitty keyboard protocol and Windows","\u002Fdecisions\u002F0017-deferred-templates-mouse-and-kitty","4.decisions\u002F0017-deferred-templates-mouse-and-kitty",{"title":183,"path":184,"stem":185},"0018. pini4s is a vendored Git submodule","\u002Fdecisions\u002F0018-pini4s-as-a-vendored-submodule","4.decisions\u002F0018-pini4s-as-a-vendored-submodule",{"title":187,"path":188,"stem":189},"0019. Upstream issues are drafts that the user posts","\u002Fdecisions\u002F0019-upstream-kyo-issues-as-drafts","4.decisions\u002F0019-upstream-kyo-issues-as-drafts",{"title":191,"path":192,"stem":193},"0020. Release from the Actions form","\u002Fdecisions\u002F0020-release-from-the-actions-form","4.decisions\u002F0020-release-from-the-actions-form",{"title":195,"path":196,"stem":197},"0021. The rulebook is CONTRIBUTING.md","\u002Fdecisions\u002F0021-the-rulebook-is-contributing-md","4.decisions\u002F0021-the-rulebook-is-contributing-md",{"title":199,"path":200,"stem":201},"0022. The logo is text","\u002Fdecisions\u002F0022-the-logo-is-text","4.decisions\u002F0022-the-logo-is-text",{"title":203,"icon":204,"path":205,"stem":206,"children":207,"page":25},"Project","i-lucide-compass","\u002Fproject","5.project",[208,213,218],{"title":209,"path":210,"stem":211,"icon":212},"Roadmap","\u002Fproject\u002Froadmap","5.project\u002F1.roadmap","i-lucide-map",{"title":214,"path":215,"stem":216,"icon":217},"Contributing","\u002Fproject\u002Fcontributing","5.project\u002F2.contributing","i-lucide-git-pull-request",{"title":219,"path":220,"stem":221,"icon":222},"Security","\u002Fproject\u002Fsecurity","5.project\u002F3.security","i-lucide-shield",{"id":224,"title":115,"body":225,"description":491,"extension":492,"links":493,"meta":494,"navigation":495,"path":116,"seo":496,"stem":117,"__hash__":497},"docs\u002F4.decisions\u002F0001-kyo-ui-is-the-dsl.md",{"type":226,"value":227,"toc":480},"minimark",[228,233,237,241,244,248,304,308,345,349,420,424,459,463],[229,230,232],"h2",{"id":231},"status","Status",[234,235,236],"p",{},"Accepted",[229,238,240],{"id":239},"date","Date",[234,242,243],{},"2026-10-02 (the fifth round of the decision log). The kyo-ui stack merged on 2026-10-14.",[229,245,247],{"id":246},"context","Context",[249,250,251,255,282,293],"ul",{},[252,253,254],"li",{},"The first goal (2026-10-01) was \"a Kyo core that wraps the underlying Scala library\", declarative and fast, with ZIO and Cats Effect modules.",[252,256,257,258,262,263,266,267,266,270,273,274,277,278,281],{},"A design panel scored four designs. The winner, \"free\", had an own model: ",[259,260,261],"code",{},"TuiApp[S]"," with ",[259,264,265],{},"init",", ",[259,268,269],{},"update(S, Event): Next[S]",[259,271,272],{},"view(S): View",", tui4s ",[259,275,276],{},"View"," case-class nodes and a ",[259,279,280],{},"Keymap"," (spec section 1). Scores: free 7.53, elm 7.35, signals 6.95, components 5.73.",[252,283,284,285,288,289,292],{},"The panel's core was built as PRs 3 to 5. On 2026-10-02 the user reviewed it: it was not a functional wrapper of jatatui, and ",[259,286,287],{},"internal\u002F"," was about 3.5k lines of mutable code (the engine had 25 ",[259,290,291],{},"var","s).",[252,294,295,296,299,300,303],{},"The user then pointed at kyo-ui. kyo-ui already has the model that the work moved towards: pure UI values, signals with fine-grained subscriptions, handlers of type ",[259,297,298],{},"Any \u003C Async",", two-way ",[259,301,302],{},"SignalRef"," bindings. Its README invites custom backends, and upstream has no terminal runner (only DOM, server push and HTML stream).",[229,305,307],{"id":306},"decision","Decision",[249,309,310,317,328,342],{},[252,311,312,313,316],{},"tui4s is a terminal runner for kyo-ui: it lays out a kyo-ui ",[259,314,315],{},"UI"," value in terminal cells and paints it with jatatui.",[252,318,319,320,323,324,327],{},"tui4s adds no UI DSL. An app imports ",[259,321,322],{},"kyo.UI.*"," for the screen and ",[259,325,326],{},"tui4s"," only to run, test and mount.",[252,329,330,331,334,335,266,338,341],{},"tui4s adds only what a terminal needs: the components in two styles (hooks and the ",[259,332,333],{},"Component"," class), ",[259,336,337],{},"Tui.run",[259,339,340],{},"TuiApp"," and the headless kit.",[252,343,344],{},"The own View\u002FKeymap\u002FEngine model of the spec is dropped. PRs 3, 4 and 5 were closed, and their branches stay only as history.",[229,346,348],{"id":347},"alternatives-considered","Alternatives considered",[249,350,351,373,387,397,403,409],{},[252,352,353,357,358,266,361,363,364,266,366,266,369,372],{},[354,355,356],"strong",{},"The own DSL of the 2026-10-01 spec"," (",[259,359,360],{},"App[S]",[259,362,276],{}," nodes, ",[259,365,280],{},[259,367,368],{},"Next[S]",[259,370,371],{},"sources(S)","). It won the panel. It lost because the user found its core not functional, and because kyo-ui already gives a richer UI model that tui4s would otherwise copy and maintain.",[252,374,375,378,379,382,383,386],{},[354,376,377],{},"The other panel designs"," (elm, signals, components). They scored lower. The panel found a near-fatal DX flaw in components (Kyo effect rows in user code) and a learnability flaw in signals (",[259,380,381],{},"map"," against ",[259,384,385],{},"at",", torn frames) (spec 1.1).",[252,388,389,392,393,396],{},[354,390,391],{},"The user's Flutter-style first take"," (Widget, Element, State on Cats Effect; branch ",[259,394,395],{},"first-take","). It was one candidate of the panel and was not chosen. The reason for this candidate alone is not recorded.",[252,398,399,402],{},[354,400,401],{},"Three prototype styles on jatatui"," (pure, mutable, streams; in the notes). The run stopped at the plan stage when the user pointed at kyo-ui.",[252,404,405,408],{},[354,406,407],{},"A State-monad UI"," (spike S8, 2026-10-09: \"the UI as State monads that change the buffer\"). The user cancelled it (\"let's not do it\"). The spec is parked.",[252,410,411,414,415,419],{},[354,412,413],{},"tui-scala as the base of the DSL",". tui-scala 0.0.10 is a tui-rs (2022) API with no input or event system, and its author calls jatatui its successor. See ",[416,417,418],"a",{"href":120},"ADR 0002",".",[229,421,423],{"id":422},"consequences","Consequences",[249,425,426,433,436,446,453],{},[252,427,428,429,432],{},"Good: one UI value runs in the terminal and in a browser (",[416,430,431],{"href":156},"ADR 0011","). The user's \"small Flutter\" goal comes from kyo-ui, not from new code.",[252,434,435],{},"Good: tui4s has no DSL to design, document or keep in step with kyo-ui.",[252,437,438,439,266,442,445],{},"Bad: tui4s depends on the AST, the attributes and the private rules of kyo-ui. The runner copies the dispatch and region rules, and a surface guard pins them (",[416,440,441],{"href":124},"ADR 0003",[416,443,444],{"href":128},"ADR 0004",").",[252,447,448,449,452],{},"Bad: kyo-ui is designed for the DOM. Units (",[259,450,451],{},"px","), mouse events, SVG and charts do not map to cells. The runner ignores 29 of 76 style properties and warns once per name.",[252,454,455,456,445],{},"Bad: the ZIO and Cats Effect modules must mirror the kyo-ui DSL by hand. They are not built (",[416,457,458],{"href":168},"ADR 0014",[229,460,462],{"id":461},"references","References",[249,464,465,468,471,474,477],{},[252,466,467],{},"Decision log: fifth round (2026-10-02), sixth round (2026-10-09), seventh round (S8 cancelled).",[252,469,470],{},"Handoff: \"2026-10-02: DIRECTION CHANGE\".",[252,472,473],{},"Spec: sections 1.1 to 1.4 and 9 (most of its API shapes were dropped by this decision).",[252,475,476],{},"PRs #3, #4, #5 (closed); PRs #10 to #16 (the kyo-ui stack, merged 2026-10-14).",[252,478,479],{},"ARCHITECTURE.md: \"What tui4s is\". ",{"title":481,"searchDepth":482,"depth":482,"links":483},"",2,[484,485,486,487,488,489,490],{"id":231,"depth":482,"text":232},{"id":239,"depth":482,"text":240},{"id":246,"depth":482,"text":247},{"id":306,"depth":482,"text":307},{"id":347,"depth":482,"text":348},{"id":422,"depth":482,"text":423},{"id":461,"depth":482,"text":462},"tui4s has no UI DSL of its own: kyo-ui describes the screen, and tui4s is its terminal runner.","md",null,{},true,{"title":115,"description":491},"LVzybckLAgjIMEHROtNRQp4xpi7vQFf1G5bP5FmpnXg",[499,501],{"title":112,"path":108,"stem":113,"description":500,"icon":46,"children":-1},"The decisions that shaped tui4s, with the alternatives that lost and why.",{"title":119,"path":120,"stem":121,"description":502,"children":-1},"jatatui 0.31.0 (a Java port of ratatui) with its crossterm JNI library is the terminal backend; tui-scala never goes on the classpath.",1792528755516]