Skip to main content

stitch-pty

Cross-platform async PTY with integrated terminal emulation for Python.

CI PyPI crates.io Python Rust License

stitch-pty is a high-performance, cross-platform pseudo-terminal (PTY) library for Python, written in Rust with PyO3 bindings. It provides true PTY semantics on Linux, macOS, and Windows, with a built-in VT100/VT220/xterm-compatible terminal emulator for rendering ANSI escape sequences with scrollback history.


Why stitch-pty?

Feature stitch-pty pty stdlib pexpect
Cross-platform ✅ Linux / macOS / Windows ❌ POSIX only ❌ POSIX only
Async I/O ✅ Native asyncio ❌ Blocking ❌ Blocking
Zero GIL contention ✅ PyO3 native async
Terminal emulation ✅ Built-in (scrollback + styled viewport)
No zombie processes ✅ Background reaping (50ms polling) ⚠️ Manual ⚠️ Manual
Type-safe Python API ✅ Full mypy support

Table of Contents


Quick Start

import asyncio
from stitch_pty import spawn

async def main():
    # Spawn a shell in a real PTY
    session = await spawn("bash", ["-i"])

    # Read output (auto-fed into the terminal emulator)
    data = await session.read(4096)
    print(session.display)          # visible screen → list[str]
    print(session.scrollback)       # scrollback history → list[str]
    print(session.full_display)     # history + visible → list[str]

    # Write to the PTY
    await session.write(b"echo hello from stitch-pty\n")

    # Resize the terminal
    session.resize(50, 120)

    # Graceful shutdown
    await session.terminate(5.0)

asyncio.run(main())

Installation

pip install stitch-pty

Pre-built wheels are available for:

Platform Architectures
Linux x86_64, aarch64 (manylinux_2_28)
macOS x86_64, arm64 (universal2)
Windows x86_64

Requirements: Python ≥ 3.12


API Reference

Core Functions

spawn(program, args=None, env=None, winsize=None) → PtySession

Spawn a program in a PTY and return a session handle.

Parameter Type Default Description
program str The executable to run
args list[str] [] Command-line arguments
env dict[str, str] None Environment variables (inherits from parent if None)
winsize Winsize | None Auto-detected Initial terminal size (defaults to 24×80)

Returns: PtySession — a combined PTY I/O + child process manager with integrated terminal emulation.

Example:

session = await spawn("python3", ["-c", "print('hello')"])
output = await session.interact()
print(output.decode())  # b"hello\n"

open_pty(winsize=None) → PtyMaster

Async. Opens a PTY pair without spawning a child process.

Parameter Type Default Description
winsize Winsize | None 24×80 Terminal size

Returns: PtyMaster — raw PTY I/O handle (no terminal emulation, no child management).

Example:

pty = await open_pty(Winsize(24, 80, 0, 0))
data = await pty.read(4096)
await pty.write(b"hello\n")

ExitStatus

Frozen dataclass returned by await wait() (or None if the child was already reaped).

from stitch_pty import ExitStatus

status = await session.wait()
if status:
    print(f"PID {status.pid} exited with code {status.exit_code}")
Field Type Description
pid int PID of the process that exited
exit_code int | None Exit code, or None if killed by a signal
signal int | None Signal number, or None if exited normally
core_dumped bool Whether a core dump was produced

PtySession

The primary interface for most use cases. Combines PTY I/O, child process management, and terminal emulation.

Method Signature Description
read await read(size=4096) → bytes Read from PTY (auto-feeds terminal)
read_timeout await read_timeout(size, timeout) → bytes Read with timeout (raises IOError on timeout)
write await write(data) → int Write bytes to PTY, returns bytes written
write_all await write_all(data) → None Write all bytes (handles partial writes)
resize resize(rows, cols) → None Resize terminal (forwards to PTY backend)
wait await wait() → ExitStatus | None Wait for child exit; returns ExitStatus or None if already reaped
terminate await terminate(grace_period=5.0) → None SIGTERM → wait → SIGKILL fallback
kill kill() → None Force kill immediately
interrupt interrupt() → None Send Ctrl+C (SIGINT on POSIX, GenerateConsoleCtrlEvent on Windows)
send_signal send_signal(num) → None Send arbitrary signal number
interact await interact(input_data=None, timeout=None) → bytes Write input, read until EOF (high-level)
read_all await read_all(timeout=1.0) → bytes Read all output until timeout
expect await expect(pattern, timeout=30.0) → bytes pexpect-style: read until pattern found

