artisanal 0.3.0
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!
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 #



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.');
}

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!'));

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:
ThemePalettewith 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);
}

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 showcasefluent_style_example.dart– Style API patternsspinner_demo.dart– Various spinner typeslipgloss_table.dart– Styled tableslog_viewer_demo.dart– Monitoring dashboardcommand_center_demo.dart– Multi-panel layouts- UV-specific demos now live in
pkgs/ultraviolet/example/