# `2.5.0` PTY Shell Sessions

Status: Done

## Goal

Add persistent interactive shells so an agent can inhabit a workspace instead
of only submitting one-shot `workspace exec` calls.

## Public API Changes

- CLI:
  - `pyro workspace shell open`
  - `pyro workspace shell read`
  - `pyro workspace shell write`
  - `pyro workspace shell signal`
  - `pyro workspace shell close`
- SDK:
  - `open_shell`
  - `read_shell`
  - `write_shell`
  - `signal_shell`
  - `close_shell`
- MCP:
  - `shell_open`
  - `shell_read`
  - `shell_write`
  - `shell_signal`
  - `shell_close`

Core shell identity:

- `workspace_id`
- `shell_id`
- PTY size
- working directory
- running/stopped state

## Implementation Boundaries

- Shells are persistent PTY sessions attached to one workspace.
- Output buffering is append-only with cursor-based reads so callers can poll
  incrementally.
- Shell sessions survive separate CLI/SDK/MCP calls and are cleaned up by
  `workspace delete`.
- Keep `workspace exec` as the non-interactive path; do not merge the two
  models.

## Non-Goals

- no terminal UI beyond structured shell I/O
- no service lifecycle changes in this milestone
- no export/diff/snapshot/reset changes yet

## Acceptance Scenarios

- open a shell, write commands, read output in chunks, send SIGINT, then close
- reopen a new shell in the same workspace after closing the first one
- delete a workspace with an open shell and confirm the shell is cleaned up

## Required Repo Updates

- shell-focused example in CLI, SDK, and MCP docs
- help text that explains shell vs exec clearly
- real Firecracker smoke for open -> write -> read -> signal -> close