Properties:

Property Type Description
is_alive bool Process still running?
terminal TerminalState Direct access to terminal emulation state
display list[str] Visible screen (one string per row)
scrollback list[str] Scrollback history
full_display list[str] History + visible screen
raw_output bytes All raw bytes read (unparsed)

Context Manager:

async with spawn("bash", ["-i"]) as session:
    await session.write(b"echo hello\n")
    output = await session.interact()
# session.terminate(2.0) called automatically on exit

PtyMaster

Raw PTY I/O without terminal emulation or child management.

Method Signature Description
read await read(size=4096) → bytes Read from PTY master
read_timeout await read_timeout(size, timeout) → bytes Read with timeout
write await write(data) → int Write bytes, returns count
write_all await write_all(data) → None Write all bytes
set_winsize set_winsize(rows, cols, xpixel=0, ypixel=0) → None Set window size
get_winsize get_winsize() → Winsize Get current size
fd property → int Raw file descriptor (Unix) / -1 (Windows)
is_open property → bool PTY still open?

PtyChild

Child process management.

Property/Method Signature Description
pid property → int Child process PID
is_running property → bool Process still running?
wait await wait() → ExitStatus | None Wait for exit; returns ExitStatus or None if already reaped
terminate await terminate(grace_period=5.0) → None SIGTERM → wait → SIGKILL
kill kill() → None Force kill
interrupt interrupt() → None Send Ctrl+C
send_signal send_signal(num) → None Send signal number

TerminalState

VT100/VT220/xterm-compatible terminal emulation with scrollback.

Method Signature Description
feed feed(data: bytes) → None Feed raw bytes (parses ANSI, updates screen)
display display() → list[str] Full display (scrollback + visible)
visible_display visible_display() → list[str] Visible screen only
history_display history_display() → list[str] Scrollback history only
styled_viewport styled_viewport() → list[list[tuple[str, str, str, int]]] Full buffer as styled cells: (text, fg, bg, attrs_bitmask)
total_lines total_lines() → int Total lines = history + visible
absolute_cursor absolute_cursor() → tuple[int, int] (x, history_len + on_screen_y)
dirty dirty() → list[int] Modified row indices
resize resize(lines, cols) → None Resize screen buffer
reset reset() → None Reset terminal + clear history
Property Type Description
cursor_x int Cursor column (0-indexed, visible area)
cursor_y int Cursor row (0-indexed, visible area)
title str Window title (from OSC sequences)
history_size int Current scrollback line count
scrollback_lines int Scrollback capacity
set_scrollback_lines set_scrollback_lines(n) → None Set capacity (trims excess)

Styled Viewport Cell Layout:

# Each cell: (text, fg, bg, attrs_bitmask)
# fg/bg formats: "default", ANSI name ("red", "brightblue"), or 6-hex RGB ("ff0000")
# attrs bitmask: bit 0=bold, 1=dim, 2=italics, 3=underscore,
#                4=blink, 5=reverse, 6=hidden, 7=strikethrough

Winsize

Terminal window dimensions.

Property Type Description
rows u16 Number of rows
cols u16 Number of columns
xpixel u16 Width in pixels
ypixel u16 Height in pixels
ws = Winsize(50, 120, 0, 0)

Error Types

Exception Inherits Raised On
PtyError Exception PTY open/operation failures, platform errors
ProcessError PtyError Spawn/kill failures, process not running
IOError PtyError I/O errors, timeouts, winsize failures

Architecture

High-Level Overview

