<p align="center">
<img src="https://raw.githubusercontent.com/moltenlabs/cauldron/main/.github/assets/banner.png" alt="Cauldron" width="100%" />
</p>
<h1 align="center">๐ฎ Cauldron</h1>
<p align="center">
<strong>A powerful TUI framework based on The Elm Architecture.</strong>
</p>
<p align="center">
<a href="https://crates.io/crates/cauldron"><img src="https://img.shields.io/crates/v/cauldron.svg?style=flat-square&logo=rust" alt="Crates.io"></a>
<a href="https://docs.rs/cauldron"><img src="https://img.shields.io/docsrs/cauldron?style=flat-square&logo=docs.rs" alt="Documentation"></a>
<a href="https://github.com/moltenlabs/cauldron/actions"><img src="https://img.shields.io/github/actions/workflow/status/moltenlabs/cauldron/ci.yml?style=flat-square&logo=github" alt="CI"></a>
<a href="#license"><img src="https://img.shields.io/badge/license-MIT%2FApache--2.0-blue?style=flat-square" alt="License"></a>
</p>
<p align="center">
<a href="#features">Features</a> โข
<a href="#installation">Installation</a> โข
<a href="#quick-start">Quick Start</a> โข
<a href="#the-elm-architecture">Architecture</a> โข
<a href="#ecosystem">Ecosystem</a>
</p>
---
## What is Cauldron?
**Cauldron** is the Rust equivalent of [bubbletea](https://github.com/charmbracelet/bubbletea) from Charmbracelet. It provides a simple, functional approach to building terminal user interfaces using The Elm Architecture.
```rust
use cauldron::{App, Model, Command, Event, Key};
struct Counter { count: i32 }
enum Msg { Increment, Decrement, Quit }
impl Model for Counter {
type Message = Msg;
fn update(&mut self, msg: Msg) -> Command<Msg> {
match msg {
Msg::Increment => self.count += 1,
Msg::Decrement => self.count -= 1,
Msg::Quit => return Command::quit(),
}
Command::none()
}
fn view(&self) -> String {
format!(
"๐ฎ Count: {}\n\n Press +/- to change\n Press q to quit",
self.count
)
}
fn handle_event(&self, event: Event) -> Option<Msg> {
match event {
Event::Key(Key::Char('+')) => Some(Msg::Increment),
Event::Key(Key::Char('-')) => Some(Msg::Decrement),
Event::Key(Key::Char('q')) => Some(Msg::Quit),
Event::Key(Key::Esc) => Some(Msg::Quit),
_ => None,
}
}
}
fn main() {
App::new(Counter { count: 0 }).run().unwrap();
}
```
---
## Features
<table>
<tr>
<td width="50%">
### ๐๏ธ Elm Architecture
- **Model** - Your application state
- **Message** - Events that update state
- **Update** - Pure state transitions
- **View** - Render to terminal
</td>
<td width="50%">
### โก Simple API
```rust
impl Model for App {
fn update(&mut self, msg: Msg) -> Command<Msg>;
fn view(&self) -> String;
}
```
</td>
</tr>
<tr>
<td width="50%">
### ๐ฑ๏ธ Input Handling
- Keyboard events
- Mouse support (optional)
- Bracketed paste mode
- Focus events
</td>
<td width="50%">
### ๐จ Styling Integration
```rust
use glyphs::{style, Color};
fn view(&self) -> String {
style("Hello!")
.fg(Color::from_hex("#F97316"))
.bold()
.to_string()
}
```
</td>
</tr>
</table>
---
## Installation
```bash
cargo add cauldron
```
Or add to your `Cargo.toml`:
```toml
[dependencies]
cauldron = "0.1"
```
---
## Quick Start
### 1. Define Your Model
```rust
struct TodoList {
items: Vec<String>,
selected: usize,
}
```
### 2. Define Your Messages
```rust
enum Msg {
MoveUp,
MoveDown,
Delete,
Quit,
}
```
### 3. Implement the Model Trait
```rust
use cauldron::{Model, Command, Event, Key};
impl Model for TodoList {
type Message = Msg;
fn update(&mut self, msg: Msg) -> Command<Msg> {
match msg {
Msg::MoveUp => {
if self.selected > 0 {
self.selected -= 1;
}
}
Msg::MoveDown => {
if self.selected < self.items.len().saturating_sub(1) {
self.selected += 1;
}
}
Msg::Delete => {
if !self.items.is_empty() {
self.items.remove(self.selected);
if self.selected >= self.items.len() {
self.selected = self.items.len().saturating_sub(1);
}
}
}
Msg::Quit => return Command::quit(),
}
Command::none()
}
fn view(&self) -> String {
let mut s = String::from("๐ Todo List\n\n");
for (i, item) in self.items.iter().enumerate() {
if i == self.selected {
s.push_str(&format!(" > {}\n", item));
} else {
s.push_str(&format!(" {}\n", item));
}
}
s.push_str("\nโ/โ: navigate d: delete q: quit");
s
}
fn handle_event(&self, event: Event) -> Option<Msg> {
match event {
Event::Key(Key::Up) => Some(Msg::MoveUp),
Event::Key(Key::Down) => Some(Msg::MoveDown),
Event::Key(Key::Char('d')) => Some(Msg::Delete),
Event::Key(Key::Char('q')) | Event::Key(Key::Esc) => Some(Msg::Quit),
_ => None,
}
}
}
```
### 4. Run It
```rust
fn main() {
let app = TodoList {
items: vec![
"Build cauldron".into(),
"Write documentation".into(),
"Ship it!".into(),
],
selected: 0,
};
cauldron::run(app).unwrap();
}
```
---
## The Elm Architecture
Cauldron follows The Elm Architecture (TEA), a pattern for building interactive programs:
```
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ โ
โ โโโโโโโโโโโ โโโโโโโโโโโโ โโโโโโโโโโโ โ
โ โ Event โโโโโถโ Update โโโโโถโ Model โ โ
โ โโโโโโโโโโโ โโโโโโโโโโโโ โโโโโโฌโโโโโ โ
โ โ โ
โ โผ โ
โ โโโโโโโโโโโ โ
โ โ View โ โ
โ โโโโโโฌโโโโโ โ
โ โ โ
โ โผ โ
โ โโโโโโโโโโโ โ
โ โ Terminalโ โ
โ โโโโโโโโโโโ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
```
1. **Events** come from user input (keyboard, mouse)
2. **Update** transforms events into state changes
3. **Model** holds your application state
4. **View** renders the model to a string
5. **Terminal** displays the view
---
## Commands
Commands let you perform side effects:
```rust
// Do nothing
Command::none()
// Quit the application
Command::quit()
// Send a message
Command::message(Msg::DataLoaded(data))
// Batch multiple commands
Command::batch(vec![cmd1, cmd2, cmd3])
// Async task (coming soon)
Msg::DataLoaded(data)
})
```
---
## App Builder
Use the `App` builder for more control:
```rust
use cauldron::App;
App::new(my_model)
.with_mouse() // Enable mouse support
.inline() // Don't use alternate screen
.show_cursor() // Keep cursor visible
.with_bracketed_paste() // Enable bracketed paste
.run()
.unwrap();
```
---
## Ecosystem
Cauldron is part of the **Molten Labs** open source ecosystem:
| **[molten_brand](https://crates.io/crates/molten_brand)** | Design tokens & colors | โ
Published |
| **[glyphs](https://crates.io/crates/glyphs)** | ANSI escape sequences | โ
Published |
| **[lacquer](https://crates.io/crates/lacquer)** | Terminal styling | โ
Published |
| **[cauldron](https://crates.io/crates/cauldron)** | TUI framework (you are here) | โ
Published |
| **sparks** | TUI components | ๐ง Coming Soon |
| **rune** | Shell glamour | ๐ง Coming Soon |
---
## Why "Cauldron"?
In the forge, a **cauldron** is where raw materials are melted and transformed into something new. Cauldron transforms your application state through pure functions, bubbling up beautiful terminal interfaces. ๐ฎ
---
## Contributing
We welcome contributions! Please see [CONTRIBUTING.md](CONTRIBUTING.md) for guidelines.
```bash
git clone https://github.com/moltenlabs/cauldron
cd cauldron
cargo test
```
---
## License
Licensed under either of:
- Apache License, Version 2.0 ([LICENSE-APACHE](LICENSE-APACHE))
- MIT license ([LICENSE-MIT](LICENSE-MIT))
at your option.
---
<p align="center">
<sub>Built with ๐ฎ by <a href="https://github.com/moltenlabs">Molten Labs</a></sub>
</p>
<p align="center">
<sub><i>"Let them cook."</i></sub>
</p>