artisanal 0.3.0 copy "artisanal: ^0.3.0" to clipboard
artisanal: ^0.3.0 copied to clipboard

A full-stack terminal toolkit for Dart featuring Lip Gloss styling, Bubble Tea TUI architecture, and Ultraviolet rendering.

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/
2
likes
160
points
586
downloads

Documentation

API reference

Publisher

unverified uploader

Weekly Downloads

A full-stack terminal toolkit for Dart featuring Lip Gloss styling, Bubble Tea TUI architecture, and Ultraviolet rendering.

Repository (GitHub)
View/report issues

Topics

#cli #tui #terminal

Funding

Consider supporting this project:

www.buymeacoffee.com

License

MIT (license)

Dependencies

acanthis, args, artisanal_widgets, chalkdart, characters, forge2d, highlight, html, html_unescape, image, json_schema_builder, liquify, markdown, meta, path, petitparser, ultraviolet

More

Packages that depend on artisanal