┌─────────────────────────────────────────────────────────────────┐
│                         Python Layer                            │
│  ┌──────────────┐  ┌────────────────────────────────────────┐   │
│  │ PtySession   │  │ TerminalState (pyte_rs)                │   │
│  │ (Python)     │  │ ├─ Parser (ANSI stream → Screen)       │   │
│  │              │  │ ├─ HistoryScreen (scrollback buffer)   │   │
│  │              │  │ └─ Screen (Char grid, cursor, SGR)     │   │
│  └──────┬───────┘  └────────────────────────────────────────┘   │
│         │                                                       │
│  ┌──────┴──────────────────────────────────────────────────┐    │
│  │         stitch_pty._core (PyO3 / Rust)                  │    │
│  │  ┌──────────────────────────────────────────────────┐   │    │
│  │  │     Platform Abstraction Layer                   │   │    │
│  │  │  ┌──────────────────┐  ┌──────────────────────┐  │   │    │
│  │  │  │  POSIX Backend   │  │  Windows Backend     │  │   │    │
│  │  │  │  ── openpty()    │  │  ── ConPTY (dyn load)│  │   │    │
│  │  │  │  ── fork()       │  │  ── NamedPipe (async)│  │   │    │
│  │  │  │  ── AsyncFd      │  │  ── CreateProcessW   │  │   │    │
│  │  │  │  ── waitpid()    │  │  ── GetExitCodeProc  │  │   │    │
│  │  │  └──────────────────┘  └──────────────────────┘  │   │    │
│  │  └──────────────────────────────────────────────────┘   │    │
│  └─────────────────────────────────────────────────────────┘    │
└─────────────────────────────────────────────────────────────────┘

PTY Backend

POSIX (platform_unix.rs)

Component Detail
PTY creation openpty(3) → master/slave pair, O_NONBLOCK on master
Process spawn fork() → child: setsid() + TIOCSCTTY + dup2()×3 + execvpe()
Async I/O tokio::io::AsyncFd over raw FD with try_io pattern
Reaping Background tokio::spawn polls waitpid(WNOHANG) every 50ms
Signal delivery All signals sent to process group (-pgid) via nix::sys::signal
Resize TIOCSWINSZ ioctl + SIGWINCH to process group via tcgetpgrp
FD leak fix close_random_fds() closes FDs > 2 via /dev/fd (critical for macOS Big Sur)
Signal reset Pre-exec: resets SIGCHLD, SIGHUP, SIGINT, SIGTERM, SIGALRM to SIG_DFL

Async I/O Pattern:

loop {
    let mut guard = self.async_fd.readable().await?;
    match guard.try_io(|inner| {
        libc::read(*inner.get_ref(), buf.as_mut_ptr(), buf.len())
    }) {
        Ok(result) => return result,
        Err(_would_block) => continue,
    }
}

Windows (platform_windows.rs)

