Files
2026-01-23 07:56:25 -05:00

2.4 KiB

CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

Project Overview

Clojure TUI framework inspired by Bubbletea (Go), using the Elm Architecture with Hiccup for views. Works with both Babashka and full Clojure.

Commands

# Run tests
bb test

# List available examples
bb examples

# Run examples with Babashka (recommended - fast startup)
bb counter
bb timer
bb list
bb spinner
bb views
bb http

# Run examples with full Clojure
clojure -A:dev -M -m examples.counter

Architecture

View (hiccup) → Render (ANSI string) → Terminal (raw mode I/O)
     ↑                                        |
     |                                        v
   Model  ←──────── Update ←─────────── Input (key parsing)

Core Modules

  • tui.core - Main runtime with core.async. Manages the event loop, executes commands (quit, after, batch, seq), handles input via goroutines.
  • tui.render - Converts hiccup ([:col [:text "hi"]]) to ANSI strings. Handles :text, :row, :col, :box, :space elements.
  • tui.terminal - Platform abstraction: raw mode via stty, reads from /dev/tty, renders by printing ANSI.
  • tui.input - Parses raw bytes into key messages ([:key {:char \a}], [:key :up], [:key {:ctrl true :char \c}]).
  • tui.ansi - ANSI escape codes, colors, box-drawing characters, string utilities.

Elm Architecture Flow

  1. App provides :init (model), :update (fn [model msg] -> [new-model cmd]), :view (fn [model size] -> hiccup)
  2. Runtime renders initial view
  3. Input loop reads keys, puts messages on channel
  4. Update function processes messages, may return commands
  5. Commands execute async (timers, batches), put results back on channel
  6. Loop until [:quit] command

Command Types

  • tui/quit - Exit
  • (tui/after ms msg) - Send msg after delay (for timers, animations)
  • (tui/batch cmd1 cmd2) - Parallel execution
  • (tui/sequentially cmd1 cmd2) - Sequential execution
  • (fn [] msg) - Custom async returning a message

Testing Philosophy

  • E2E tests: Small number of integration tests to verify the full stack works (terminal init → input → update → render → cleanup)
  • Unit tests: Cover all engine behavior for rendering (hiccup→ANSI), input handling (byte sequences→key messages), and model/command interactions