koto is a lightweight, dependency-free C++23 Terminal User Interface (TUI) library engineered for Linux and POSIX systems. It provides differential double-buffered rendering, DEC Mode 2026 synchronized updates, deterministic input decoding, and zero-allocation frame layouts.
Comprehensive architectural documentation, interactive guides, widget references, and API specifications are available on the official documentation website: koto.karmveervaghela.workers.dev.
- Differential Double-Buffered Rendering: Minimizes standard output write volume by comparing front and back cell buffers per frame with ANSI SGR color and attribute state caching.
- DEC Mode 2026 Synchronized Updates: Emits private mode sequences (
\033[?2026h/\033[?2026l) to halt terminal rasterization during buffer emission, preventing mid-frame shearing on supporting terminal emulators. - Deterministic Input Decoding: Utilizes a monotonic 35 ms escape sequence deadline timer combined with
ioctl(FIONREAD)burst draining, resolving escape ambiguity without CPU busy-spinning or input lag. - Zero-Allocation Layout Deduction: Computes multi-element horizontal and vertical flex constraints at compile time using C++ Non-Type Template Parameters (NTTP), enabling structured bindings (
auto [left, right] = Layout::horizontal(...)) with zero heap allocation. - Concept-Constrained Focus Engine: Provides 1D Tab cycling and 2D Manhattan distance spatial routing constrained by the C++20
FocusableStateconcept. - Cell Hit-Buffer: Tags back-buffer cells with 32-bit universal
Idtokens forO(1)spatial mouse click, hover, and scroll wheel dispatch. - Wide Unicode & Grapheme Integrity: Full UAX-11 East Asian Width calculation, 2-column continuation cells, 31-byte grapheme storage for multi-codepoint ZWJ emoji clusters, and boundary-safe clipping.
- POSIX Stream I/O:
EINTR-safewrite_all()loop with short-write protection, asynchronous signal handling via a POSIX self-pipe (SIGWINCH), and async-signal-safe terminal restoration.
- Application Lifecycle & Raw Mode: Terminal raw mode, mouse reporting, and alternate screen buffer are initialized strictly when
App::run()executes, not in theAppconstructor. The library does not intercept or hardcode any global exit hotkeys; developers manage application termination explicitly viaapp.quit(). - Crash Recovery & Signal Chaining: Fatal crash handlers (
SIGSEGV,SIGABRT,SIGBUS,SIGFPE,SIGILL) andstd::terminateemit a minimal async-signal-safe escape sequence to restore terminal modes before chaining to host handlers. Termination signals (SIGTERM,SIGINT,SIGQUIT,SIGHUP) chain directly to custom host signal handlers without altering terminal raw mode, or cleanly restore the terminal when default dispositions apply. Inheritednohup(SIG_IGNonSIGHUP) is respected without override. - Bracketed Paste Preservation & Inactivity Timeout: Multi-byte bracketed paste streams (
\033[200~through\033[201~) are exempted from the 35 ms short-escape timeout. Incoming chunks refresh a 500 ms inactivity deadline (with a 4 MB safety cap), ensuring fragmented pastes across SSH or tmux arrive as atomicPasteEvents while guaranteeing that unterminated paste sequences never block subsequent keyboard input. - Non-ESC Stale Input Recovery: Truncated or orphaned non-escape bytes (such as an incomplete UTF-8 lead byte) are discarded after the 35 ms timeout, preventing event loop stalling and preserving 60 FPS animation tick timing.
- Focus State Lifetimes & Collision Safety:
FocusManagerstores non-owning references (&state) to widget state structs. States must outlive the manager, be explicitly unregistered usingfm.remove(state)orfm.remove(id), or be scoped inside anIdScopemodal trap. Pointer-to-hash collision assertions detect identical 32-bit tokens across distinct state addresses without ABI drift across build configurations. - Terminal Protocol Capabilities: Emits Kitty keyboard progressive enhancement flag 1 (
\033[>1u) on startup and pops it on teardown (\033[<u). On terminals lacking Kitty keyboard support, input decoding falls back transparently to standard ANSI, CSI, and SS3 escape sequences.
#include <koto/koto.hpp>
using namespace koto;
int main()
{
App app;
ListState todo({"Refactor core", "DEC Mode 2026", "Zero-alloc layout"});
todo.navigation = ListNavigation::Wrap;
app.on_key([&](const KeyEvent& key) {
if (key.ch == 'q' || key.ch == 'Q' || (key.ctrl && (key.ch == 'c' || key.ch == 'C'))) {
app.quit();
}
todo.handle_event(key);
});
app.on_render([&](Frame& frame) {
auto [header, list_area, footer] = Layout::vertical(frame.area(), {
Constraint::fixed(3),
Constraint::fill(),
Constraint::fixed(1),
});
Box()
.border_style(BorderStyle::Rounded)
.title(" Tasks ")
.title_align(TitleAlign::Left)
.fg(Color::Cyan)
.draw(frame, header);
List(todo)
.border_style(BorderStyle::Single)
.highlight_fg(Color::Emerald)
.highlight_symbol("> ")
.draw(frame, list_area);
Text("Navigate: [j/k or Up/Down] | Quit: [q or Ctrl+C]")
.fg(Color::DarkGray)
.draw(frame, footer);
});
auto res = app.run();
if (!res) {
std::fprintf(stderr, "Terminal error: %.*s\n",
static_cast<int>(res.error().message().size()),
res.error().message().data());
return 1;
}
return 0;
}- Compiler: GCC 13+ or Clang 17+ (C++23 standard support required)
- Build System: CMake 3.25+ and Ninja (or Make)
- Target OS: Linux / POSIX-compliant environment
Add koto as a subdirectory or submodule in your CMakeLists.txt:
cmake_minimum_required(VERSION 3.25)
project(my_tui_app LANGUAGES CXX)
set(CMAKE_CXX_STANDARD 23)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
add_subdirectory(koto)
add_executable(my_tui_app src/main.cpp)
target_link_libraries(my_tui_app PRIVATE koto)# Configure and build
cmake -B build -G Ninja -DCMAKE_BUILD_TYPE=Release
cmake --build build --parallel $(nproc)
# Execute automated test suites via CTest
ctest --test-dir build --output-on-failure
# Or run individual modular suites directly
./build/test_headless_widgets
./build/test_headless_layout
./build/test_headless_focus_events
./build/test_headless_render_terminal
./build/test_headless_regressions
./build/test8_text_cjk_emojiThe library includes 46 automated unit, layout, snapshot, and regression tests:
| Test Suite | Tests | Scope |
|---|---|---|
test_headless_widgets |
11 | Rendering, borders, padding, and state behavior for Box, List, Text, TextArea, Tabs, Button, Gauge, Sparkline, and Rule. |
test_headless_layout |
5 | Constraint clamping, zero-allocation compile-time deduction, 2D grids, and C++23 native operations. |
test_headless_focus_events |
8 | Kitty CSI-u decoding, hit-buffer tagging, FocusManager 1D/2D routing, modal focus trapping, and mouse routing. |
test_headless_render_terminal |
6 | Color downscaling, terminal TTY detection, POSIX self-pipe signaling, and differential buffer updates. |
test_headless_regressions |
7 | C1 escape timeout, H3/M2 SIGHUP nohup inheritance, R1 slow paste preservation, R5 truncated input, and Move-only Frame semantics. |
test8_text_cjk_emoji |
9 | UAX-11 widths, 2-column continuation cells, multi-codepoint ZWJ emoji clusters, and grapheme-atomic editing. |
- Compiler Flags: Compiles cleanly with zero warnings under
-Wall -Wextra -Wpedantic -Wconversion -Wsign-conversion -Wsign-compare -Wshadow -Wold-style-cast -D_FORTIFY_SOURCE=2 -O2. - Sanitizers: Validated with zero memory leaks and zero runtime issues under AddressSanitizer (ASan) and UndefinedBehaviorSanitizer (UBSan).
- Release Assertions: Build configurations explicitly undefine
NDEBUGfor test targets (-UNDEBUG), ensuring all assertions actively evaluate in both Release and Debug builds.
The repository contains standalone demo applications demonstrating individual subsystem capabilities:
| Binary | Description |
|---|---|
kotoapp |
Multi-pane workspace featuring List, TextArea, Gauge, and dynamic layout splits. |
test1_tic_tac_toe |
Interactive 2-player board game with keyboard navigation and mouse click hit-testing. |
test2_key_visualizer |
Keystroke inspector reporting modifier bitmasks, Kitty CSI-u codes, and hex codepoints. |
test4_text_input |
Interactive text field with horizontal sliding window scrolling and cursor synchronization. |
test5_yazi |
3-column file manager layout demonstrating parent-child synchronized navigation. |
test7_dashboard |
Systems monitor layout with real-time gauges, sparkline trends, and status tables. |
test9_chess_board |
8x8 chessboard with 2D spatial navigation and piece placement hit-testing. |
test11_text_area |
Multi-line code editor with line number gutter, sticky cursor, and scrolling margins. |
test12_tabs |
Multi-page tab navigation across Bar, Pill, and Underline styles. |
test15_modal_focus_trap |
Modal popup dialog with background click shielding and focus restoration. |
test17_solar_system |
60 FPS ASCII simulation rendering orbital bodies and vector math. |
test18_3d_engine |
Real-time software 3D wireframe rasterizer with rotational matrices. |
Comprehensive documentation, tutorials, and API specifications are available at koto.karmveervaghela.workers.dev:
- Getting Started: System requirements, CMake integration (
FetchContentandfind_package), and first app walkthrough. - Concepts & Architecture: Immediate-mode design, DEC Mode 2026 synchronized updates, differential rendering, and 2D spatial focus routing.
- Widget Catalog: Guides, properties, and examples for all 14 built-in widgets (
Box,Button,Fill,Gauge,HBox,List,Rule,Sparkline,Tabs,TextArea,TextInput,Text,VBox,Clear). - Guides & Recipes: Headless unit testing in CI, keyboard/mouse input decoding, modal dialog traps, and Unicode 15 / CJK IME alignment.
- Deep Dives: 64-byte cache-line
Celllayout, small buffer optimization (SBO), zero-byte clean frames, and terminal troubleshooting. - API Reference: Header-by-header API documentation for
App,Frame,Layout,FocusManager,Terminal,Id, andEvent.
This project is licensed under the MIT License. See LICENSE for details.