Model — a single object that holds all application state — combined with three pure functions: init, update, and view.
How it works
- Init runs once at startup, returning an optional
Commandto kick off I/O or timers. - The main loop feeds
Messagevalues (key presses, timer ticks, window resize events, etc.) intoupdate. - Update returns the next model state plus an optional
Commandfor any side effects. - The main loop calls
viewon the updated model and redraws the terminal.
QuitMessage command.
The three methods
init()
Called exactly once when the program starts. Return a Command to schedule the first piece of async work, or null (or Command.none()) if no startup I/O is needed.
update(Message msg)
Receives every event — key presses, timer ticks, window size changes, custom messages — and returns an UpdateResult pairing the next model state with an optional follow-up Command.
UpdateResult.from(model) is shorthand for UpdateResult.from(model, null). Both forms are
equivalent — a null command is treated as a no-op.view()
Converts the current model state into a plain String. TUI4J computes a diff against the previous frame and redraws only what changed.
view() must be a pure function — no side effects, no I/O. Everything that mutates state belongs in update.
Minimal complete example
The example below implements a simple counter. Press+ to increment, - to decrement, and q to quit.
How commands flow back into the loop
ACommand is a @FunctionalInterface (specifically () -> Message). When update returns one, the runtime executes it on a background thread, then delivers the resulting Message back into the main loop — which calls update again.
This means all side effects (HTTP calls, file I/O, timers) happen outside of update, keeping the update logic synchronous and testable.
Comparison with Bubble Tea (Go)
TUI4J is a direct port of Bubble Tea. The core concepts are identical; only the syntax differs.Program
How to instantiate and run a TUI4J program.
Messages and commands
All built-in messages and how to create custom ones.