Artisanal

About this project:

This library is a faithful port of Charm's TUI libraries (Lip Gloss, Bubble Tea, Bubbles) to Dart. We aim to port as much functionality as possible. In some scenarios, things may not work as expected—please report any issues you discover so we can adjust where necessary.

Many of the included examples were generated and may contain issues or not reflect the latest API. If you find a broken or outdated example, please let us know!

License: MIT Documentation Buy Me A Coffee

A full-stack terminal toolkit for Dart, inspired by popular Go terminal libraries: Lip Gloss (styling), Bubble Tea (TUI framework), and Bubbles (reusable widgets).

Build everything from rich command-line tools to complex interactive TUI applications with a consistent, idiomatic Dart API.

Features

Feature Description
CLI I/O High-level Console helpers for status lines, tables, tasks, prompts, and styled output
Styling Fluent, immutable Style API with colors, borders, padding, margins, and themes
TUI Runtime Elm Architecture (Model/Msg/Cmd) with a full-featured Program event loop
Bubbles 20+ reusable widgets: inputs, lists, tables, spinners, progress bars, file pickers, etc.
Ultraviolet (UV) High-performance cell-buffer renderer with diff-based updates and graphics support
Terminal + Renderer Unified terminal abstraction, ANSI helpers, and renderer backends
Markdown ANSI Markdown renderer plus Glamour high-fidelity output
Charting Sparklines, line/ribbon charts, histograms, heatmaps, and pie charts

Installation

dependencies:
  artisanal: ^0.2.0

Note: This package uses workspace resolution. Use a path or git reference in standalone projects.

If you are building a widget app and do not need the rest of the CLI/style/runtime toolkit from this package, prefer depending on artisanal_widgets directly. Use package:artisanal/... as the umbrella convenience surface when you want the broader stack from a single package.

🖼️ Screenshots

Log Viewer

Console Tags

Layout

Library Exports

Import Purpose
package:artisanal/artisanal.dart Full CLI kit (Console, Style, Terminal, Layout)
package:artisanal/args.dart Command runner utilities (CommandRunner, Command)
package:artisanal/style.dart Styling, Layout, Colors, Borders, Themes
package:artisanal/runtime.dart Focused TEA runtime surface (Model, Msg, Cmd, Program, StringTerminal, runtime messages)
package:artisanal/hosts.dart Terminal backends, bridges, browser/socket hosts
package:artisanal/plugins.dart Stable remote-surface plugin protocol, transport, sessions, and host surface state
package:artisanal/tui.dart TUI runtime: Model, Msg, Cmd, Program
package:artisanal/bubbles.dart Reusable interactive widgets
package:artisanal/terminal.dart Terminal abstraction, ANSI codes, Keys
package:artisanal/app.dart Stable widget app shells, runners, and hosted wrappers
package:artisanal/editors.dart Stable widget text inputs and editors
package:artisanal/selection.dart Stable widget text selection
package:artisanal/testing.dart Stable widget testing helpers
package:artisanal/widgets.dart Stable re-export of the widget framework, including shortcut and zone-hit message support
package:ultraviolet/ultraviolet.dart Low-level cell-buffer renderer
package:artisanal/uv.dart Compatibility re-export for UV (package:ultraviolet/ultraviolet.dart)
package:artisanal/markdown.dart Markdown to ANSI renderer
package:artisanal/glamour.dart High-fidelity Markdown renderer
package:artisanal/charting.dart Charting primitives

For widget work, the package:artisanal/... widget entrypoints are convenience re-exports of the primary package:artisanal_widgets/... libraries. Prefer the direct artisanal_widgets imports when that is the only package your app needs.

Documentation

See the in-repo docs for full coverage:

  • docs/DOCS_INDEX.md

Quick Start: CLI Output

import 'package:artisanal/artisanal.dart';

Future<void> main() async {
  final io = Console();

  io.title('My App');
  io.section('Setup');
  io.info('Checking configuration...');

  await io.task('Running migrations', run: () async {
    await Future.delayed(const Duration(milliseconds: 200));
    return TaskResult.success;
  });

  io.table(
    headers: ['ID', 'Name', 'Status'],
    rows: [
      [1, 'users', io.style.success('DONE')],
      [2, 'posts', io.style.warning('PENDING')],
    ],
  );

  final proceed = io.confirm('Continue?', defaultValue: true);
  if (!proceed) return;

  io.success('All good.');
}

CLI Output

Quick Start: Styling (Lip Gloss)

import 'package:artisanal/style.dart';

final style = Style()
    .bold()
    .foreground(Colors.purple)
    .padding(1, 2)
    .border(Border.rounded);

print(style.render('Hello, Artisanal!'));

Hello artisanal

Style Capabilities

  • Text effects: bold(), italic(), underline(), strikethrough(), dim(), inverse(), blink()
  • Colors: ANSI 16, ANSI 256, TrueColor (RGB), AdaptiveColor (light/dark aware)
  • Spacing: padding(), margin()
  • Borders: rounded, thick, double, hidden, custom
  • Alignment: align(), alignVertical()
  • Dimensions: width(), height(), maxWidth(), maxHeight()
  • Themes: ThemePalette with presets (dark, light, ocean, nord, dracula, monokai, solarized)

Quick Start: TUI (Elm Architecture)

