Go package
Every exported identifier in pkg/boxer, for opening, running and managing sandboxes from Go.
import "github.com/BarakChamo/boxer/pkg/boxer"pkg/boxer is the module's only importable package. Everything else is under internal/. It
calls the same code the CLI does, so a Box reads the worktree's boxer.toml and behaves as
boxer run would there. The stability contract
covers its exported functions, types and fields from 1.0.
b, err := boxer.Open("/Users/me/src/app-wt1", boxer.Options{})
if err != nil {
return err
}
if _, err := b.Ensure(true, false); err != nil {
return err
}
code, err := b.Run([]string{"sh", "-c", "npm test"}, boxer.RunOpts{Stdout: os.Stdout, Stderr: os.Stderr})examples/go-embed runs one
shell line in several worktrees at once through this package and reports each exit code.
Build on boxer covers when to use it and what to check before you ship.
Index
| Identifier | Kind |
|---|---|
Open | func |
List, ListAll, Stop, Delete, LastUsed | func |
Ports, URLs | func |
Box | type, with Scope, Warnings, Ensure, Run, Status, Down |
Options | type |
RunOpts | type alias |
Machine | type alias |
Scope | type alias |
Error | type alias |
Open
func Open(cwd string, o Options) (*Box, error)Resolves the sandbox for cwd, or for the process working directory when cwd is empty. It reads
configuration and does not create anything. The error is a *Error when boxer refused, with cause
NO_REPOSITORY, WORKTREE_REQUIRED or SCOPE_UNRESOLVED, and a plain error when boxer.toml is
invalid.
Options
type Options struct {
Harness string
SessionID string
AgentID string
}Every field may be empty.
| Field | |
|---|---|
Harness | Selects the [harness.<name>] override layer |
SessionID | The session id for isolation = "session" |
AgentID | The subagent id for isolation = "subagent" |
Box
type Box struct { /* unexported */ }The sandbox resolved for one working directory. Its methods are safe to call on a running sandbox.
Box.Scope
func (b *Box) Scope() ScopeThe resolved scope.
Box.Warnings
func (b *Box) Warnings() []stringNon-fatal findings from resolution, such as running in the main checkout or degraded isolation.
Box.Ensure
func (b *Box) Ensure(allowCreate, recreate bool) (created bool, err error)Makes the machine exist and run. When it starts one, it runs setup and start and waits for
ready; a machine already running is returned as it is. It creates a machine only
when allowCreate is set. Otherwise a missing sandbox fails with cause NO_SANDBOX. recreate deletes an
existing machine first. created reports whether a machine was created.
Box.Run
func (b *Box) Run(argv []string, o RunOpts) (int, error)Executes argv in the guest and returns its exit code. It provisions first when
create_on includes run. A non-nil error means the
command did not run. -1 with an error means
on_sandbox_unavailable = "passthrough"
applies and you may run argv on the host.
Box.Status
func (b *Box) Status() (Machine, bool, error)The machine, and whether it exists.
Box.Down
func (b *Box) Down() errorDeletes the machine. Absence is not an error.
List
func List() ([]Machine, error)Every boxer-owned machine on the host backend.
ListAll
func ListAll() ([]Machine, error)Every boxer-owned machine on every backend installed on this host, with Machine.Backend set to
the backend's name. A backend that is installed and not answering is skipped. Its error is returned
beside the machines the other backends listed, so check both. Same as boxer ls -A.
Ports
func Ports(m Machine) map[string]stringA machine's forwarded ports, guest port to host port, read from its boxer.port.<guest> labels.
Empty when it forwards none.
URLs
func URLs(m Machine) map[string]stringA URL for each forwarded port, keyed by guest port: the portless name when
[urls] is on and the route is registered, otherwise
http://127.0.0.1:<host port>. Same as boxer url --all.
ms, _ := boxer.ListAll()
for _, m := range ms {
if m.Running() {
fmt.Println(m.Backend, m.Name, boxer.URLs(m)["3000"])
}
}Stop
func Stop(name string) errorStops one machine by name without deleting it. boxer status reports a stopped machine as exit 3. Stopping a
stopped machine is not an error. Same as boxer stop NAME.
Delete
func Delete(name string) errorRemoves one machine by name, and what boxer kept about it: its run record, last-used stamp, lock and
URLs, as boxer rm NAME does. Its volumes are kept.
LastUsed
func LastUsed(name string) time.TimeWhen the scope last ran a command, or the zero time when unknown.
List, Stop, Delete and LastUsed take a machine name instead of a directory because the
worktree may be gone. List, Stop and Delete act on the backend the CLI would use from the
process's working directory. That is BOXER_BACKEND if set, else the backend boxer.toml names,
else smolvm.
RunOpts
type RunOpts = box.RunOpts
type RunOpts struct {
Stdin io.Reader
Stdout io.Writer
Stderr io.Writer
TTY bool
Timeout time.Duration
Task string
}The fields set the streams, whether to request a terminal, a timeout (zero for none), and the
[tasks] name to record in the run record. Pass the same writer as Stdout and Stderr to get one interleaved
stream.
Machine
type Machine = vm.Machine
type Machine struct {
Name string
State string
Image string
Labels map[string]string
CreatedAt int64
PID int
CPUs int
MemoryMiB int
Backend string
}
func (m Machine) Running() boolOne sandbox on any backend. Name is the scope key. CreatedAt is Unix seconds. Backend is set
only by ListAll. Labels carry
boxer's boxer.* keys, which are stable:
| Label | Value |
|---|---|
boxer.root | the worktree |
boxer.isolation | the isolation it was created with |
boxer.port.<guest> | the host port a guest port is forwarded to |
boxer.harness, boxer.session, boxer.agent | the identity it was created for, when set |
Scope
type Scope = scope.Scope
type Scope struct {
Key string
Isolation string
Root string
Degraded bool
Reason string
}
func (s Scope) Slug() string
func (s Scope) Names() stringKey is sb- plus twelve hex characters and is the machine name. Isolation is the isolation
used after degradation, and Reason says why when Degraded is set. Root is the mounted
worktree. Slug is the two-word name (swift-crab). Names is swift-crab (sb-7e1852e4a3c3).
Error
type Error = box.Error
type Error struct {
Reason string
Cause string
Fix string
Scope Scope
}
func (e *Error) Error() stringThe error boxer returns when it refuses. Error() returns the same multi-line text the CLI prints.
var be *boxer.Error
if errors.As(err, &be) {
log.Printf("%s (%s)\n fix: %s", be.Reason, be.Cause, be.Fix)
}Match on Cause, which is stable. Do not match on the message. The
full list is on the JSON page. The same causes appear in --json
output and in failed MCP tool calls.