SCIP Index / index (push) Successful in 1m38s
- Add package-map.edn mapping tui.* namespaces to io.github.ajet/clojure-tui - Update CI workflow to pass package-map when generating SCIP index - Enables cross-repo navigation from dependent projects in Sourcegraph Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Clojure TUI
A terminal user interface framework for Clojure, inspired by Bubbletea (Go). Build interactive CLI applications using the Elm Architecture with Hiccup-style views.
Features
- Elm Architecture - Predictable state management with
init,update, andview - Hiccup Views - Declarative UI with familiar Clojure syntax
- Async Commands - Timers, batched operations, and custom async functions
- Rich Styling - Colors (16, 256, true color), bold, italic, underline, and more
- Layout System - Rows, columns, and boxes with borders
- Input Handling - Full keyboard support including arrows, function keys, and modifiers
- Babashka Compatible - Fast startup with Babashka or full Clojure
Quick Start
Installation
Add to your deps.edn:
{:deps {io.github.yourname/clojure-tui {:git/tag "v0.1.0" :git/sha "..."}}}
Hello World
(ns myapp.core
(:require [tui.core :as tui]))
(defn update-fn [model msg]
(if (tui/key= msg "q")
[model tui/quit]
[model nil]))
(defn view [model _size]
[:col
[:text {:fg :cyan :bold true} "Hello, TUI!"]
[:text {:fg :gray} "Press q to quit"]])
(tui/run {:init {}
:update update-fn
:view view})
Output:
Hello, TUI!
Press q to quit
Counter Example
(ns myapp.counter
(:require [tui.core :as tui]))
(defn update-fn [model msg]
(cond
(tui/key= msg "q") [model tui/quit]
(tui/key= msg "k") [(inc model) nil]
(tui/key= msg "j") [(dec model) nil]
(tui/key= msg "r") [0 nil]
:else [model nil]))
(defn view [model _size]
[:col
[:box {:border :rounded :padding [0 2]}
[:text {:fg :yellow :bold true} (str "Count: " model)]]
[:text {:fg :gray} "j/k: change r: reset q: quit"]])
(tui/run {:init 0
:update update-fn
:view view})
Output:
╭──────────────╮
│ Count: 0 │
╰──────────────╯
j/k: change r: reset q: quit
Examples
Counter
Simple counter demonstrating basic Elm Architecture.
bb counter
Timer
Countdown timer with pause/resume - demonstrates async commands.
bb timer
List Selection
Multi-select list with cursor navigation.
bb list
Spinner
Animated loading spinners with multiple styles.
bb spinner
Views
State machine pattern with multiple views and navigation.
bb views
HTTP
Async HTTP requests with loading states.
bb http
Running Examples
Run examples with Babashka (recommended for fast startup):
bb counter
bb timer
Or with full Clojure:
clojure -A:dev -M -m examples.counter
Documentation
- Getting Started - Installation, first app, core concepts
- Hiccup Views - View elements, styling, and layout
- API Reference - Complete API documentation
- Examples - Annotated example applications
Architecture
View (hiccup) → Render (ANSI string) → Terminal (raw mode I/O)
↑ │
│ v
Model ←──────── Update ←─────────── Input (key parsing)
The application follows the Elm Architecture:
- Model - Your application state (any Clojure data structure)
- Update - A pure function
(fn [model msg] [new-model cmd])that handles messages - View - A pure function
(fn [model size] hiccup)that renders the UI, wheresizeis{:width w :height h}
Hiccup View Elements
| Element | Description | Example |
|---|---|---|
:text |
Styled text | [:text {:fg :red :bold true} "Error"] |
:row |
Horizontal layout | [:row "Left" "Right"] |
:col |
Vertical layout | [:col "Line 1" "Line 2"] |
:box |
Bordered container | [:box {:border :rounded} "Content"] |
:space |
Empty space | [:space {:width 5}] |
Commands
Commands are returned from your update function to trigger side effects:
| Command | Description |
|---|---|
tui/quit |
Exit the application |
(tui/after ms msg) |
Send msg after ms milliseconds |
(tui/batch c1 c2) |
Run commands in parallel |
(tui/sequentially c1 c2) |
Run commands sequentially |
(fn [] msg) |
Custom async function returning a message |
Key Matching
(tui/key= msg "q") ;; Character
(tui/key= msg :enter) ;; Special key
(tui/key= msg :up) ;; Arrow
(tui/key= msg [:ctrl \c]) ;; Control combo
(tui/key= msg [:alt \x]) ;; Alt combo
Project Structure
src/
tui/
core.clj # Main runtime (Elm architecture + async commands)
render.clj # Hiccup → ANSI
terminal.clj # Raw mode, input/output
input.clj # Key parsing
ansi.clj # ANSI codes, colors
examples/
counter.clj
timer.clj
list_selection.clj
spinner.clj
views.clj
http.clj
License
MIT
Description
Languages
Clojure
100%





