Cliux — styled terminal output made simple

cliux is a lightweight Rust crate for styling terminal output — no TUI required. It’s a toolkit for making CLI output look clean, expressive, and readable using structured components.

I built cliux because the output in one of my Rust projects felt flat and hard to scan. So I created a crate that adds layout and clarity without needing a full TUI framework.

Features

  • Boxed — bordered containers with titles and content
  • Section — titled blocks with horizontal dividers
  • Divider — customizable horizontal lines
  • .wrap() — wraps long text to fit the width
  • .pad() — emoji-aware padding for alignment

Example

use cliux::Boxed;

fn main() {
    Boxed::new("Cliux Boxed")
        .content("This code uses the cliux library to create a boxed section.")
        .width(61)
        .print();
}

Output:

Boxed component

Links

Github Repo
Crates.io

Any feedback, ideas, or contributions are welcome!

Restored this, open to hear what people think.

cliux v0.2.0 has been released, with a Label component and styles using ansi_term.

Example:

use cliux::Label;

fn main() {
    Label::new("INFO").style("info").print();
    Label::new("✓ Done").style("success").print();
    Label::new("ERROR").style("error").print();

    let inline = Label::new("DEBUG").color("cyan").bold(true).inline();
    println!("Inline label: {}", inline);
}

Output:

Label Component

Suggestions for more components or features are welcome.

cliux v0.3.0 has been released, with two new components: Tag and List.

  • Tag lets you display inline status markers like (beta) or {admin} with color and style.
  • List renders bullet-pointed or numbered lists with optional wrapping.

Example:

use cliux::{Tag, List};

fn main() {
    Tag::new("beta").rounded().color("yellow").bold(true).print();
    Tag::new("admin").curly().color("red").print();
    Tag::new("draft").print();

    List::new(vec!["First item", "Second item", "Third item"])
        .bullet("*")
        .width(40)
        .print();

    List::new(vec!["One", "Two", "Three"])
        .numbered()
        .print();
}

Output:

List Component

Tag Component

Suggestions for more components or features are welcome.

The field numbered: bool in List is superfluous. You can determine whether it's a numbered or bullet list by determining whether bullet is None or not.

Thanks for pointing that out. I refactored it before publishing v0.4.0, which is now the latest version.

cliux v0.4.0 has been released, with two new components: Table and Note, and a small internal refactor to List.

  • Table renders structured rows and columns with optional headers, borders, and custom widths.
  • Note displays styled callouts for tips, warnings, and info blocks — with emoji, color, and border styles.
  • List has been internally cleaned up: it now infers numbering from bullet = None.

Example:

use cliux::{Table, Note};

fn main() {
    Table::new()
        .headers(&["Name", "Status"])
        .row(&["cliux", "active"])
        .row(&["other", "pending"])
        .widths(&[20, 10])
        .bordered(true)
        .print();

    Note::new("Be careful with this setting.")
        .kind("warning")
        .style("rounded")
        .width(40)
        .print();

    Note::new("Tip: You can use --force here.")
        .kind("info")
        .style("+")
        .width(40)
        .print();
}

Output:

Table Component

Note Component

emoji rendering might be different across terminals, if alignment is off, try monospace-safe symbols like !, *, or i.

Suggestions for more components or features are welcome.

This is a nice little TUI library btw. And sorry for the nitpicking yesterday. I didn't read correctly and assumed this was a request for a code review. :smiley:

1 Like

Thanks for the compliment. Nice to know you found it interesting.

cliux v0.5.0 has been released, with two new components Input and Confirm.

Examples:

Input:

use cliux::Input;

fn main() {
    let name = Input::new("What's your name?")
        .default("Anonymous")
        .bold(true)
        .color("cyan")
        .style("rounded")
        .width(40)
        .prompt();

    println!("Hello, {}!", name);
}

Confirm:

use cliux::Confirm;

fn main() {
    let confirmed = Confirm::new("Delete file?")
        .color("red")
        .bold(true)
        .style("square")
        .width(40)
        .default(false)
        .prompt();

    if confirmed {
        println!("File deleted.");
    } else {
        println!("Operation cancelled.");
    }
}

Output:

Input Component

Confirm Component