libghostty

pub package GitHub Actions Sponsor

Dart bindings to libghostty-vt, the terminal emulator library from Ghostty.

Android iOS macOS Linux Windows Web

Getting started

# pubspec.yaml
dependencies:
  libghostty: ^0.0.12

On web, initialize the WASM module once before using any bindings:

await initializeForWeb(Uri.parse('assets/libghostty.wasm'));

Usage

Terminal

Terminal emulator with screen state, scrollback, cursor, styles, modes, and VT stream processing. Register effect callbacks for PTY writes, bell, title changes, and more.

Effects run synchronously during write and callback-emitting resize calls. If one or more effects throw, that call finishes processing, notifies its listeners, and then rethrows its first failure with the original stack. Catch the initiating call when the host needs to recover.

import 'dart:typed_data';
import 'package:libghostty/libghostty.dart';

void main() {
  final terminal = Terminal(cols: 80, rows: 24);

  // Register effects (callbacks invoked synchronously during write).
  terminal.onWritePty = (data) => pty.write(data);
  terminal.onBell = () => playSound();
  terminal.onTitleChanged = () => print('Title: ${terminal.title}');

  // Write VT data and resize.
  terminal.write(Uint8List.fromList(vtData));
  terminal.resize(cols: 120, rows: 40, cellWidthPx: 8, cellHeightPx: 16);

  // Read a single cell via grid reference (for ad-hoc lookups).
  final ref = GridRef.at(terminal, const Position(row: 0, col: 0));
  print(ref.content); // the character at (0, 0)

  // Read screen via render state and reusable iterators.
  final renderState = RenderState();
  final rows = RowIterator();
  final cells = CellIterator();

  renderState.update(terminal);
  rows.reset(renderState);
  while (rows.next()) {
    cells.reset(rows);
    while (cells.next()) {
      if (cells.hasText) print(cells.content);
    }
    rows.dirty = false;
  }
  renderState.dirty = DirtyState.clean;

  cells.dispose();
  rows.dispose();
  renderState.dispose();
  terminal.dispose();
}

Key encoding

Encode key events into terminal escape sequences, supporting legacy and Kitty keyboard protocol.

final encoder = KeyEncoder();
final event = KeyEvent()
  ..mods = const .ctrl()
  ..action = .press
  ..key = .c;

encoder.sync(terminal); // pick up mode changes before encoding
final encoded = encoder.encode(event);
if (encoded.isNotEmpty) pty.write(utf8.encode(encoded));

event.dispose();
encoder.dispose();

Mouse encoding

Encode mouse events into escape sequences, supporting X10, UTF-8, SGR, URxvt, and SGR-Pixels protocols.

final encoder = MouseEncoder()
  ..setSize(const MouseEncoderSize(
    screenWidth: 640,
    screenHeight: 384,
    cellWidth: 8,
    cellHeight: 16,
  ));

final event = MouseEvent()
  ..action = .press
  ..button = .left
  ..setPosition(x: 10.0, y: 5.0);

encoder.sync(terminal); // pick up tracking-mode changes before encoding
final encoded = encoder.encode(event);
if (encoded.isNotEmpty) pty.write(utf8.encode(encoded));

event.dispose();
encoder.dispose();

Formatting

Format terminal content as plain text, VT sequences, or HTML.

final formatter = Formatter(terminal: terminal, format: .plain);
print(formatter.format());
formatter.dispose();

SGR and OSC parsing

Parse SGR (Select Graphic Rendition) parameters into typed attributes and OSC (Operating System Command) sequences from a byte stream.

// SGR: parse Select Graphic Rendition parameters.
final sgr = SgrParser();
for (final attr in sgr.parse([1, 38, 2, 255, 0, 0])) {
  switch (attr.tag) {
    case .bold:
      print('bold');
    case .directColorFg:
      print('fg: ${attr.color}');
    default:
      break;
  }
}
sgr.dispose();

// OSC: parse Operating System Command sequences.
final osc = OscParser();
osc.feedBytes(utf8.encode('0;My Title'));
final command = osc.end(0x07);
print(command.type);        // OscCommandType.changeWindowTitle
print(command.windowTitle); // My Title
osc.dispose();

Paste validation

Check paste data for unsafe sequences (newlines, bracketed paste escapes) before writing to the terminal.

pasteIsSafe('hello');           // true
pasteIsSafe('rm -rf /\n');      // false
pasteIsSafe('\x1b[201~inject'); // false

Libraries

libghostty
Terminal emulation powered by libghostty.