clue/term-react
Streaming terminal emulator for ReactPHP. Includes ControlCodeParser stream wrapper to strip ANSI/VT100 control sequences from input, buffering incomplete sequences so emitted data is always plain text for reliable processing.
Start by installing via Composer: composer require clue/term-react. This package provides a streaming ANSI terminal emulator for ReactPHP, ideal for building interactive CLI tools, remote shell proxies, or TTY-aware WebSocket servers. Your first use case is likely capturing and processing terminal input/output in async PHP — for example, acting as a middleware layer between a WebSocket client and an underlying process. Initialize the emulator with a sink (e.g., a WriteStream) to receive emitted ANSI sequences:
use Clue\React\Term\Term;
use React\Stream\ThroughStream;
$sink = new ThroughStream();
$term = new Term($sink);
// Hook up input stream (e.g., stdin or socket)
$stdin->on('data', [$term, 'input']);
// Pipe output back
$sink->pipe($stdoutOrSocket);
Check the examples/ folder in the repo for minimal working demos like echo-server.php or websocket-term.php.
Common patterns involve embedding Term in event-driven CLI or server apps:
Term to forward interactive shells to subprocesses (React\ChildProcess\Process) and handle PTY-like interactions.Ratchet\WebSocket\WsServer), converting WS messages ↔ terminal escape sequences.$sink stream to sanitize or augment output (e.g., log terminal sessions, convert colors).Term::input() via extension or composition to inject hotkeys or command shortcuts before forwarding to the sink.For scalable use, couple with React\EventLoop\Loop and a PSR-7/PSR-15-compatible HTTP/WebSocket stack (e.g., React\Http + React\Socket). Always ensure you handle backpressure by enabling流控 (setEncoding('binary'), respecting isWritable()).
$sink must be able to consume data quickly. If downstream (e.g., WebSocket) is slow, pipe via ThroughStream + Buffer to avoid memory bloat.Term is stateless-by-default. If reconnecting clients (e.g., SSH over WS), you must implement your own state snapshot (e.g., save buffer + cursor state via $term->exportState() — note: this method doesn’t exist in current v1; you must subclass and track manually).script or asciinema to verify behavior.final and non-extendable — override behavior by composition: wrap Term and delegate calls, intercepting input() and sink events.exit event handlers to avoid zombie processes — Term doesn’t manage child lifecycle.ResourceStream writing to php://stderr, or use a custom sink that logs data events with timestamps.How can I help you explore Laravel packages today?