Skip to main content

Go SDK

The official Go SDK for Rexec provides a native, type-safe way to interact with Rexec’s Terminal as a Service.

Installation

Install using go get:
go get github.com/brimblehq/rexec-go

Quick Start

package main

import (
    "context"
    "fmt"
    "log"

    rexec "github.com/brimblehq/rexec-go"
)

func main() {
    // Create client
    client := rexec.NewClient("https://your-rexec-instance.com", "your-api-token")

    ctx := context.Background()

    // Create a container
    container, err := client.Containers.Create(ctx, &rexec.CreateContainerRequest{
        Image: "ubuntu:24.04",
        Name:  "my-sandbox",
    })
    if err != nil {
        log.Fatal(err)
    }
    fmt.Printf("Created container: %s\n", container.ID)

    // Connect to terminal
    term, err := client.Terminal.Connect(ctx, container.ID)
    if err != nil {
        log.Fatal(err)
    }
    defer term.Close()

    // Send a command
    term.Write([]byte("echo 'Hello from Rexec!'\n"))

    // Read output
    output, _ := term.Read()
    fmt.Printf("Output: %s\n", output)

    // Clean up
    client.Containers.Delete(ctx, container.ID)
}

Client Initialization

Basic Client

client := rexec.NewClient(baseURL, apiToken)
The client is defined at /home/daytona/workspace/source/sdk/go/rexec.go:36.

Custom HTTP Client

You can provide a custom HTTP client for advanced configuration:
import (
    "net/http"
    "time"
)

client := rexec.NewClient(baseURL, apiToken)
client.SetHTTPClient(&http.Client{
    Timeout: 60 * time.Second,
})
See the SetHTTPClient method at /home/daytona/workspace/source/sdk/go/rexec.go:67.

Container Operations

The Container service provides methods for managing sandboxed environments.

List Containers

containers, err := client.Containers.List(ctx)
if err != nil {
    log.Fatal(err)
}

for _, c := range containers {
    fmt.Printf("%s: %s\n", c.Name, c.Status)
}
Implementation at /home/daytona/workspace/source/sdk/go/rexec.go:168.

Get Container

container, err := client.Containers.Get(ctx, containerID)
if err != nil {
    log.Fatal(err)
}

fmt.Printf("Container %s is %s\n", container.Name, container.Status)
Implementation at /home/daytona/workspace/source/sdk/go/rexec.go:175.

Create Container

container, err := client.Containers.Create(ctx, &rexec.CreateContainerRequest{
    Image: "ubuntu:24.04",
    Name:  "my-container",
    Environment: map[string]string{
        "MY_VAR": "value",
        "DEBUG":  "true",
    },
    Labels: map[string]string{
        "project": "demo",
    },
})
if err != nil {
    log.Fatal(err)
}

fmt.Printf("Created: %s\n", container.ID)
The CreateContainerRequest type is defined at /home/daytona/workspace/source/sdk/go/rexec.go:154.

Start Container

err := client.Containers.Start(ctx, containerID)
if err != nil {
    log.Fatal(err)
}
Implementation at /home/daytona/workspace/source/sdk/go/rexec.go:194.

Stop Container

err := client.Containers.Stop(ctx, containerID)
if err != nil {
    log.Fatal(err)
}
Implementation at /home/daytona/workspace/source/sdk/go/rexec.go:199.

Delete Container

err := client.Containers.Delete(ctx, containerID)
if err != nil {
    log.Fatal(err)
}
Implementation at /home/daytona/workspace/source/sdk/go/rexec.go:189.

File Operations

Manage files and directories within containers.

List Files

files, err := client.Files.List(ctx, containerID, "/home")
if err != nil {
    log.Fatal(err)
}

for _, f := range files {
    icon := "📄"
    if f.IsDir {
        icon = "📁"
    }
    fmt.Printf("%s %s\n", icon, f.Name)
}
Implementation at /home/daytona/workspace/source/sdk/go/rexec.go:219.

Download File