import 'package:artisanal/runtime.dart';

class CounterModel implements Model {
  final int count;
  const CounterModel([this.count = 0]);

  @override
  Cmd? init() => null;

  @override
  (Model, Cmd?) update(Msg msg) {
    return switch (msg) {
      KeyMsg(key: Key(type: KeyType.up)) => (CounterModel(count + 1), null),
      KeyMsg(key: Key(type: KeyType.down)) => (CounterModel(count - 1), null),
      KeyMsg(key: Key(type: KeyType.runes, runes: [0x71])) => (this, Cmd.quit()),
      _ => (this, null),
    };
  }

  @override
  String view() => 'Count: \$count\n\nUse ↑/↓ to change, q to quit';
}

Future<void> main() async {
  await runProgram(CounterModel());
}

Replay + Trace Debugging

The TUI runtime supports deterministic replay (ProgramReplay) and built-in file tracing (TuiTrace) for debugging and profiling.

Enable tracing for any TUI app:

ARTISANAL_TUI_TRACE=1 ARTISANAL_TUI_TRACE_CAPTURE=1 \
ARTISANAL_TUI_TRACE_PATH=traces/my-run.log \
dart run your_app.dart

Structured app/domain events can be emitted via TuiTrace.event(...) and are preserved in replay conversion when they use stable typed type names.

Full replay and tracing documentation: docs/TUI.md.

Bubbles (Reusable Widgets)

Widget Description
TextInputModel Single-line text input
TextAreaModel Multi-line text editing
ListModel Filterable list selection
TableModel Interactive tables
ViewportModel Scrollable content pane
ProgressModel Progress bars with ETA
SpinnerModel Animated loading spinners
FilePickerModel File/directory browser
AnticipateModel Autocomplete with suggestions
WizardModel Multi-step form wizard
SelectModel<T> Single-choice selection prompt
MultiSelectModel<T> Multiple-choice selection
PasswordModel Masked password input
TimerModel Countdown timer
StopwatchModel Elapsed time tracking
PaginatorModel Pagination controls
HelpModel Key binding help views

Command Runner

Build CLI tools with styled help and nested commands:

import 'package:artisanal/args.dart';

class HelloCommand extends Command {
  @override
  String get name => 'hello';
  
  @override
  String get description => 'Say hello';

  @override
  void run() {
    io.success('Hello, world!');
  }
}

void main(List<String> args) async {
  final runner = CommandRunner('my-cli', 'A great CLI');
  runner.addCommand(HelloCommand());
  await runner.run(args);
}

Command Runner

Ultraviolet Renderer

High-performance rendering with diff-based updates for flicker-free TUI applications:

await runProgram(
  MyModel(),
  options: const ProgramOptions(
    useUltravioletRenderer: true,
    useUltravioletInputDecoder: true,
    altScreen: true,
    mouse: true,
  ),
);

UV Features

  • 2D cell buffer with styled cells
  • Diff-based terminal updates (minimal redraws)
  • Layer composition and hit-testing
  • Mouse support and focus events
  • Graphics: Kitty, Sixel, iTerm2, half-block drawing

Console Methods

Category Methods
Output writeln(), write(), title(), section()
Messages line(), info(), comment(), question(), warn(), error(), note(), caution(), alert(), verbose(), debug()
Layout table(), tree(), listing(), twoColumnDetail(), text()
Interactive ask(), confirm(), choice(), secret(), selectChoice(), multiSelectChoice(), menu(), search()
Progress task(), spin(), progress(), progressIterate()

Examples

See the example/ directory for comprehensive demos:

  • main.dart – Full feature showcase
  • fluent_style_example.dart – Style API patterns
  • spinner_demo.dart – Various spinner types
  • lipgloss_table.dart – Styled tables
  • log_viewer_demo.dart – Monitoring dashboard
  • command_center_demo.dart – Multi-panel layouts
  • UV-specific demos now live in pkgs/ultraviolet/example/

Libraries

app
Stable widget app-shell and runner API for composable terminal UIs.
charting
Charting primitives for terminal-native visualizations.
editors
Stable text input and editor API for composable terminal UIs.
glamour
Glamour Markdown Rendering for Dart.
hosts
Stable backend and host entrypoint for interactive terminal apps.
liquid
Liquid tag template adapters for Artisanal.
markdown
Markdown to ANSI terminal rendering.
physics
Physics helpers (Forge2D adapters) for Artisanal.
plugins
Stable protocol entrypoint for out-of-process Artisanal plugins.
runtime
Stable core runtime entrypoint for interactive terminal applications.
scoring
Bayesian match scoring for command palette filtering.
selection
Stable text-selection widget API for composable terminal UIs.
testing
Stable widget testing API for composable terminal UIs.
widgets
Stable high-level widget API for composable terminal UIs.

Core

args Core
Command-line argument parsing and command runners for Artisanal.
artisanal Core
Artisanal: A polished CLI framework for Dart.

Style

style Style
Fluent styling system for terminal text (Lip Gloss for Dart).

Terminal

terminal Terminal
Unified terminal module for artisanal.

TUI

bubbles TUI
Reusable interactive components for Artisanal TUI.
tui TUI
Interactive TUI framework (Bubble Tea for Dart).

Ultraviolet

uv Ultraviolet
Ultraviolet (UV): High-performance terminal rendering and input.