Go API
Go API
Embed Shai inside Go applications for programmatic sandbox control.
Installation
1go get github.com/colony-2/shai/pkg/shaiQuick Start
1package main
2
3import (
4 "context"
5 "log"
6
7 shai "github.com/colony-2/shai/pkg/shai"
8)
9
10func main() {
11 ctx := context.Background()
12
13 // Load config from workspace
14 cfg, err := shai.LoadSandboxConfig("/path/to/workspace",
15 shai.WithReadWritePaths([]string{"src/components"}),
16 shai.WithResourceSets([]string{"frontend-dev"}),
17 )
18 if err != nil {
19 log.Fatal(err)
20 }
21
22 // Set command to run
23 cfg.PostSetupExec = &shai.SandboxExec{
24 Command: []string{"npm", "test"},
25 Workdir: "/src",
26 UseTTY: false,
27 }
28
29 // Create and run sandbox
30 sandbox, err := shai.NewSandbox(cfg)
31 if err != nil {
32 log.Fatal(err)
33 }
34 defer sandbox.Close()
35
36 if err := sandbox.Run(ctx); err != nil {
37 log.Fatal(err)
38 }
39}Core Types
SandboxConfig
Configuration for the sandbox:
1type SandboxConfig struct {
2 WorkspacePath string // Path to workspace
3 ConfigPath string // Path to .shai/config.yaml
4 ReadWritePaths []string // Paths to mount as writable
5 ResourceSets []string // Additional resource sets
6 TemplateVars map[string]string // Template variables
7 PostSetupExec *SandboxExec // Command to run
8 ImageOverride string // Override image
9 UserOverride string // Override user
10 Verbose bool // Enable verbose output
11}SandboxExec
Command execution specification:
1type SandboxExec struct {
2 Command []string // Command and args
3 Env map[string]string // Additional env vars
4 Workdir string // Working directory
5 UseTTY bool // Allocate TTY
6}Sandbox Interface
1type Sandbox interface {
2 Run(ctx context.Context) error // Run and wait
3 Start(ctx context.Context) (SandboxSession, error) // Start without waiting
4 Close() error // Cleanup
5}SandboxSession
Long-running sandbox session:
1type SandboxSession interface {
2 ContainerID() string // Get container ID
3 Wait() error // Wait for completion
4 Stop(timeout time.Duration) error // Stop gracefully
5 Close() error // Cleanup
6}Common Patterns
Running Tests
1cfg, _ := shai.LoadSandboxConfig(workspacePath,
2 shai.WithReadWritePaths([]string{"coverage"}),
3)
4
5cfg.PostSetupExec = &shai.SandboxExec{
6 Command: []string{"go", "test", "./..."},
7 UseTTY: false,
8}
9
10sandbox, _ := shai.NewSandbox(cfg)
11defer sandbox.Close()
12
13if err := sandbox.Run(ctx); err != nil {
14 // Tests failed
15}Long-Running Process
1sandbox, _ := shai.NewSandbox(cfg)
2defer sandbox.Close()
3
4// Start without waiting
5session, err := sandbox.Start(ctx)
6if err != nil {
7 log.Fatal(err)
8}
9defer session.Close()
10
11log.Printf("Container: %s", session.ContainerID())
12
13// Do other work...
14
15// Wait for completion
16if err := session.Wait(); err != nil {
17 log.Fatal(err)
18}Multiple Sandboxes
1// Run multiple sandboxes concurrently
2var wg sync.WaitGroup
3
4for _, component := range components {
5 wg.Add(1)
6 go func(comp string) {
7 defer wg.Done()
8
9 cfg, _ := shai.LoadSandboxConfig(workspacePath,
10 shai.WithReadWritePaths([]string{comp}),
11 )
12
13 sandbox, _ := shai.NewSandbox(cfg)
14 defer sandbox.Close()
15
16 sandbox.Run(ctx)
17 }(component)
18}
19
20wg.Wait()With Template Variables
1cfg, _ := shai.LoadSandboxConfig(workspacePath,
2 shai.WithTemplateVars(map[string]string{
3 "ENV": "staging",
4 "REGION": "us-east-1",
5 }),
6)Error Handling
1cfg, err := shai.LoadSandboxConfig(workspacePath)
2if err != nil {
3 // Config loading failed
4 // - Config file invalid
5 // - Template vars missing
6 // - Workspace doesn't exist
7 log.Fatal(err)
8}
9
10sandbox, err := shai.NewSandbox(cfg)
11if err != nil {
12 // Sandbox creation failed
13 // - Docker not available
14 // - Image pull failed
15 // - Invalid configuration
16 log.Fatal(err)
17}
18
19if err := sandbox.Run(ctx); err != nil {
20 // Execution failed
21 // - Command failed
22 // - Container crashed
23 // - Network error
24 log.Fatal(err)
25}Testing with Shai
Use Shai in integration tests:
1func TestMyApp(t *testing.T) {
2 ctx := context.Background()
3
4 cfg, err := shai.LoadSandboxConfig(".",
5 shai.WithReadWritePaths([]string{"tmp"}),
6 )
7 require.NoError(t, err)
8
9 cfg.PostSetupExec = &shai.SandboxExec{
10 Command: []string{"./test-script.sh"},
11 }
12
13 sandbox, err := shai.NewSandbox(cfg)
14 require.NoError(t, err)
15 defer sandbox.Close()
16
17 err = sandbox.Run(ctx)
18 assert.NoError(t, err)
19}Advanced: Custom Logging
1import "os"
2
3cfg.StdoutWriter = os.Stdout
4cfg.StderrWriter = os.Stderr
5cfg.Verbose = true
6
7sandbox, _ := shai.NewSandbox(cfg)
8// All output goes to configured writersSee Also
- GitHub Repository for complete API docs
- Examples for configuration patterns
- pkg.go.dev for API reference