portable_pty 0.0.2 copy "portable_pty: ^0.0.2" to clipboard
portable_pty: ^0.0.2 copied to clipboard

Cross-platform pseudo-terminal (PTY) for Dart. Spawns shell subprocesses on Linux, macOS, and Windows via a Rust native library. On web, connects through WebSocket or WebTransport to a remote PTY server.

portable_pty #

CI pub package License: MIT

Cross-platform pseudo-terminal (PTY) for Dart. Spawn shell subprocesses on Linux, macOS, and Windows with full terminal I/O — or connect to a remote PTY server on the web via WebSocket / WebTransport.

Features #

  • Native PTYforkpty / openpty on Unix, ConPTY on Windows, via a Rust native library (portable-pty).
  • Web transport — plug in WebSocket, WebTransport, or any custom PortablePtyTransport to talk to a server-side PTY from the browser.
  • Unified API — same PortablePty / PortablePtyController interface regardless of platform.
  • Synchronous read/write for low-latency integrations.
  • Window resize, mode queries, and explicit lifecycle management.

Platform support #

Platform Backend Build toolchain
Linux Native PTY (Rust) Rust (or prebuilt)
macOS Native PTY (Rust) Rust (or prebuilt)
Windows ConPTY (Rust) Rust (or prebuilt)
Android Native PTY (Rust) Rust + cross (or prebuilt)
iOS Static lib (Rust) Rust (or prebuilt)
Web WebSocket / WebTransport None (pure Dart)

Installation #

dependencies:
  portable_pty: ^0.0.2

The Rust native library is compiled automatically by a Dart build hook using native_toolchain_rust. You need Rust ≥ 1.92 installed.

Tip: If you don't want to install Rust, download a prebuilt library instead.

Quick start #

import 'package:portable_pty/portable_pty.dart';

void main() {
  final pty = PortablePty.open(rows: 24, cols: 80);
  pty.spawn('/bin/sh', args: ['-c', 'echo hello from portable_pty']);

  final out = pty.readSync(4096);
  print(String.fromCharCodes(out));

  print('pid: ${pty.childPid}');
  print('mode: ${pty.getMode()}');

  pty.close();
}

API overview #

Opening a PTY #

final pty = PortablePty.open(
  rows: 24,
  cols: 80,
  // Web-only options:
  webSocketUrl: 'ws://localhost:8080/pty',
  // webTransportUrl: 'https://localhost:4433/pty',
  // transport: MyCustomTransport(),
);

Spawning a process #

pty.spawn('/bin/bash', args: ['-l']);
pty.spawn('cmd.exe');  // Windows

Reading & writing #

// Synchronous
final bytes = pty.readSync(4096);
pty.writeString('ls -la\n');
pty.writeBytes(Uint8List.fromList([0x03]));  // Ctrl+C

// Written byte count
final n = pty.writeString('echo hello\n');
print('wrote $n bytes');

Window resize #

pty.resize(rows: 40, cols: 120);

PTY mode #

final mode = pty.getMode();
print('canonical: ${mode.canonical}, echo: ${mode.echo}');

Process lifecycle #

print('running: ${pty.childPid}');

final exitCode = pty.tryWait();   // non-blocking, returns null if still running
print('exited: $exitCode');

pty.kill();    // SIGKILL
pty.close();   // close file descriptors

Controller (with buffered output) #

final controller = PortablePtyController(
  rows: 24,
  cols: 80,
  defaultShell: '/bin/bash',
);

await controller.start();
controller.write('ls\n');
final output = controller.readOutput();
print(output);

await controller.stop();
controller.dispose();

Prebuilt libraries #

Prebuilt binaries for every platform are attached to each GitHub release.

The easiest way to get them is the built-in setup command:

dart run portable_pty:setup

This downloads the correct library for your host platform into .prebuilt/<platform>/ at your project root. The build hook will find it automatically — no Rust install required.

You can also specify a release tag or target platform:

dart run portable_pty:setup --tag v0.0.2 --platform macos-arm64

Monorepo users can download all prebuilt libs at once:

dart run tool/prebuilt.dart --tag v0.0.2 --lib pty

You can also set the PORTABLE_PTY_PREBUILT environment variable to point directly at a prebuilt library file.

Tip: Add .prebuilt/ to your .gitignore.

Web usage #

Browsers cannot spawn OS processes. On web, portable_pty connects to a remote PTY server over WebSocket or WebTransport.

┌──────────────┐       ws / webtransport       ┌──────────────┐
│  Browser app │  ◄──────────────────────────►  │  PTY server  │
│  (Dart web)  │                                │  (any lang)  │
└──────────────┘                                └──────────────┘
final pty = PortablePty.open(
  rows: 24,
  cols: 80,
  webSocketUrl: 'ws://localhost:8080/pty',
);
pty.spawn('ws://localhost:8080/pty');
pty.writeString('echo hello\n');

Custom transport #

Implement PortablePtyTransport for any protocol (SSH, proprietary, etc.):

class MySshTransport implements PortablePtyTransport {
  @override
  void write(Uint8List data) { /* ... */ }

  @override
  Uint8List readSync(int maxBytes) { /* ... */ }

  // ...
}

final pty = PortablePty.open(transport: MySshTransport());
Package Description
portable_pty_flutter Flutter ChangeNotifier controller for PTY sessions
ghostty_vte Terminal VT engine — paste safety, OSC/SGR parsing, key encoding
ghostty_vte_flutter Flutter terminal widgets powered by Ghostty

License #

MIT — see LICENSE.

0
likes
0
points
60
downloads

Publisher

unverified uploader

Weekly Downloads

Cross-platform pseudo-terminal (PTY) for Dart. Spawns shell subprocesses on Linux, macOS, and Windows via a Rust native library. On web, connects through WebSocket or WebTransport to a remote PTY server.

Homepage
Repository (GitHub)
View/report issues

Topics

#terminal #pty #ffi #shell #process

License

unknown (license)

Dependencies

code_assets, ffi, hooks, native_toolchain_rust, web

More

Packages that depend on portable_pty