Repository navigation
feat(cli): add openshell sandbox exec subcommand #750
Description
Problem Statement
There is no CLI command to run a one-off command inside an already-running sandbox. Today the workarounds are:
openshell sandbox create -- <cmd>- creates a new sandbox just to run a command.openshell sandbox connect- opens an interactive shell; there's no way to pass a single command and get stdout/stderr/exit-code back non-interactively.
This is the equivalent of docker exec or kubectl exec - a fundamental primitive for scripting, CI pipelines, and agent tool-use against running sandboxes.
Providing such a command will make it easier to create wrapper scripts that do additional configuration of sandboxes.
Proposed Design
Add a new Exec variant to SandboxCommands:
openshell sandbox exec <NAME> -- <COMMAND...>
Flags
| Flag | Description |
|---|---|
--tty / --no-tty |
Force/disable PTY allocation (auto-detect by default) |
--workdir <PATH> |
Set the working directory inside the sandbox |
--env KEY=VALUE |
Set environment variables (repeatable) |
--timeout <SECONDS> |
Kill the command after N seconds (0 = no timeout) |
Behavior
- Resolve sandbox by name (reuse existing
resolve_sandboxlogic). - Call the existing
ExecSandboxgRPC RPC (proto/openshell.proto:37-38) which already acceptssandbox_id,command,workdir,environment,timeout_seconds, andstdin. - Stream
ExecSandboxEventresponses to stdout/stderr. - Exit with the remote command's exit code.
Implementation sketch
The server-side implementation already exists in crates/openshell-server/src/grpc.rs:1011-1069. The client-side SSH plumbing exists in crates/openshell-cli/src/ssh.rs (sandbox_exec, sandbox_exec_without_exec). The new subcommand mainly needs to:
- Add an
Execvariant toSandboxCommandsincrates/openshell-cli/src/main.rs - Add a match arm in
run.rsthat resolves the sandbox and calls either the gRPCExecSandboxRPC or the existing SSH-basedsandbox_exec_without_exec()(the latter avoids replacing the CLI process) - Wire up
--tty,--workdir,--env,--timeoutflags
Example usage
# Run a command and capture output
openshell sandbox exec my-sandbox -- ls -la /workspace
# Pipe data through
echo "hello" | openshell sandbox exec my-sandbox -- cat
# Run with env vars and timeout
openshell sandbox exec my-sandbox --env FOO=bar --timeout 30 -- python train.py
# Non-interactive scripting
EXIT_CODE=$(openshell sandbox exec my-sandbox -- test -f /workspace/model.pt; echo $?)Alternatives Considered
-
Extend
sandbox connectwith-- <cmd>trailing args - Semantically wrong;connectimplies an interactive session. Docker separatesattach(interactive) fromexec(run command) for good reason. -
Expose the gRPC API only and let users call it via
grpcurl- Poor DX. The CLI should wrap this, just as it wraps every other gRPC call. -
Use
sandbox connect+ssh -t <host> <cmd>manually - Requires users to manage SSH config themselves. The point of the CLI is to abstract this away.
Agent Investigation
- The
ExecSandboxgRPC RPC is already defined (proto/openshell.proto:37-38) and implemented server-side (crates/openshell-server/src/grpc.rs:1011-1069). - The SSH execution helpers
sandbox_exec()andsandbox_exec_without_exec()exist incrates/openshell-cli/src/ssh.rs:430. sandbox createusessandbox_exec()after the sandbox reaches Ready phase (run.rs:2405), proving the exec path works end-to-end.- The
SandboxCommandsenum (main.rs:1070) has noExecvariant - this is the only missing piece. openshell doctor execexists but targets the gateway container, not sandboxes.
Activity
drew commentedon Apr 3, 2026
This has been on our radar as well. We've actually got a prototype here, main...feat/sandbox-exec-cli. I'll get this cleaned up and a PR out for it.
steve-todorov commentedon Apr 3, 2026
Wonderful! I was also playing around with it and got it to work, but given you already have implemented it I won't submit a PR. Looking forward to the new release!
fix(cli): add TTY support, phase check, and hardening to sandbox exec
fix(cli): add TTY support, phase check, and hardening to sandbox exec
fix(cli): add TTY support, phase check, and hardening to sandbox exec
fix(cli): add TTY support, phase check, and hardening to sandbox exec