Skip to main content

PtyShell

Struct PtyShell 

Source
pub struct PtyShell {
    pub last_command: String,
    pub output_buffer: String,
    pub command_running: bool,
    pub last_exit_code: Option<i32>,
    pub output_truncated: bool,
    pub last_returned_hash: Option<u64>,
    pub attach_hint: Option<String>,
    /* private fields */
}
Expand description

Real PTY-based interactive shell

Uses portable-pty for true pseudo-terminal functionality, enabling proper handling of interactive programs like sudo, vim, etc.

Fields§

§last_command: String

Last command executed

§output_buffer: String

Accumulated output buffer

§command_running: bool

Whether a command is currently running

§last_exit_code: Option<i32>

Exit code of the last completed foreground command, parsed from the prompt marker (──➤<nonce>:<code>). None until a command finishes, and reset to None while one is running.

§output_truncated: bool

Flag for output truncation

§last_returned_hash: Option<u64>

Hash of the last rendered output we shipped to the caller. Used by the delta path in status_check to elide repeats when the screen is idle.

§attach_hint: Option<String>

Optional command a human can run to attach to the same terminal session.

Implementations§

Source§

impl PtyShell

Source

pub fn new(initial_dir: &Path, restricted_mode: bool) -> Result<Self>

Create a new PTY shell session

§Arguments
  • initial_dir - Starting directory for the shell
  • restricted_mode - Whether to use bash restricted mode (-r)
§Returns

A new PtyShell instance with an active bash session

Source

pub fn send_command(&mut self, command: &str) -> Result<()>

Send a command to the shell and start reading output

Source

pub fn mark_command_started(&mut self)

Start the monotonic runtime clock for a newly submitted command.

Source

pub fn completion_report_pending(&self) -> bool

Whether the most recent foreground command has finished without any response having reported its exit yet.

Source

pub fn mark_completion_reported(&mut self)

Record that a response reported the current command as finished.

Source

pub fn command_generation(&self) -> u64

Source

pub fn incarnation(&self) -> u64

Source

pub fn command_elapsed(&self) -> Option<Duration>

Elapsed runtime since the current command was submitted.

Source

pub fn current_cwd(&self) -> &Path

Current working directory last reported by this shell’s prompt.

Source

pub fn delivered_output(&self) -> String

Snapshot used as the left-hand side of incremental output rendering.

Source

pub fn mark_output_delivered(&mut self, output: &str)

Mark the cumulative output snapshot as delivered after rendering it.

Source

pub fn collect_scrollback(&self, lines: usize) -> String

Return up to lines recent lines from the scrollback ring, oldest first. When older lines were evicted or a long unterminated line was clipped, a [winx: …] notice is prepended so the caller knows the scrollback is incomplete rather than silently receiving less than asked.

Source

pub fn fingerprint(text: &str) -> u64

Hash arbitrary rendered output into a u64 dedup key.

Source

pub fn read_output(&mut self, timeout_secs: f32) -> Result<(String, bool)>

Read output from the PTY with timeout

Returns (output, is_complete) tuple where is_complete indicates whether the command has finished (prompt detected)

Source

pub fn poll_output_nonblocking(&mut self) -> bool

Non-blocking drain of whatever the reader thread has already queued.

Unlike read_output, this never sleeps: it consumes every chunk currently available, updates prompt/completion state, and returns immediately. prune_finished_shells uses it so the global background-shell lock is never held across a blocking 100ms read_output. Returns true if the command has completed (prompt seen or PTY closed).

Source

pub fn output_snapshot(&self) -> String

Snapshot of the accumulated output buffer — the same text read_output returns. Lets callers poll non-blocking (poll_output_nonblocking) and grab the buffer once at the end instead of cloning it on every slice.

Source

pub fn set_scratch_root(&mut self, root: &Path)

Point output-offload scratch files at root (the workspace). Idempotent; callers set it per command so it always tracks the current workspace.

Source

pub fn scratch_path(&self) -> Option<&Path>

The scratch file holding the current command’s dropped output head, if any was offloaded this command.

Source

pub fn reset_scratch(&mut self)

Forget the current command’s scratch file so the next command starts a fresh one. Does not delete the file (pruned later by age).

Source

pub fn send_interrupt(&mut self) -> Result<()>

Send Ctrl+C (interrupt) to the PTY

Source

pub fn send_eof(&mut self) -> Result<()>

Send Ctrl+D (EOF) to the PTY

Source

pub fn send_suspend(&mut self) -> Result<()>

