yoxterm

CI pub CRAP score (max)

yoxterm is a high-performance terminal emulator for Flutter — a performance-focused fork of xterm.dart (MIT, © xuty). It keeps the upstream API and feature set (VT100/xterm emulation, CJK & emoji, IME, shortcuts, mobile and desktop) and rebuilds the hot paths: parsing, painting and scrolling.

Requires Flutter >= 3.33.0

Why yoxterm over xterm.dart

Measured by flutter test test/src/ui/perf_benchmark_test.dart and test/src/ui/draw_ops_bench_test.dart (Apple Silicon; absolute numbers are machine-dependent, the deltas are not):

Hot path upstream-style yoxterm
Plain-text parse flood 73.9 MB/s (byte-at-a-time parser) 98.3 MB/s (+33%) parser bypass fast path
Canvas ops per htop frame (1920 cells) 1714 (218 rects + 1496 paragraphs) 49 (~35× fewer) run merging + glyph atlas
Frame paint under output flood — 49 µs/frame atlas hits, no layout
Idle frame repaint — 45 µs/frame recorded-op replay, zero rebuilds

What changed under the hood:

  • Glyph-atlas renderer — glyphs are rasterized once into a texture atlas and emitted as batched drawRawAtlas sprite calls instead of one Paragraph per text run. Box-drawing characters are painted procedurally.
  • Pooled paint ops — per-line paint operations are recorded once and replayed for unchanged lines; evicted ops are recycled through an object pool (XRecycler-style) instead of being re-allocated every frame.
  • Parser bypass fast path — plain-text chunks without control characters skip the escape parser entirely; scrollback lines are recycled rather than re-allocated.
  • Listener fast paths — observable terminal notifications avoid allocation and iteration overhead when nothing is subscribed.
  • Output paint throttle — painting is capped at display refresh instead of repainting on every PTY read, so a 120 Hz ProMotion display does not double the paint work.
  • Quality ratchet — CI and a pre-commit hook enforce flutter analyze, the full test suite (~1300 tests) and a crap4dart CRAP gate (threshold 61, current max 59) so performance debt cannot grow back.

Screenshots

Features

  • 📦 Works out of the box — no special configuration required.
  • 🚀 Fast — glyph-atlas rendering, pooled paint ops, parser fast paths.
  • 😀 Wide character support — CJK and emojis.
  • ✂️ Customizable — themes, terminal text style, shortcuts.
  • ✔ Frontend independent — the terminal core works without the Flutter frontend (headless testing, server-side emulation).
  • 📱 Mobile and desktop — IME integration, keyboard shortcuts, pointer input.

Getting started

1. Add the dependency:

dependencies:
  yoxterm: ^4.0.0

2. Create the terminal:

import 'package:yoxterm/xterm.dart';

terminal = Terminal();

terminal.onOutput = (output) {
  print('output: $output');
};

3. Attach a view:

child: TerminalView(terminal),

4. Write to the terminal:

terminal.write('Hello, world!');

Done!

More examples

yoxterm powers the terminal panels of YoLoIT, a CLI-first desktop workspace — that is where the performance work originates.

Contributing

Feature requests and bugs: issue tracker.

Development setup:

git config core.hooksPath scripts   # enables the pre-commit gate
flutter test
flutter test test/src/ui/perf_benchmark_test.dart  # throughput numbers

The pre-commit hook runs flutter analyze, flutter test --coverage and the crap4dart CRAP ratchet. If a change legitimately improves the max CRAP score, lower the threshold in crap4dart.yaml — never raise it to make a regression pass.

License

MIT. Based on xterm.dart by xuty and the TerminalStudio contributors.