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 (
claude CLI) - 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.
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
ChildProcessimplementation uses Electron'sutilityProcess.fork()which spawns processes withstdio: '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:
Use Case
We are building a NativePHP desktop app that needs to embed interactive CLI tools like:
claudeCLI) - an AI coding assistant with a full TUI interfacehtop,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: trueoption 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.jsExample API
Events
The existing event system (
MessageReceived,ErrorReceived,ProcessExited) would continue to work. An additional event could be added for resize handling:Technical Details
The key change would be in the Electron-side
childProcess.jshelper:The rest of the event chain (stdout →
notifyLaravel→broadcastToWindows→ Livewire dispatch) would remain unchanged.Environment
Workaround
Currently there is no viable workaround for running interactive TUI applications through the ChildProcess API.