mirror of
https://github.com/ownpilot/OwnPilot.git
synced 2026-04-25 15:25:52 +03:00
[GH-ISSUE #6] [Feature Request] PTY-based interactive Claude Code CLI control for autonomous multi-agent orchestration #2
Labels
No labels
pull-request
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
starred/OwnPilot#2
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Originally created by @CyPack on GitHub (Feb 25, 2026).
Original GitHub issue: https://github.com/ownpilot/OwnPilot/issues/6
Summary
Currently, when agent frameworks spawn Claude Code as a subprocess (via
exec/spawnwithstdio: pipe), Claude Code detects it is not connected to a real terminal (isatty() == false) and silently switches out of interactive mode. This makes it impossible to:AskUserQuestionwindowThe fix is straightforward: spawn Claude Code via a PTY (Pseudo-Terminal) so it believes it is attached to a real terminal. This is the exact mechanism OpenClaw uses in its
exectool withpty: true.Problem Statement
The
isatty()TrapWhen Claude Code is started via a pipe (
subprocess.Popen(stdin=PIPE, stdout=PIPE)in Python, orBun.spawn/child_process.spawnwithout a PTY in Node), the kernel'sisatty()returnsfalse. Claude Code uses this check to decide its behavior:isatty = true)isatty = false)AskUserQuestion)The most critical consequence:
AskUserQuestionhas a hard 60-second timeout. If the controlling agent cannot detect the question and inject an answer via PTY stdin within that window, the task either aborts or takes a destructive default path.Why This Blocks Multi-Agent Orchestration
The ideal autonomous workflow looks like this:
This pattern is completely impossible with pipe-based subprocess control. The consultation agent in pane 2 never sees the question because pane 1 never emits it.
Requested Feature
Minimum Viable Implementation
Add a
pty: trueflag (or equivalent) to the shell/exec tool so Claude Code is spawned inside a PTY instead of a pipe.Node.js reference implementation using
node-pty:Rust reference (for Moltis — using
portable-ptycrate):Additional Advantages (Beyond Prompt Answering)
Beyond the core interactive-prompt use case, PTY unlocks several production-grade orchestration capabilities:
1. Process Group / Subtree Cleanup
When Claude Code is spawned via PTY with
detached: true, all child processes it creates (subagents, compilers, test runners) belong to the same POSIX process group. A singlekill(-pgid, SIGKILL)destroys the entire tree atomically:This is critical when an agent run goes wrong and must be terminated cleanly.
2. Session Persistence via Terminal Multiplexer
PTY sessions can be managed by
tmuxorscreen, providing true session persistence:A long-running multi-hour agent task survives network interruptions, server restarts, and laptop sleep/wake cycles — none of which are possible with a pipe-backed subprocess.
3. Pause / Resume Capability
PTY enables POSIX job control signals:
With pipe-based processes, "pause" requires killing and restarting (losing all in-progress state).
4. SIGWINCH — Proper Output Formatting
Claude Code and rich CLI tools use
SIGWINCH(window resize signal) to reflow their output. Without it, progress bars and formatted tables overflow or truncate incorrectly. PTY automatically deliversSIGWINCHonpty.resize(cols, rows):5. Real-Time Streaming Without 4 KB Buffer Stall
Standard pipes are block-buffered (typically 4 KB) unless explicitly flushed. This means:
PTY forces line-buffering, so every newline flushes immediately to the master. Orchestrators react in real time.
Security Considerations
PTY-based control is powerful and should be gated appropriately:
allowCommands/denyCommandsPrior Art
exectool,pty: trueflag): The primary reference implementation. PTY spawning with automatic fallback onEBADF(macOS edge case).tmux-based multi-session manager for Claude Code (uses PTY indirectly via tmux).Implementation Checklist
node-pty(Node) orportable-pty(Rust) as dependencypty: booleanoption toexec/shelltoolresize(cols, rows)API so orchestrators can set terminal dimensionsEBADFfallback for macOS compatibilityAskUserQuestiontimeout constraintprocess_group_kill()helper for clean shutdownImpact
Feature request prepared based on analysis of OpenClaw's PTY implementation, node-pty documentation, and production multi-agent orchestration patterns.
@ersinkoc commented on GitHub (Feb 26, 2026):
Thanks for the detailed writeup! PTY-based interactive CLI control is partially implemented in the codebase already via
coding-agent-pty.tsand the Coding Agents feature (auto mode withchild_process.spawn). The key limitation noted here — thatnode-ptyis required for true interactive mode — is documented in our memory notes.For now, the auto mode path (
spawnStreamingProcess) works without native deps and handles most orchestration use cases. Full PTY support (interactive mode withnode-pty) is on the roadmap but not blocking current workflows.Closing as the core functionality exists. We'll reopen or create a follow-up when interactive PTY mode becomes a priority.
@ersinkoc commented on GitHub (Feb 26, 2026):
Closing as the core auto-mode functionality exists. Will revisit when full interactive PTY mode becomes a priority.