Send Ctrl+Z (suspend) to the PTY

Source

pub fn send_text(&mut self, text: &str) -> Result<()>

Send text directly to the PTY (for interactive input)

Source

pub fn send_bytes(&mut self, bytes: &[u8]) -> Result<()>

Send raw bytes directly to the PTY.

Source

pub fn send_special_key(&mut self, key: &str) -> Result<()>

Send a special key sequence

Source

pub fn live_snapshot(&self, max_lines: usize) -> Vec<String>

Snapshot the live terminal screen — a stable, consolidated view of what a human would currently see, with cursor moves/redraws applied and ANSI stripped. max_lines of 0 returns the full screen buffer. This is the foundation for piloting interactive TUIs (the claude CLI, vim, …).

Source

pub fn live_in_alt_screen(&self) -> bool

Whether the live terminal is currently on the alternate screen buffer (a full-screen app like vim/htop/less is running).

Source

pub fn live_osc_title(&self) -> String

The latest OSC 0/2 window title emitted by the foreground program ("" when none) — an out-of-band turn signal for the manifest recognizers (claude/codex render a spinner glyph in the title while generating).

Source

pub fn live_osc_progress(&self) -> String

The latest OSC 9 payload after 9; ("" when none) — ConEmu-style progress reads 4;<state>;<percent>.

Source

pub fn live_cursor_position(&self) -> (u16, u16)

Cursor position (row, col) on the live screen (0-based), so a piloting agent knows where focus is in a menu/form. (0, 0) if the lock is poisoned.

Source

pub fn live_snapshot_diff( &self, max_lines: usize, threshold: usize, ) -> ScreenUpdate

Diff the live screen against what the client last saw, returning only the changed lines when the change is small (huge token savings over many polls). Updates the baseline as a side effect. See ScreenUpdate.

Source

pub fn resize(&mut self, cols: u16, rows: u16) -> Result<()>

Resize the terminal

Source

pub fn get_size(&self) -> (u16, u16)

Get current terminal size

Source

pub fn process_id(&self) -> Option<u32>

OS process id of the shell that owns this PTY.

Source

pub fn is_alive(&mut self) -> bool

Check if the shell is still alive

Trait Implementations§

Source§

impl Debug for PtyShell

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Drop for PtyShell

Source§

fn drop(&mut self)

Kill and reap the shell child and its whole process group so neither the shell nor anything it spawned leaks.

std::process::Child::drop neither kills nor waits, and even Child::kill signals only the shell itself: a background job it started (npm run dev &, a nohup’d server) would be reparented to init and live on. Because portable-pty runs the shell as a session/group leader, we can signal the whole group with a negative pid - SIGTERM first so well-behaved children can clean up, then Child::kill (SIGKILL on the leader, which closes the PTY slave so the reader thread’s read() returns EOF and the thread exits), then SIGKILL the group to sweep anything still alive, then reap. The pgid is captured while the leader is alive and reused: it stays valid until we wait(), even after the leader dies. All best-effort.

Source§

fn pin_drop(self: Pin<&mut Self>)

🔬This is a nightly-only experimental API. (pin_ergonomics)
Execute the destructor for this type, but different to Drop::drop, it requires self to be pinned. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> Downcast for T
where T: Any,

Source§

fn into_any(self: Box<T>) -> Box<dyn Any>

Convert Box<dyn Trait> (where Trait: Downcast) to Box<dyn Any>. Box<dyn Any> can then be further downcast into Box<ConcreteType> where ConcreteType implements Trait.
Source§

fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>

Convert Rc<Trait> (where Trait: Downcast) to Rc<Any>. Rc<Any> can then be further downcast into Rc<ConcreteType> where ConcreteType implements Trait.
Source§

fn as_any(&self) -> &(dyn Any + 'static)

Convert &Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot generate &Any’s vtable from &Trait’s.
Source§

fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)

Convert &mut Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot generate &mut Any’s vtable from &mut Trait’s.
Source§

impl<T> ErasedDestructor for T
where T: 'static,

Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<A, B, T> HttpServerConnExec<A, B> for T
where B: Body,

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self> ⓘ

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self> ⓘ

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ

Converts self into a Left variant of Either<Self, Self> if into_left is true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
where F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> if into_left(&self) returns true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

impl<T> MaybeSendSync for T

Source§

impl<T> Pointable for T

Source§

const ALIGN: usize

The alignment of pointer.
Source§

type Init = T

The type for initializers.
Source§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
Source§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
Source§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
Source§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, !>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self> ⓘ
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self> ⓘ

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more