-
-
Notifications
You must be signed in to change notification settings - Fork 28
Description
Summary
Add pseudo-terminal (PTY) support to the ChildProcess API to enable running interactive CLI/TUI applications within NativePHP desktop apps.
Current Behavior
The current ChildProcess implementation uses Electron's utilityProcess.fork() which spawns processes with stdio: 'pipe'. This works well for simple command-line tools that read/write plain text via stdin/stdout.
However, interactive TUI (Text User Interface) applications do not work because they require a pseudo-terminal (PTY) to:
- Detect terminal dimensions (rows/columns)
- Handle raw input mode (character-by-character instead of line-buffered)
- Support ANSI escape sequences for cursor movement, colors, and screen manipulation
- Respond to terminal resize events (SIGWINCH)
Use Case
We are building a NativePHP desktop app that needs to embed interactive CLI tools like:
- Claude Code (
claudeCLI) - an AI coding assistant with a full TUI interface - Other TUI apps:
htop,vim,lazygit, terminal-based REPLs, etc.
These tools detect that they are not connected to a TTY and either refuse to start in interactive mode or fall back to a degraded non-interactive mode with no output rendering.
Proposed Solution
Add an optional pty: true option to the ChildProcess API that uses a PTY instead of plain pipes. On the Node.js/Electron side, this could leverage:
node-pty- a mature library for spawning PTY processes in Node.js- Native PTY APIs via N-API addon
Example API
// Current (pipes only)
ChildProcess::start('claude', cwd: '/path/to/project');
// Proposed (with PTY support)
ChildProcess::start('claude', cwd: '/path/to/project', pty: true);
// Optional: resize support
ChildProcess::resize($alias, cols: 120, rows: 40);Events
The existing event system (MessageReceived, ErrorReceived, ProcessExited) would continue to work. An additional event could be added for resize handling:
#[On('native:...\ChildProcess\ProcessResized')]
public function onResize(string $alias, int $cols, int $rows): void { }Technical Details
The key change would be in the Electron-side childProcess.js helper:
// Current: uses stdio pipes
const proc = spawn(command, args, { stdio: 'pipe', cwd });
// With PTY: use node-pty
const pty = require('node-pty');
const proc = pty.spawn(command, args, { cwd, cols: 80, rows: 24 });The rest of the event chain (stdout → notifyLaravel → broadcastToWindows → Livewire dispatch) would remain unchanged.
Environment
- NativePHP Desktop v2
- macOS (primary), but node-pty supports Windows and Linux as well
- Electron (utilityProcess context)
Workaround
Currently there is no viable workaround for running interactive TUI applications through the ChildProcess API.