data, err := client.Files.Download(ctx, containerID, "/home/file.txt")
if err != nil {
    log.Fatal(err)
}

fmt.Printf("File contents: %s\n", string(data))
Implementation at /home/daytona/workspace/source/sdk/go/rexec.go:227.

Create Directory

err := client.Files.Mkdir(ctx, containerID, "/home/newdir")
if err != nil {
    log.Fatal(err)
}
Implementation at /home/daytona/workspace/source/sdk/go/rexec.go:250.

Terminal Operations

Connect to containers via WebSocket for real-time terminal access.

Connect to Terminal

term, err := client.Terminal.Connect(ctx, containerID)
if err != nil {
    log.Fatal(err)
}
defer term.Close()
Implementation at /home/daytona/workspace/source/sdk/go/rexec.go:265.

Write to Terminal

err := term.Write([]byte("ls -la\n"))
if err != nil {
    log.Fatal(err)
}
The Write method is defined at /home/daytona/workspace/source/sdk/go/rexec.go:280.

Read from Terminal

for {
    output, err := term.Read()
    if err != nil {
        break
    }
    fmt.Print(string(output))
}
The Read method is defined at /home/daytona/workspace/source/sdk/go/rexec.go:285.

Resize Terminal

err := term.Resize(120, 40)
if err != nil {
    log.Fatal(err)
}
Implementation at /home/daytona/workspace/source/sdk/go/rexec.go:291.

Advanced Examples

Run a Script

func runScript(client *rexec.Client, containerID, script string) error {
    ctx := context.Background()
    
    term, err := client.Terminal.Connect(ctx, containerID)
    if err != nil {
        return err
    }
    defer term.Close()

    // Write script
    term.Write([]byte(script + "\n"))
    
    // Read output
    for {
        output, err := term.Read()
        if err != nil {
            break
        }
        fmt.Print(string(output))
    }
    
    return nil
}

Interactive Session

func interactiveSession(client *rexec.Client, containerID string) error {
    ctx := context.Background()
    
    term, err := client.Terminal.Connect(ctx, containerID)
    if err != nil {
        return err
    }
    defer term.Close()

    // Handle terminal resize
    term.Resize(80, 24)

    // Read from stdin and write to terminal
    go func() {
        buf := make([]byte, 1024)
        for {
            n, _ := os.Stdin.Read(buf)
            term.Write(buf[:n])
        }
    }()

    // Read from terminal and write to stdout
    for {
        output, err := term.Read()
        if err != nil {
            break
        }
        os.Stdout.Write(output)
    }
    
    return nil
}

Type Definitions

Container

type Container struct {
    ID          string            `json:"id"`
    Name        string            `json:"name"`
    Image       string            `json:"image"`
    Status      string            `json:"status"`
    CreatedAt   time.Time         `json:"created_at"`
    StartedAt   *time.Time        `json:"started_at,omitempty"`
    Labels      map[string]string `json:"labels,omitempty"`
    Environment map[string]string `json:"environment,omitempty"`
}
Defined at /home/daytona/workspace/source/sdk/go/rexec.go:143.

FileInfo

type FileInfo struct {
    Name    string    `json:"name"`
    Path    string    `json:"path"`
    Size    int64     `json:"size"`
    Mode    string    `json:"mode"`
    ModTime time.Time `json:"mod_time"`
    IsDir   bool      `json:"is_dir"`
}
Defined at /home/daytona/workspace/source/sdk/go/rexec.go:204.

Error Handling

import "errors"

container, err := client.Containers.Get(ctx, "invalid-id")
if err != nil {
    var apiErr *rexec.APIError
    if errors.As(err, &apiErr) {
        fmt.Printf("API Error %d: %s\n", apiErr.StatusCode, apiErr.Message)
    } else {
        fmt.Printf("Network error: %v\n", err)
    }
}
The APIError type is defined at /home/daytona/workspace/source/sdk/go/rexec.go:133.

Source Code

View the full source code on GitHub:

License

MIT License - see LICENSE for details.

Build docs developers (and LLMs) love