Agent Diagnostic
- Loaded
openshell-cli skill and inspected crates/openshell-cli/src/run.rs
- Traced the
sandbox_exec_grpc function: the existing unary ExecSandbox RPC sends all stdin upfront in the request body and streams stdout/stderr back. When --tty is used, the terminal is in raw mode but stdin is still buffered into a single blob before the exec call, so interactive programs (bash, top, vim, claude, opencode) never receive live keystrokes.
- Confirmed the proto definition (
proto/openshell.proto) has no bidirectional streaming RPC for exec — only the unary ExecSandbox(ExecSandboxRequest) returns (stream ExecSandboxEvent).
- Checked
crates/openshell-server/src/grpc/sandbox.rs — the server handler reads ExecSandboxRequest.stdin once and pipes it into the SSH channel, then only streams output back. No mechanism exists to forward ongoing client input.
- The non-interactive path (
-- ls, -- cat file) works fine because stdin is consumed before the call. Only interactive TTY sessions are broken.
Description
Running openshell sandbox exec --tty <sandbox> -- <interactive-command> hangs immediately. The command starts on the remote side but the user cannot interact with it — keystrokes are not forwarded, and the session never exits cleanly.
What happens:
openshell sandbox exec --tty my-sandbox -- bash — hangs, no prompt appears (or appears but does not accept input)
openshell sandbox exec --tty my-sandbox -- top — UI renders once but q does not quit
- TUI apps (opencode, claude) render initial UI but freeze
What should happen:
Interactive TTY sessions should behave like ssh — live keystroke forwarding, terminal resize propagation, and clean exit on Ctrl+D or process termination.
Root cause: The ExecSandbox RPC is unary request / server-stream response. There is no client-to-server stream to carry ongoing stdin, resize events, or EOF signals during execution.
Reproduction Steps
- Create a sandbox:
openshell sandbox create --provider docker -- bash
- Run an interactive command:
openshell sandbox exec --tty <sandbox-name> -- bash
- Observe: the session hangs; keystrokes are not forwarded
- Try with
top: openshell sandbox exec --tty <sandbox-name> -- top — q does not quit
Environment
- OS: macOS 26 / Linux
- OpenShell: built from
main branch
- Terminal: iTerm2, Terminal.app, any terminal emulator
Logs
# No error output — the CLI simply hangs after establishing the connection.
# With --tty, stdin bytes are sent in the initial request but no further
# input can reach the remote process.
Agent-First Checklist
Agent Diagnostic
openshell-cliskill and inspectedcrates/openshell-cli/src/run.rssandbox_exec_grpcfunction: the existing unaryExecSandboxRPC sends all stdin upfront in the request body and streams stdout/stderr back. When--ttyis used, the terminal is in raw mode but stdin is still buffered into a single blob before the exec call, so interactive programs (bash, top, vim, claude, opencode) never receive live keystrokes.proto/openshell.proto) has no bidirectional streaming RPC for exec — only the unaryExecSandbox(ExecSandboxRequest) returns (stream ExecSandboxEvent).crates/openshell-server/src/grpc/sandbox.rs— the server handler readsExecSandboxRequest.stdinonce and pipes it into the SSH channel, then only streams output back. No mechanism exists to forward ongoing client input.-- ls,-- cat file) works fine because stdin is consumed before the call. Only interactive TTY sessions are broken.Description
Running
openshell sandbox exec --tty <sandbox> -- <interactive-command>hangs immediately. The command starts on the remote side but the user cannot interact with it — keystrokes are not forwarded, and the session never exits cleanly.What happens:
openshell sandbox exec --tty my-sandbox -- bash— hangs, no prompt appears (or appears but does not accept input)openshell sandbox exec --tty my-sandbox -- top— UI renders once butqdoes not quitWhat should happen:
Interactive TTY sessions should behave like
ssh— live keystroke forwarding, terminal resize propagation, and clean exit on Ctrl+D or process termination.Root cause: The
ExecSandboxRPC is unary request / server-stream response. There is no client-to-server stream to carry ongoing stdin, resize events, or EOF signals during execution.Reproduction Steps
openshell sandbox create --provider docker -- bashopenshell sandbox exec --tty <sandbox-name> -- bashtop:openshell sandbox exec --tty <sandbox-name> -- top—qdoes not quitEnvironment
mainbranchLogs
Agent-First Checklist
debug-openshell-cluster,debug-inference,openshell-cli)