Component Detail
ConPTY loading Dynamic GetProcAddress from kernel32.dll (graceful fallback on older Windows)
PTY creation CreatePseudoConsole(size, stdin_handle, stdout_handle)
Pipe plumbing Two tokio::net::NamedPipeServer instances (input + output)
Pipe naming \\.\pipe\stitch-pty-{pid}-{counter} (unique per instance)
Process spawn CreateProcessW with PROC_THREAD_ATTRIBUTE_PSEUDOCONSOLE via SafeAttributeList
Async I/O tokio::net::NamedPipeServer → true async via IOCP (no spawn_blocking)
Reaping Background poll of GetExitCodeProcess every 50ms (no WaitForSingleObject)
Signal delivery Ctrl+C → GenerateConsoleCtrlEvent; SIGTERM/KILL → TerminateProcess
Resize ResizePseudoConsole (no signal forwarded to child)
Startup handshake Sends DSR reply \x1b[1;1R to conhost to begin relaying child output
Command quoting ArgvQuote algorithm: proper escaping of spaces, quotes, trailing backslashes

Send-Safe Windows Types:

SendSyncHandle wraps HANDLE with Send + Sync + Clone, allowing Windows non-Send types to cross .await boundaries. All non-Send locals (STARTUPINFOEXW, PROCESS_INFORMATION, attribute list) are scoped to a block ending before the first .await after CreateProcessW.

Terminal Emulation (terminal/)

Embedded from pyte_rs. Provides VT100/VT220/xterm-compatible rendering.

ANSI Parser (ansi_parser.rs)

ECMA-48 state machine with 10 states:

State Enters On Exits On
Ground Default ESC (\x1b), C0 control
CsiEntry ESC [ Final byte (@~)
CsiParam 09, ;, : Final byte
CsiIntermediate / Final byte
CsiIgnore >? in param Final byte
OscString ESC ] BEL, ST, ESC
DcsEntry ESC P Hook byte
DcsPassthrough After hook \x9c, ESC, SUB, CAN
Escape ESC Final byte / intermediate
EscapeIntermediate ESC + / Final byte

Parser Limits: Max 32 params (sub-param groups), 2 intermediates, 16 OSC params, 1024 OSC bytes, 4-byte UTF-8 partial buffer.

Screen Buffer (screen.rs)

Feature Detail
Char cell data, fg, bg, bold, dim, italics, underscore, blink, reverse, hidden, strikethrough
SGR colors 8 ANSI, 8 aixterm bright, 256-color, 24-bit RGB (with colon subparams)
Modes Public (IRM, LNM) + Private (DECOM, DECAWM, DECCOLM, DECTCEM, DECSCNM) + Extended (mouse, bracketed paste)
Character sets G0/G1 with DEC Special line drawing
Unicode Width-1/2 chars, combining marks, CJK, emoji
Kitty Keyboard Protocol Mode push/pop/replace
Dirty tracking BTreeSet<usize> of modified row indices

Scrollback (history.rs)

Method Description
scroll_up_with_history(rows) Push scrolled lines to history
scroll_down_with_history(rows) Pop lines from history
total_lines() history_len + visible_lines
absolute_cursor() (x, history_len + on_screen_y)
styled_viewport() Full buffer as (text, fg, bg, attrs_bitmask) cells

GIL Management Strategy

PyO3 native async automatically releases the GIL at .await:

Python call (GIL held)
    → future_into_py (GIL released)
    → tokio I/O await (GIL released)
    → completion: GIL reacquired
    → Rust value → Python object conversion

GIL is acquired only for:

  1. Converting Vec<u8>PyBytes
  2. Raising PyErr exceptions

Memory Safety

POSIX ownership:

PtyPair (owns master_fd + slave_fd)
    ├── master_fd → UnixPtyMaster (via mem::forget)
    │   └── Drop: close(fd)
    └── slave_fd → child process (via fork)
        └── Child closes on exec, parent closes after fork

Windows ownership:

WinPtyBackend (owns HPCON + NamedPipeServer handles)
    ├── input_pipe → NamedPipeServer (Drop: drop)
    ├── output_pipe → NamedPipeServer (Drop: drop)
    └── conpty → ConPTY (Drop: ClosePseudoConsole)

RAII guarantees:

Type Drop Behavior
UnixPtyMaster close(raw_fd)
WinPtyBackend ClosePseudoConsole + drop named pipes
UnixChildProcess kill(SIGKILL) if running
WinChildProcess TerminateProcess if running; CloseHandle

Examples

Simple Command Execution

import asyncio
from stitch_pty import spawn

async def main():
    session = await spawn("echo", ["hello", "world"])
    output = await session.interact()
    print(output.decode())  # b"hello world\n"

asyncio.run(main())

Interactive Shell

import asyncio
from stitch_pty import spawn

async def main():
    session = await spawn("bash", ["-i"])

    # Send a command
    await session.write(b"ls -la\n")

    # Wait for output
    output = await session.interact()
    print(output.decode())

    # Cleanup
    await session.terminate()

asyncio.run(main())

pexpect-Style Expect

import asyncio
from stitch_pty import spawn

async def main():
    session = await spawn("bash", ["-i"])

    # Wait for a prompt
    prompt = await session.expect(b"$ ", timeout=10.0)
    print(f"Got: {prompt.decode()}")

    # Send command
    await session.write(b"uname -a\n")

    # Wait for output
    output = await session.expect(b"\n", timeout=5.0)
    print(f"Output: {output.decode()}")

    await session.terminate()

asyncio.run(main())

Raw PTY (No Child)

import asyncio
from stitch_pty import open_pty, Winsize

async def main():
    pty = await open_pty(Winsize(24, 80, 0, 0))

    # Write and read raw bytes
    await pty.write(b"hello from raw PTY\n")
    data = await pty.read(4096)
    print(data.decode())

asyncio.run(main())

PySide6 Terminal Emulator (GUI)

A full terminal emulator with real-time rendering, keyboard input, resize handling, and styled viewport:

pip install PySide6 stitch-pty
python examples/terminal_emulator.py
python examples/terminal_emulator.py --cmd "whoami"
python examples/terminal_emulator.py --rows 30 --cols 100

Key features demonstrated:

  • Async PTY + Qt event loop integration (background thread)
  • Real-time styled rendering via styled_viewport() with HTML
  • Cursor position tracking via absolute_cursor()
  • Keyboard input forwarding with Ctrl+key → ANSI sequences
  • Window resize forwarding (rate-limited during drag)
  • Graceful shutdown on window close

Building from Source

stitch-pty is designed to be used both as a standalone Rust crate and as a Python extension. The Python bindings are decoupled and gated behind the python feature flag.

Prerequisites

Requirement Version
Rust ≥ 1.85
Python ≥ 3.12
maturin ≥ 1.8
# Install Rust
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh

# Install maturin
pip install maturin

Building as a Rust Crate

To use stitch-pty in a Rust project, add it to your Cargo.toml. The Python bindings are disabled by default, allowing for a pure Rust build without PyO3 overhead.

[dependencies]
stitch-pty = "0.5.5"

To build and test the pure Rust code locally:

cargo build
cargo test

Building as a Python Extension

The Python extension is built using maturin. The pyproject.toml is configured to automatically enable the python feature when building wheels.

# Clone
git clone https://github.com/stitch-pty/stitch-pty.git
cd stitch-pty

# Development build (fast, unoptimized)
maturin develop

# Alternatively, using uv to test:
uv run --extra dev pytest

# Run Python tests (platform-specific tests auto-skip)
pytest tests/ -v

# Type check
mypy python/stitch_pty/

# Lint
ruff check .

# Production wheel
maturin build --release

Cross-Compilation

# Linux ARM64 from x86_64 host
maturin build --release --target aarch64-unknown-linux-gnu

# macOS universal2
maturin build --release --target universal2-apple-darwin

# Windows from Linux (requires cross toolchain)
maturin build --release --target x86_64-pc-windows-gnu

Source Projects & Dependencies

stitch-pty is built on three foundational open-source projects. Each contributed significant portions of code, architecture patterns, and design decisions that were adapted, extended, or embedded into this project.

1. portable-pty — PTY Abstraction Layer

Property Detail
Source ../other packages/portable-pty-main
Repository github.com/wezterm/portable-pty
Version 0.9.0
Author Wez Furlong
License MIT
Role Cross-platform PTY backend patterns (traits, ChildKiller, ExitStatus, PtySize)

What was taken:

  • ChildKiller trait — deadlock-free kill/wait separation pattern (cloneable killer split from ChildBackend to avoid blocking .wait threads)
  • ExitStatus / ProcessExit structs — unified exit code + signal representation
  • PtySizeWinsize — window size struct with rows/cols/pixels
  • close_random_fds() — macOS Big Sur / Linux FD leak prevention (closes all FDs > 2 via /dev/fd listing)
  • ArgvQuote algorithm — proper Windows command-line quoting (backslash/quote escaping)
  • SafeAttributeList pattern — Win32 PROC_THREAD_ATTRIBUTE_LIST lifecycle management (Initialize → Update → Delete) for ConPTY attachment
  • ProcessSignaller — cross-platform signal delivery abstraction

What changed:

  • Rewritten for tokio async (portable-pty uses blocking I/O)
  • Replaced nix 0.28nix 0.31 with additional features (signal, poll, ioctl)
  • Replaced winapiwindows crate (0.62, modern MSFT bindings)
  • Replaced anyhowthiserror for zero-cost error propagation
  • Added Tokio NamedPipes for Windows async I/O (portable-pty uses spawn_blocking)
  • Added dynamic ConPTY loading via GetProcAddress for graceful fallback
  • GIL management for Python integration

2. pyte — Terminal Emulation

Property Detail
Source ../other packages/pyte-master
Repository github.com/selectel/pyte
Version 0.8.3 (dev)
License LGPL-3.0
Role VT100/VT220/xterm-compatible terminal screen emulation (embedded as terminal/)

What was taken:

  • Screen — 2D Char grid, cursor management, tab stops, dirty tracking
  • Char cell — data, fg/bg colors, bold/dim/italics/underscore/blink/reverse/hidden/strikethrough
  • Cursor — position, attributes, save/restore stack
  • Margins — scroll region top/bottom
  • CursorStyle — block/underline/beam variants
  • SGR color handling — 8 ANSI, 8 aixterm bright, 256-color palette, 24-bit RGB
  • Mode management — public ANSI (IRM, LNM) + private DEC (DECOM, DECAWM, DECCOLM, etc.)
  • Character set designation — G0/G1 with DEC Special line drawing map
  • OSC title/icon dispatch — OSC 0/1/2; icon name and window title
  • CSI cursor movement — CUU/CUD/CUF/CUB/CUP/CNL/CPL/CHA
  • CSI erase — ED (display), EL (line), DC (characters), DL/IL (lines)
  • Unicode handlingunicode-width for width-1/width-2 chars, combining marks
  • Kitty Keyboard Protocol — mode push/pop/replace
  • Device status — DA0/DA1 identification, cursor position report

What changed:

  • Ported from Python to Rust with PyO3 bindings
  • Added HistoryScreen — scrollback buffer (not in upstream pyte)
  • Added styled_viewport() — full buffer as (text, fg, bg, attrs_bitmask) cells
  • Added total_lines() and absolute_cursor() for scroll-aware positioning
  • Added unicode-segmentation for proper grapheme boundary handling
  • SGR subparameter parsing (: as param separator) — differs from vte crate
  • Color stored as hex strings ("ff0000") instead of RGB tuples for Python serialization

3. vte — ANSI Escape Sequence Parser

Property Detail
Source ../other packages/vte-master
Repository github.com/alacritty/vte
Version 0.15.0
Authors Joe Wilm, Christian Duerr
License Apache-2.0 OR MIT
Role ECMA-48 ANSI escape sequence state machine (embedded as terminal/ansi_parser.rs)

What was taken:

  • ECMA-48 state machine — 10-state ANSI parser (Ground, CsiEntry, CsiParam, CsiIntermediate, CsiIgnore, OscString, DcsEntry, DcsPassthrough, Escape, EscapeIntermediate)
  • Parser struct — state, intermediates, params, UTF-8 partial buffer, OSC raw buffer
  • Params struct — sub-parameter groups with MAX_PARAMS = 32 limit
  • Perform traitprint, execute, hook, put, unhook, osc_dispatch, csi_dispatch, esc_dispatch, terminated
  • UTF-8 handling — partial byte buffer (4 bytes), invalid byte replacement with \u{FFFD}
  • OSC handlingMAX_OSC_PARAMS = 16, MAX_OSC_RAW = 1024, BEL/ST termination
  • DCS passthrough — hook/passthrough/unhook state transitions
  • C0/C1 control handling — C0 (\x00\x1f), C1 (\x80\x9f)
  • Parameter parsing: subparameter separator, ; param separator, overflow saturation

What changed:

  • Embedded directly as source (not a crate dependency) — allows custom Perform impl
  • Perform trait extended with esc_dispatch for legacy ESC sequences
  • CSI parameter parsing: : treated as param separator (not subparam like upstream vte)
  • Added escape.rs designator constants (RIS, IND, NEL, HTS, etc.)
  • Added charsets.rs DEC Special line drawing map
  • Added control.rs C0/C1 constants
  • Added extensive unit tests for parser edge cases (overflow, reset, partial UTF-8)

Dependency Summary

Source Project License How Used Lines Contributed
portable-pty MIT PTY backend patterns, ChildKiller, ExitStatus, ArgvQuote, SafeAttributeList ~200 lines (patterns)
pyte LGPL-3.0 Terminal emulation (Screen, Char, Cursor, SGR, modes, character sets) ~1,200 lines (embedded)
vte Apache-2.0 OR MIT ANSI parser state machine (Parser, Params, Perform) ~600 lines (embedded)

Note: stitch-pty is licensed MIT OR Apache-2.0. The LGPL-3.0 dependency (pyte) is satisfied by the "exception to section 3" clause: the terminal emulation is embedded as a module, not linked as a library. The MIT and Apache-2.0 licenses are compatible with stitch-pty's dual licensing.


Platform Support

Platform Backend Signal Support Resize Signal Exit Info Status
Linux POSIX openpty() + fork() Full SIGWINCH code + signal + core_dumped ✅ Complete
macOS POSIX openpty() + fork() Full SIGWINCH code + signal + core_dumped ✅ Complete
Windows 10 1809+ ConPTY + NamedPipes Ctrl+C only ❌ No signal code only ✅ Complete
Windows <10 CreateProcess + pipes ❌ Limited code only ⚠️ Fallback

Platform Differences

Feature POSIX Windows
PTY backend openpty(3) + fork() + execvpe() ConPTY (CreatePseudoConsole) + CreateProcessW
I/O model tokio::AsyncFd over raw FDs tokio::NamedPipeServer (IOCP)
Signal delivery Full via nix::sys::signal (SIGINT, SIGTERM, SIGKILL, SIGWINCH) Ctrl+C (GenerateConsoleCtrlEvent), SIGTERM/KILL → TerminateProcess
Resize signal SIGWINCH forwarded to process group via tcgetpgrp No signal; ResizePseudoConsole only
Exit info exit_code + signal + core_dumped exit_code only
Pipe plumbing Single FD pair (master/slave) Two named pipes (input/output) + connect() to arm IOCP
Startup handshake N/A DSR reply (\x1b[1;1R) to conhost before child output flows
FD leak fix close_random_fds() (macOS/Linux) N/A

License

MIT OR Apache-2.0

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distributions

No source distribution files available for this release.See tutorial on generating distribution archives.

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

stitch_pty-0.5.6-cp312-abi3-win_amd64.whl (511.9 kB view details)

Uploaded CPython 3.12+Windows x86-64

stitch_pty-0.5.6-cp312-abi3-manylinux_2_28_x86_64.whl (536.5 kB view details)

Uploaded CPython 3.12+manylinux: glibc 2.28+ x86-64

stitch_pty-0.5.6-cp312-abi3-manylinux_2_28_aarch64.whl (526.5 kB view details)

Uploaded CPython 3.12+manylinux: glibc 2.28+ ARM64

stitch_pty-0.5.6-cp312-abi3-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl (976.7 kB view details)

Uploaded CPython 3.12+macOS 10.12+ universal2 (ARM64, x86-64)macOS 10.12+ x86-64macOS 11.0+ ARM64

File details

Details for the file stitch_pty-0.5.6-cp312-abi3-win_amd64.whl.

File metadata

  • Download URL: stitch_pty-0.5.6-cp312-abi3-win_amd64.whl
  • Upload date:
  • Size: 511.9 kB
  • Tags: CPython 3.12+, Windows x86-64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for stitch_pty-0.5.6-cp312-abi3-win_amd64.whl
Algorithm Hash digest
SHA256 73f8d9a6de46a2eb48edbb503ff89f175798afef78900f7f8ddd5a537e033648
MD5 a5905be2b9bc82ee5c2dbee7df539a14
BLAKE2b-256 09103d5ef759742dfe4b965120f27e83a7b57a94e6a959c1f8da9c362737d1c9

See more details on using hashes here.

Provenance

The following attestation bundles were made for stitch_pty-0.5.6-cp312-abi3-win_amd64.whl:

Publisher: CI.yml on opticsWolf/stitch-pty

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file stitch_pty-0.5.6-cp312-abi3-manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for stitch_pty-0.5.6-cp312-abi3-manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 38b143d1a2f60b8e29cc8a16c9261658bcf594181de72df2fb7e21b4fd2df403
MD5 90555d70c38ef25bd6425366e490a968
BLAKE2b-256 c7908de40363d2c7908f639ffd18a0a9e2eba8274e708eb4983c81d5feb71b41

See more details on using hashes here.

Provenance

The following attestation bundles were made for stitch_pty-0.5.6-cp312-abi3-manylinux_2_28_x86_64.whl:

Publisher: CI.yml on opticsWolf/stitch-pty

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file stitch_pty-0.5.6-cp312-abi3-manylinux_2_28_aarch64.whl.

File metadata

File hashes

Hashes for stitch_pty-0.5.6-cp312-abi3-manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 f7da002e1cd8586a2c8b17cabb1a7a0d7cd426a6716f6ab2aa123f17f75b01fa
MD5 78c2946b6642a5df97b7a7a3baf9bf4e
BLAKE2b-256 0888f8fdc4c41e330a6a29b8def88c00a2d1d0563cf63068fe157d5d32a43a80

See more details on using hashes here.

Provenance

The following attestation bundles were made for stitch_pty-0.5.6-cp312-abi3-manylinux_2_28_aarch64.whl:

Publisher: CI.yml on opticsWolf/stitch-pty

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file stitch_pty-0.5.6-cp312-abi3-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl.

File metadata

File hashes

Hashes for stitch_pty-0.5.6-cp312-abi3-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl
Algorithm Hash digest
SHA256 25dd9b95e853d0aa40cde00688d60fd96de59205e76a2e1bd259467cba86df24
MD5 07e742af87eec565bf84ab0c07557638
BLAKE2b-256 ae6bef35e30996d5381b1cae9fcc6a900564f872cfdd1fa4e6557a48014699e9

See more details on using hashes here.

Provenance

The following attestation bundles were made for stitch_pty-0.5.6-cp312-abi3-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl:

Publisher: CI.yml on opticsWolf/stitch-pty

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page