Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Exec

Accessor: client.Exec()

Execute commands in a sandbox with three modes: one-shot (Run), streaming (Stream), or interactive terminal (Interactive).

Run

Execute a command and collect all output into a single result.

result, err := client.Exec().Run(ctx, "default", "sbx-123", []string{"ls", "-la"})
if err != nil {
    log.Fatal(err)
}

fmt.Println("Exit code:", result.ExitCode)
fmt.Println("Stdout:", result.Stdout)
fmt.Println("Stderr:", result.Stderr)

The SDK collects all streamed events, assembles stdout/stderr, and returns a single ExecResult.

ExecResult contains the complete output after the command finishes:

FieldTypeDescription
StdoutstringCaptured standard output
StderrstringCaptured standard error
ExitCodeintProcess exit code

Stream

Execute a command and process output chunks as they arrive.

stream, err := client.Exec().Stream(ctx, "default", "sbx-123", []string{"tail", "-f", "/var/log/app.log"})
if err != nil {
    log.Fatal(err)
}
defer stream.Close()

for {
    chunk, err := stream.Next()
    if err == io.EOF {
        break
    }
    if err != nil {
        log.Fatal(err)
    }

    if chunk.Stream == v1.StreamStdout {
        fmt.Print(string(chunk.Data))
    }
}

exitCode, err := stream.ExitCode()
if err != nil {
    log.Fatal(err)
}
fmt.Println("Exited with:", exitCode)

Interactive

Open a bidirectional terminal session with a command.

session, err := client.Exec().Interactive(ctx, "default", "sbx-123", []string{"/bin/bash"}, 80, 24)
if err != nil {
    log.Fatal(err)
}
defer session.Close()

// Send input
_, err = session.Write([]byte("echo hello\n"))
if err != nil {
    log.Fatal(err)
}

// Read output
buf := make([]byte, 4096)
n, err := session.Read(buf)
if err != nil {
    log.Fatal(err)
}
fmt.Print(string(buf[:n]))

// Handle terminal resize
if err := session.Resize(120, 40); err != nil {
    log.Fatal(err)
}

// Get exit code after session ends
exitCode, err := session.ExitCode()
if err != nil {
    log.Fatal(err)
}
fmt.Println("Exited with:", exitCode)

The SDK wraps the bidirectional stream as an InteractiveSession with Read/Write/Resize methods.

ExecStream

ExecStream provides an iterator interface over command output chunks. Call Next() repeatedly to receive output as it is produced. When the command finishes, Next() returns io.EOF.

type ExecStream interface {
    Next() (*ExecChunk, error)
    ExitCode() (int, error)
    Close() error
}
MethodDescription
NextReturns the next output chunk. Returns io.EOF when done.
ExitCodeReturns the process exit code. Call after Next returns io.EOF.
CloseReleases the underlying stream resources.

InteractiveSession

InteractiveSession implements io.Reader and io.Writer for bidirectional communication with a running process. Use it for terminal emulation, REPL interaction, or any command that requires ongoing input.

type InteractiveSession interface {
    Read(p []byte) (int, error)
    Write(p []byte) (int, error)
    Resize(cols, rows uint32) error
    ExitCode() (int, error)
    Close() error
}
MethodDescription
ReadReads output from the process into the provided buffer.
WriteSends input to the process.
ResizeUpdates the terminal dimensions (columns and rows).
ExitCodeWaits for final gRPC status; returns any observed exit code alongside a later stream error.
CloseAborts the RPC and releases resources.

SDK sessions also implement the optional InteractiveSessionControl interface, which embeds InteractiveSession and adds CloseWrite() error and Cancel() error. Existing custom implementations only need the original methods above.

Call CloseInteractiveInput(session) to end stdin and resize input without cancelling output. It invokes CloseWrite() when supported; otherwise it returns ErrorUnimplemented without closing the session. Call CancelInteractive(session) to invoke Cancel() when supported, falling back to Close() for legacy sessions. The SDK’s close and cancel methods are idempotent.

Drain Read concurrently with waiting for ExitCode; bounded output buffers can otherwise prevent completion. After input closure, writes and resizes return io.ErrClosedPipe. Request EOF is not equivalent to a terminal Ctrl-D keystroke.

ExecChunk

Each chunk from ExecStream.Next() carries a segment of process output along with which stream it came from.

type ExecChunk struct {
    Data   []byte
    Stream StreamType
}
FieldTypeDescription
Data[]byteRaw output bytes from the process.
StreamStreamTypeEither StreamStdout or StreamStderr.

See also: Error Handling, Testing