gbash

package module
v0.0.22 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Mar 20, 2026 License: Apache-2.0 Imports: 13 Imported by: 0

README

gbash

A deterministic, sandbox-only, bash-like runtime for AI agents, implemented in Go.

Shell parsing and execution are owned in-tree under internal/shell, with a project-owned virtual filesystem, registry-backed command execution, policy enforcement, and structured tracing around that shell core. Commands never fall through to host binaries, and network access is off by default. Originally inspired by Vercel's just-bash.

[!WARNING] This is alpha software. It is likely that additional security hardening is needed. Use with care.

Table of Contents

Features

  • Virtual in-memory filesystem — no host access by default
  • Registry-backed command execution — unknown commands never run host binaries
  • 90+ built-in commands with GNU coreutils compatibility coverage (compatibility report)
  • Optional allowlisted network access via curl
  • Persistent sessions with shared filesystem state across executions
  • Shared JSON-RPC server mode for session-oriented hosts and wrapper binaries
  • Host directory mounting with read-only overlay for real project workspaces
  • Execution budgets — command count, loop iterations, glob expansion, stdout/stderr limits
  • Opt-in structured trace events and lifecycle logs for debugging and agent orchestration
  • WebAssembly support — runs in the browser (demo)

Public Packages

  • github.com/ewhauser/gbash: the core Go runtime and embedding API
  • github.com/ewhauser/gbash/server: shared JSON-RPC server mode for hosting persistent gbash sessions
  • github.com/ewhauser/gbash/contrib/...: optional Go command modules
  • @ewhauser/gbash-wasm/browser: the explicit browser entrypoint for the js/wasm package. It is versioned in-repo today; npm publishing remains disabled in the release workflow for now.
  • @ewhauser/gbash-wasm/node: the explicit Node entrypoint for the same js/wasm package.

Installation

Library:

go get github.com/ewhauser/gbash

CLI:

go install github.com/ewhauser/gbash/cmd/gbash@latest

Extras CLI:

go install github.com/ewhauser/gbash/contrib/extras/cmd/gbash-extras@latest

Prebuilt gbash and gbash-extras archives are also available on the GitHub Releases page. Released Go modules are also requested from the public Go proxy during the release workflow so their API docs stay current on pkg.go.dev. The coordinated release workflow also exports the website and deploys it to GitHub Pages, preserving raw compatibility assets under /compat/latest/ for the published compatibility report.

Quick Start

Try it with go run — no install required:

go run github.com/ewhauser/gbash/cmd/gbash@latest -c 'echo hello; pwd; ls -la'

You should see hello, the default working directory /home/agent, and the initial listing for the empty sandbox home directory.

Everything runs inside a virtual filesystem — nothing touches your host.

Usage

Go API

Use gbash.New to configure a runtime and Runtime.Run for one-shot execution.

package main

import (
	"context"
	"fmt"

	"github.com/ewhauser/gbash"
)

func main() {
	gb, err := gbash.New()
	if err != nil {
		panic(err)
	}

	result, err := gb.Run(context.Background(), &gbash.ExecutionRequest{
		Script: "echo hello\npwd\n",
	})
	if err != nil {
		panic(err)
	}

	fmt.Printf("exit=%d\n", result.ExitCode)
	fmt.Print(result.Stdout)
}
exit=0
hello
/home/agent
Persistent Sessions

Use Session.Exec when you want multiple shell executions to share one sandbox filesystem.

package main

import (
	"context"
	"fmt"

	"github.com/ewhauser/gbash"
)

func main() {
	ctx := context.Background()

	gb, err := gbash.New()
	if err != nil {
		panic(err)
	}

	session, err := gb.NewSession(ctx)
	if err != nil {
		panic(err)
	}

	if _, err := session.Exec(ctx, &gbash.ExecutionRequest{
		Script: "echo hello > /shared.txt\n",
	}); err != nil {
		panic(err)
	}

	result, err := session.Exec(ctx, &gbash.ExecutionRequest{
		Script: "cat /shared.txt\npwd\n",
	})
	if err != nil {
		panic(err)
	}

	fmt.Print(result.Stdout)
}
hello
/home/agent
CLI

Pipe a script to the CLI to execute it inside the sandbox:

printf 'echo hi\npwd\n' | gbash
hi
/home/agent

When stdin is a terminal, the CLI starts an interactive shell automatically:

gbash

You can also force interactive mode explicitly:

printf 'pwd\ncd /tmp\npwd\nexit\n' | gbash -i

The interactive shell reuses one sandbox session and carries forward filesystem and environment state. It exposes a session-local history command, but it does not provide readline-style line editing or job control.

For host-backed CLI runs, you can switch the filesystem mode explicitly:

gbash --root /path/to/project --cwd /home/agent/project -c 'pwd; ls'

--root mounts a host directory read-only at /home/agent/project under an in-memory writable overlay. --cwd sets the initial sandbox working directory.

For programmatic wrappers and harnesses, non-interactive runs can emit one structured JSON object instead of streaming stdout and stderr directly:

gbash -c 'echo hello' --json

The JSON payload includes stdout, stderr, exitCode, truncation flags, timing metadata, and trace metadata when the wrapper enables tracing on the underlying runtime.

For long-lived agent or editor integrations, the same shared CLI frontend can serve a JSON-RPC protocol instead of executing one script:

gbash --server --socket /tmp/gbash.sock --session-ttl 30m
gbash --server --listen 127.0.0.1:8080 --session-ttl 30m

The server speaks JSON-RPC 2.0 over either a Unix socket or an explicit loopback TCP listener. session_id maps 1:1 to a persistent sandbox session, and session.exec runs one non-interactive shell execution inside that session and returns the full result in one response. Filesystem shape is still chosen at server startup through the normal CLI/runtime options such as --root, --readwrite-root, and --cwd; it is not configured over the wire. The shared CLI requires exactly one transport flag, --socket PATH or --listen HOST:PORT, and --listen is restricted to loopback hosts because the protocol has no built-in authentication.

Install gbash-extras when you want the same CLI surface with the stable official contrib commands (awk, html-to-markdown, jq, sqlite3, and yq) pre-registered:

gbash-extras -c 'jq -r .name data.json'

gbash-extras --server --socket /tmp/gbash-extras.sock and gbash-extras --server --listen 127.0.0.1:8081 expose the same JSON-RPC protocol with the stable extras registry already installed.

The shared frontend is also exposed as the public github.com/ewhauser/gbash/cli package. Call cli.Run with a cli.Config to reuse the stock flag parsing, interactive mode, server mode, and runtime setup from your own wrapper binary. For direct embedding without going through the CLI package, use github.com/ewhauser/gbash/server.

Configuration

Filesystem

Most callers should use one of these entry points:

  • gbash.New() — default mutable in-memory sandbox
  • gbash.WithFileSystem(gbash.SeededInMemoryFileSystem(...)) — in-memory sandbox preloaded with eager or lazy files
  • gbash.WithWorkspace(root) — real host directory mounted read-only under an in-memory overlay
  • gbash.WithFileSystem(gbash.MountableFileSystem(...)) — multi-mount namespace over a base filesystem plus sibling mounts
  • gbash.WithFileSystem(gbash.ReadWriteDirectoryFileSystem(...)) — just-bash-style mutable host-backed root
  • gbash.WithFileSystem(gbash.CustomFileSystem(...)) — custom backends

Preload an in-memory sandbox with eager or lazy files:

gb, err := gbash.New(
	gbash.WithFileSystem(gbash.SeededInMemoryFileSystem(gbfs.InitialFiles{
		"/home/agent/config.json": {Content: []byte("{\"mode\":\"dev\"}\n")},
		"/home/agent/big.txt": {
			Lazy: func(ctx context.Context) ([]byte, error) {
				return fetchLargeFixture(ctx)
			},
		},
	})),
)

Compose multiple sandbox mounts under one namespace:

gb, err := gbash.New(
	gbash.WithFileSystem(gbash.MountableFileSystem(gbash.MountableFileSystemOptions{
		Mounts: []gbfs.MountConfig{
			{MountPoint: "/workspace", Factory: gbfs.Overlay(gbfs.Host(gbfs.HostOptions{Root: "/path/to/project", VirtualRoot: "/"}))},
			{MountPoint: "/cache", Factory: gbfs.Memory()},
		},
	})),
)

Mount a host directory as a read-only workspace overlay:

gb, err := gbash.New(
	gbash.WithWorkspace("/path/to/project"),
)

This mounts the host directory read-only at /home/agent/project, starts the session there, and keeps all writes in the in-memory upper layer.

For full control over the mount point or host-file read cap:

gb, err := gbash.New(
	gbash.WithFileSystem(gbash.HostDirectoryFileSystem("/path/to/project", gbash.HostDirectoryOptions{
		MountPoint: "/home/agent/project",
	})),
)

If you want writes to persist directly back to the host directory instead of landing in the in-memory overlay, use the read/write helper:

gb, err := gbash.New(
	gbash.WithFileSystem(gbash.ReadWriteDirectoryFileSystem("/path/to/project", gbash.ReadWriteDirectoryOptions{})),
	gbash.WithWorkingDir("/"),
)

This mode maps the host directory to sandbox /, so it is best suited to compatibility harnesses and other opt-in developer workflows.

Network Access

Network access is disabled by default. Enable it to register curl in the sandbox.

For simple URL allowlisting, use WithHTTPAccess:

package main

import (
	"context"
	"fmt"

	"github.com/ewhauser/gbash"
)

func main() {
	gb, err := gbash.New(
		gbash.WithHTTPAccess("https://api.example.com/v1/"),
	)
	if err != nil {
		panic(err)
	}

	result, err := gb.Run(context.Background(), &gbash.ExecutionRequest{
		Script: "curl -o /tmp/status.json https://api.example.com/v1/status\ncat /tmp/status.json\n",
	})
	if err != nil {
		panic(err)
	}

	fmt.Print(result.Stdout)
}

For fine-grained control over methods, response limits, and private-range blocking, use WithNetwork:

gb, err := gbash.New(
	gbash.WithNetwork(&gbash.NetworkConfig{
		AllowedURLPrefixes: []string{"https://api.example.com/v1/"},
		AllowedMethods:     []gbash.Method{gbash.MethodGet, gbash.MethodHead},
		MaxResponseBytes:   10 << 20,
		DenyPrivateRanges:  true,
	}),
)

Allowed URL prefixes are origin- and path-boundary aware. For example, https://api.example.com/v1 matches /v1 and /v1/..., but not /v10.

For full transport control in tests or embedding, inject your own Config.NetworkClient. See examples/oauth-network-extension for a demo that injects OAuth headers from a host-side vault so the sandbox never sees the bearer token.

Observability

Tracing and logging are disabled by default.

Use WithTracing(TraceConfig{Mode: gbash.TraceRedacted}) to populate ExecutionResult.Events for non-interactive runs and to receive structured OnEvent callbacks for both non-interactive and interactive executions. TraceRedacted is the recommended mode for agent workloads. TraceRaw preserves full argv and path metadata and should only be used when you control the sink and retention policy.

Use WithLogger to receive top-level lifecycle logs: exec.start, stdout, stderr, exec.finish, and exec.error. Logger callbacks receive the same captured stdout and stderr strings returned in ExecutionResult.

Security Model

  • The shell only sees the filesystem and runtime configuration you provide.
  • Command execution is registry-backed. Unknown commands never execute host binaries.
  • Network access is off by default. When enabled, requests are constrained by allowlists and runtime limits.
  • The default static policy applies execution budgets such as command-count, loop-iteration, glob-expansion, substitution-depth, and stdout/stderr capture limits.
  • Structured trace events are opt-in. Redacted tracing is the recommended default, and raw tracing is unsafe unless you tightly control where events go.

This is not a hardened sandbox. If you need stronger containment against denial-of-service or runtime bugs, use OS- or process-level isolation around it. For a detailed threat analysis, see THREAT_MODEL.md.

Supported Commands

The default runtime exposes registry-backed commands plus shell builtins and shims. Use gbash.DefaultRegistry() to start from the stock registry-backed command set and register custom commands on top.

Category Commands
File and path basename cat chmod chown cp dircolors dirname du file find ln link ls dir mkdir mktemp mv readlink realpath rm rmdir stat touch tree truncate unlink vdir
Search and text base32 base64 basenc column comm csplit cut diff egrep fgrep grep head join nl numfmt od paste printf rev sed seq sort split strings tac tail tee tr uniq wc xan
Archive gzip gunzip tar zcat
Builtins . : [ alias break builtin cd command continue declare dirs echo eval exec exit export false getopts hash help history let local mapfile popd printf pushd pwd read readarray readonly return set shift shopt source test trap true type typeset unalias unset wait
Environment and execution arch b2sum bash cksum clear date echo env expr factor false help history id md5sum printenv pwd sh sha1sum sha224sum sha256sum sha384sum sha512sum sleep sum test timeout true tsort tty uname uptime which who whoami xargs yes
Network (when configured) curl
Extras* awk html-to-markdown jq sqlite3 yq

* Use gbash-extras for extras commands.

Some builtin names, such as echo, help, history, printf, pwd, test, true, and false, are routed to gbash's registry-backed implementations and therefore also appear in the command categories above.

Shell language support also includes indexed arrays and associative arrays.

Many commands are ported from uutils/coreutils and have full GNU flag parity. See the current compatibility report.

Contrib Commands

Optional commands live in contrib/ as separate Go modules so the core library stays dependency-light. They are not registered by default.

Command Module Backed by
awk github.com/ewhauser/gbash/contrib/awk benhoyt/goawk
html-to-markdown github.com/ewhauser/gbash/contrib/htmltomarkdown JohannesKaufmann/html-to-markdown
jq github.com/ewhauser/gbash/contrib/jq itchyny/gojq
sqlite3 github.com/ewhauser/gbash/contrib/sqlite3 ncruces/go-sqlite3
yq github.com/ewhauser/gbash/contrib/yq mikefarah/yq

Use github.com/ewhauser/gbash/contrib/extras to register all contrib commands at once:

import "github.com/ewhauser/gbash/contrib/extras"

gb, err := gbash.New(gbash.WithRegistry(extras.FullRegistry()))

The same stable set is bundled in the gbash-extras CLI at github.com/ewhauser/gbash/contrib/extras/cmd/gbash-extras.

See the custom-zstd example for how to register custom commands.

Shell Features

Shell parsing and execution are provided by the project-owned shell core under internal/shell, with project-owned filesystem, command, policy, and observability layers around it.

The runtime supports a practical shell subset for agent workflows, including:

  • pipelines and redirections
  • variable expansion and command substitution
  • conditionals and loops
  • shell functions and common builtins handled by the in-tree shell core
  • virtual cd and pwd behavior against the sandbox filesystem
  • nested bash and sh execution inside the same sandbox session

It is intentionally not a full Bash reimplementation. It does not aim to provide full GNU Bash compatibility, readline-style UX, history navigation/editing, job control, or host TTY emulation.

Default Sandbox Layout

Each fresh session starts with a Unix-like virtual layout:

  • home and default working directory: /home/agent
  • scratch directory: /tmp
  • command directories: /usr/bin and /bin
  • default PATH: /usr/bin:/bin

Those command paths are virtual stubs used for shell resolution. Command implementations still come from the Go registry, not the host filesystem.

Examples

Example Description
adk-bash-chat Local CLI chatbot using adk-go with a persistent gbash bash tool session and a seeded ops analytics lab
custom-zstd Demonstrates custom command registration by adding a zstd compression/decompression command
openai-tool-call Uses the OpenAI Go SDK Responses API with gbash as a bash function tool
sqlite-backed-fs Custom gbfs.FileSystem backed by a SQLite database for persistent sandbox filesystem state
transactional-workspaces Narrated snapshot/rollback/branch demo showing how gbash sessions become reversible, inspectable shell workspaces

Development

make build, make test, and make lint cover the Go modules. See CONTRIBUTING.md for repository structure, module versioning, release process, benchmarks, and GNU coreutils compatibility testing.

For the documentation site, run make website-dev to start a local Next.js server seeded with the latest published compatibility assets from /compat/latest/.

License

This project is licensed under the Apache License 2.0. Copyright 2026 Eric Hauser.

Acknowledgements

  • just-bash sparked the idea for gbash and provided the starting point for the initial port.
  • mvdan/sh provides the shell parser and interpreter foundation that gbash forks and builds on in-tree.
  • uutils/coreutils provides the baseline behavior and implementations behind many of the command ports.
  • bashkit contributed strong ideas for structuring shell conformance testing well.

Documentation

Overview

Package gbash provides the primary embedding API for the gbash sandbox.

The root package is the intended entry point for most callers. It exposes the runtime, session, execution request/result types, and the opinionated configuration helpers that cover the common embedding cases:

  • create an isolated in-memory sandbox with New
  • mount a real host directory into the sandbox with WithWorkspace
  • enable allowlisted HTTP access for curl with WithHTTPAccess or WithNetwork
  • customize the registry, policy, or filesystem with explicit options when you need lower-level control

Most embedders should only import the root package. Advanced integrations may also import the supported extension packages:

  • commands for custom command authorship and registry customization
  • fs for custom filesystem backends and factories
  • network for sandbox HTTP client customization
  • policy for sandbox policy implementations
  • trace for structured execution event consumption when callers opt in to tracing on the runtime

Packages under internal/ and other undocumented subpackages are not public API.

Index

Constants

View Source
const (
	// MethodGet allows HTTP GET requests.
	MethodGet = network.MethodGet
	// MethodHead allows HTTP HEAD requests.
	MethodHead = network.MethodHead
	// MethodPost allows HTTP POST requests.
	MethodPost = network.MethodPost
	// MethodPut allows HTTP PUT requests.
	MethodPut = network.MethodPut
	// MethodDelete allows HTTP DELETE requests.
	MethodDelete = network.MethodDelete
	// MethodPatch allows HTTP PATCH requests.
	MethodPatch = network.MethodPatch
	// MethodOptions allows HTTP OPTIONS requests.
	MethodOptions = network.MethodOptions
)
View Source
const (
	// DefaultWorkspaceMountPoint is the default sandbox mount point used by
	// [WithWorkspace] and [HostDirectoryFileSystem].
	DefaultWorkspaceMountPoint = gbfs.DefaultHostVirtualRoot
	// DefaultHostFileReadBytes is the default per-file read cap used when a host
	// directory is mounted into the sandbox.
	DefaultHostFileReadBytes = gbfs.DefaultHostMaxFileReadBytes
)
View Source
const (
	// TraceOff disables structured execution events.
	TraceOff = internalruntime.TraceOff
	// TraceRedacted enables structured events with argv redaction for
	// secret-bearing values. This is the recommended mode for agent workloads.
	TraceRedacted = internalruntime.TraceRedacted
	// TraceRaw enables full structured events without argv redaction.
	//
	// This mode is unsafe for shared logs or centralized telemetry unless the
	// embedder controls retention and sink access tightly.
	TraceRaw = internalruntime.TraceRaw
)
View Source
const (
	// LogExecStart fires before the shell engine begins execution.
	LogExecStart = internalruntime.LogExecStart
	// LogStdout carries the final captured stdout for one execution.
	LogStdout = internalruntime.LogStdout
	// LogStderr carries the final captured stderr for one execution.
	LogStderr = internalruntime.LogStderr
	// LogExecFinish fires when execution completes normally, including shell
	// exit statuses and timeout/cancel control outcomes.
	LogExecFinish = internalruntime.LogExecFinish
	// LogExecError fires when gbash returns an unexpected runtime error rather
	// than a normal shell exit status.
	LogExecError = internalruntime.LogExecError
)

Variables

This section is empty.

Functions

func DefaultRegistry

func DefaultRegistry() *commands.Registry

DefaultRegistry returns a registry populated with gbash's built-in commands.

Callers can register additional custom commands onto the returned registry before passing it to WithRegistry.

Types

type Config

type Config struct {
	// FileSystem controls how each session gets its sandbox filesystem and what
	// working directory new sessions start in.
	FileSystem FileSystemConfig

	// Registry contains the commands that can be executed inside the sandbox.
	// When nil, the default built-in registry is used.
	Registry commands.CommandRegistry

	// Policy governs path access, command limits, and other sandbox checks.
	// When nil, the default static policy is used.
	Policy policy.Policy

	// BaseEnv provides the base environment visible to each execution before any
	// per-request environment overrides are applied.
	BaseEnv map[string]string

	// Network configures the built-in HTTP client used by the curl command. When
	// nil and NetworkClient is also nil, curl is not registered in the sandbox.
	Network *NetworkConfig

	// NetworkClient replaces the built-in HTTP client. This is the advanced
	// escape hatch for tests and custom transports.
	NetworkClient network.Client

	// Tracing controls structured execution events. Tracing is off by default.
	// When enabled, [ExecutionResult.Events] is populated for non-interactive
	// executions and OnEvent receives events for both non-interactive and
	// interactive runs.
	Tracing TraceConfig

	// Logger receives top-level execution lifecycle events. Logging is off by
	// default.
	Logger LogCallback
}

Config describes the complete gbash runtime configuration.

The zero value is useful: it creates the default in-memory sandbox rooted at /home/agent with the default command registry and the default static policy.

Most callers should prefer New with a small number of option helpers such as WithWorkspace, WithHTTPAccess, WithRegistry, or WithBaseEnv. This struct is provided for callers that want to construct a configuration value explicitly before handing it to WithConfig.

type ExecutionRequest

type ExecutionRequest struct {
	Name            string
	Interpreter     string
	PassthroughArgs []string
	ScriptPath      string
	Script          string
	Args            []string
	StartupOptions  []string
	Env             map[string]string
	WorkDir         string
	Timeout         time.Duration
	ReplaceEnv      bool
	Interactive     bool
	Stdin           io.Reader
	Stdout          io.Writer
	Stderr          io.Writer
}

ExecutionRequest describes a single shell execution.

Callers usually populate [ExecutionRequest.Script] and optionally provide stdin, environment overrides, or a working directory override.

type ExecutionResult

type ExecutionResult struct {
	ExitCode      int
	ShellExited   bool
	Stdout        string
	Stderr        string
	ControlStderr string
	FinalEnv      map[string]string
	StartedAt     time.Time
	FinishedAt    time.Time
	Duration      time.Duration
	// Events contains structured execution events when tracing is enabled on the
	// runtime. It is empty by default.
	Events          []trace.Event
	StdoutTruncated bool
	StderrTruncated bool
}

ExecutionResult captures the output, exit status, timing, and optional trace events produced by a shell execution.

type FileSystemConfig

type FileSystemConfig struct {
	// Factory builds the filesystem instance for a new session.
	Factory gbfs.Factory

	// WorkingDir is the directory new sessions start in.
	WorkingDir string
}

FileSystemConfig describes how gbash provisions a session filesystem.

Callers rarely need to populate this struct directly. Prefer the helper constructors InMemoryFileSystem, SeededInMemoryFileSystem, HostDirectoryFileSystem, MountableFileSystem, ReadWriteDirectoryFileSystem, and CustomFileSystem, and then apply the result with WithFileSystem.

func CustomFileSystem

func CustomFileSystem(factory gbfs.Factory, workingDir string) FileSystemConfig

CustomFileSystem wires an arbitrary filesystem factory into the runtime.

This is the low-level escape hatch for callers that want to seed a custom filesystem backend or provide their own persistence model.

func HostDirectoryFileSystem

func HostDirectoryFileSystem(root string, opts HostDirectoryOptions) FileSystemConfig

HostDirectoryFileSystem mounts a real host directory into the sandbox under a writable in-memory overlay.

The mounted host tree is read-only. All writes, deletes, and command stubs live in the in-memory upper layer, so shell activity never mutates the host directory directly.

func InMemoryFileSystem

func InMemoryFileSystem() FileSystemConfig

InMemoryFileSystem returns the default mutable sandbox filesystem configuration.

This is the same filesystem layout gbash uses when New is called without a filesystem option.

func MountableFileSystem

func MountableFileSystem(opts MountableFileSystemOptions) FileSystemConfig

MountableFileSystem returns a multi-mount filesystem configuration.

func ReadWriteDirectoryFileSystem

func ReadWriteDirectoryFileSystem(root string, opts ReadWriteDirectoryOptions) FileSystemConfig

ReadWriteDirectoryFileSystem mounts a real host directory as the mutable sandbox root.

This is the closest gbash equivalent to just-bash's ReadWriteFs: sandbox paths are rooted at "/", sessions start at "/", and writes persist directly to the host directory.

func SeededInMemoryFileSystem

func SeededInMemoryFileSystem(files gbfs.InitialFiles) FileSystemConfig

SeededInMemoryFileSystem returns an in-memory filesystem configuration preloaded with the provided files.

type HostDirectoryOptions

type HostDirectoryOptions struct {
	// MountPoint is the sandbox path where the host directory should appear.
	// When empty, [DefaultWorkspaceMountPoint] is used.
	MountPoint string

	// MaxFileReadBytes limits the size of individual regular files that may be
	// read from the host directory. When zero or negative, the default host read
	// cap is used.
	MaxFileReadBytes int64
}

HostDirectoryOptions controls how a real host directory is mounted into the sandbox.

The mounted directory is always read-only from the host's perspective. gbash layers an in-memory writable upper filesystem on top so the shell can create, overwrite, and delete files without mutating the host tree.

type InteractiveRequest

type InteractiveRequest struct {
	Name           string
	Args           []string
	StartupOptions []string
	Env            map[string]string
	WorkDir        string
	ReplaceEnv     bool
	Stdin          io.Reader
	Stdout         io.Writer
	Stderr         io.Writer
}

InteractiveRequest describes an interactive shell session.

type InteractiveResult

type InteractiveResult struct {
	ExitCode int
}

InteractiveResult captures the final exit status from an interactive shell session.

type LogCallback

type LogCallback = internalruntime.LogCallback

LogCallback receives top-level execution lifecycle logs.

Callbacks run synchronously on the execution path. Panics are recovered and ignored so observability hooks do not fail shell execution.

type LogEvent

type LogEvent = internalruntime.LogEvent

LogEvent describes one top-level execution lifecycle log callback.

type LogKind

type LogKind = internalruntime.LogKind

LogKind identifies a high-level execution lifecycle log event.

type Method

type Method = network.Method

Method identifies an HTTP method that is allowed by the sandbox network policy.

type MountableFileSystemOptions

type MountableFileSystemOptions struct {
	// Base provisions the base filesystem used for unmounted paths. When nil, a
	// fresh in-memory filesystem is used.
	Base gbfs.Factory

	// Mounts configures the mounted filesystems visible inside the sandbox.
	Mounts []gbfs.MountConfig

	// WorkingDir is the directory new sessions start in. When empty,
	// /home/agent is used.
	WorkingDir string
}

MountableFileSystemOptions configures a multi-mount sandbox filesystem.

type NetworkConfig

type NetworkConfig struct {
	// AllowedURLPrefixes is the URL allowlist for sandbox HTTP access.
	AllowedURLPrefixes []string

	// AllowedMethods restricts which HTTP methods may be used. When empty, GET
	// and HEAD are allowed.
	AllowedMethods []Method

	// MaxRedirects limits how many redirects a request may follow.
	MaxRedirects int

	// Timeout is the default request timeout.
	Timeout time.Duration

	// MaxResponseBytes caps the response body size.
	MaxResponseBytes int64

	// DenyPrivateRanges blocks requests to private, loopback, link-local, and
	// similar address ranges.
	DenyPrivateRanges bool
}

NetworkConfig controls the built-in HTTP client that powers curl inside the sandbox.

All fields are optional except that some form of URL allowlist is required at runtime. Empty AllowedMethods defaults to GET and HEAD. Zero-valued limits use the network package defaults.

type Option

type Option func(*Config) error

Option mutates a Config before New constructs the runtime.

Options are applied in order, so later options can intentionally override earlier ones.

func WithBaseEnv

func WithBaseEnv(env map[string]string) Option

WithBaseEnv replaces the base environment inherited by each execution.

func WithConfig

func WithConfig(cfg *Config) Option

WithConfig overlays non-zero fields from cfg onto the runtime configuration.

This is useful when configuration is assembled ahead of time and then applied as one option to New.

func WithFileSystem

func WithFileSystem(cfg FileSystemConfig) Option

WithFileSystem replaces the session filesystem configuration.

func WithHTTPAccess

func WithHTTPAccess(prefixes ...string) Option

WithHTTPAccess enables curl with a URL allowlist and the default HTTP policy.

This is the simplest way to turn on network access. Requests are restricted to the provided URL prefixes, and all other HTTP settings use the defaults from the network package.

func WithLogger

func WithLogger(callback LogCallback) Option

WithLogger installs a top-level execution lifecycle log callback.

func WithNetwork

func WithNetwork(cfg *NetworkConfig) Option

WithNetwork replaces the built-in HTTP client configuration used by curl.

Use this option when you want to customize methods, limits, timeouts, or private-range denial behavior while still relying on the standard gbash HTTP client implementation.

func WithNetworkClient

func WithNetworkClient(client network.Client) Option

WithNetworkClient injects a fully custom HTTP client for curl.

This is the advanced escape hatch for tests and unusual embedding scenarios where the built-in allowlist-based client is not sufficient.

func WithPolicy

func WithPolicy(p policy.Policy) Option

WithPolicy replaces the sandbox policy implementation.

func WithRegistry

func WithRegistry(registry commands.CommandRegistry) Option

WithRegistry replaces the command registry visible inside the sandbox.

func WithTracing

func WithTracing(cfg TraceConfig) Option

WithTracing replaces the runtime tracing configuration.

func WithWorkingDir

func WithWorkingDir(dir string) Option

WithWorkingDir overrides the initial working directory for new sessions.

This option composes with both the default in-memory sandbox and any explicit filesystem option such as WithWorkspace or WithFileSystem.

func WithWorkspace

func WithWorkspace(dir string) Option

WithWorkspace mounts dir into the sandbox under a writable in-memory overlay and starts new sessions in that mounted directory.

This is the intended happy-path option for embedding gbash against a real codebase or workspace on disk.

type ReadWriteDirectoryOptions

type ReadWriteDirectoryOptions struct {
	// MaxFileReadBytes limits the size of individual regular files that may be
	// read from the host directory. When zero or negative, the default host read
	// cap is used.
	MaxFileReadBytes int64
}

ReadWriteDirectoryOptions controls how a real host directory is mounted as a mutable sandbox root.

Unlike HostDirectoryOptions, this mode writes directly back to the host directory instead of using an in-memory overlay. It is intended for opt-in compatibility harnesses and advanced embedding scenarios.

type Runtime

type Runtime struct {
	// contains filtered or unexported fields
}

Runtime executes bash-like scripts inside the configured sandbox.

Use New to construct a runtime, Runtime.Run for one-shot execution, and Runtime.NewSession when you want multiple executions to share the same sandbox filesystem state.

func New

func New(opts ...Option) (*Runtime, error)

New constructs a runtime from the provided options.

When called with no options, New returns the default sandbox runtime:

  • an isolated in-memory filesystem rooted at /home/agent
  • the built-in command registry
  • the default in-tree shell core
  • the default static policy and resource limits
  • no network access

Use WithWorkspace to mount a real host directory, WithHTTPAccess or WithNetwork to enable curl, and WithRegistry, WithPolicy, or WithFileSystem when you need lower-level control.

func (*Runtime) NewSession

func (r *Runtime) NewSession(ctx context.Context) (*Session, error)

NewSession creates a new persistent session backed by the runtime's configured filesystem factory and sandbox policy.

Each session gets its own filesystem state. Repeated calls create isolated sessions, while repeated calls to Session.Exec on the same session share the same sandbox filesystem.

func (*Runtime) Run

Run executes a script in a fresh session and returns the result.

Use Runtime.NewSession when you want filesystem state to persist across multiple executions.

type Session

type Session struct {
	// contains filtered or unexported fields
}

Session is a persistent sandbox that can execute multiple scripts against the same filesystem state.

Sessions are created by calling Runtime.NewSession.

func (*Session) Exec

Exec runs a script inside the existing session.

Session executions share filesystem state with each other, but shell-local state such as the working directory and environment only persists when the caller explicitly threads it through later requests.

func (*Session) FileSystem

func (s *Session) FileSystem() gbfs.FileSystem

FileSystem returns the live sandbox filesystem for the session.

Most callers do not need this method. It exists as an advanced escape hatch for tests, bootstrapping, and integrations that need direct filesystem access. Callers should treat the result as the gbfs.FileSystem interface and should not rely on concrete backend types.

func (*Session) Interact

func (s *Session) Interact(ctx context.Context, req *InteractiveRequest) (*InteractiveResult, error)

Interact runs an interactive shell session inside the existing session.

type TraceConfig

type TraceConfig = internalruntime.TraceConfig

TraceConfig configures structured execution tracing.

When Mode is TraceOff, [ExecutionResult.Events] is empty and OnEvent is not called. Interactive executions only deliver events to OnEvent; they do not return events in an InteractiveResult.

type TraceMode

type TraceMode = internalruntime.TraceMode

TraceMode controls whether gbash records structured execution events.

Directories

Path Synopsis
cmd
Package cmd documents the shipped gbash CLI entrypoints.
Package cmd documents the shipped gbash CLI entrypoints.
gbash command
Package main provides the primary gbash CLI entrypoint.
Package main provides the primary gbash CLI entrypoint.
gbash-gnu command
Package main provides the GNU compatibility harness used by the gbash project.
Package main provides the GNU compatibility harness used by the gbash project.
Package commands provides the stable command authoring and registry API for gbash.
Package commands provides the stable command authoring and registry API for gbash.
Package contrib documents the layout of the optional gbash extension modules.
Package contrib documents the layout of the optional gbash extension modules.
awk module
extras module
jq module
nodejs module
sqlite3 module
yq module
Package fs provides the filesystem contracts and virtual filesystem backends used by gbash, including the default mutable in-memory backend and the experimental read-mostly trie-backed backend.
Package fs provides the filesystem contracts and virtual filesystem backends used by gbash, including the default mutable in-memory backend and the experimental read-mostly trie-backed backend.
internal
builtins
Package builtins provides gbash's shipped command implementations and default registry assembly.
Package builtins provides gbash's shipped command implementations and default registry assembly.
runtime
Package runtime implements the internal execution engine that backs the public gbash API.
Package runtime implements the internal execution engine that backs the public gbash API.
shell
Package shell provides gbash's project-owned shell core plus the in-tree parser, expansion, and interpreter packages it executes against.
Package shell provides gbash's project-owned shell core plus the in-tree parser, expansion, and interpreter packages it executes against.
shell/expand
Package expand contains code to perform various shell expansions.
Package expand contains code to perform various shell expansions.
shell/fileutil
Package fileutil allows inspecting shell files, such as detecting whether a file may be shell or extracting its shebang.
Package fileutil allows inspecting shell files, such as detecting whether a file may be shell or extracting its shebang.
shell/interp
Package interp implements an interpreter to execute shell programs parsed by the syntax package.
Package interp implements an interpreter to execute shell programs parsed by the syntax package.
shell/pattern
Package pattern allows working with shell pattern matching notation, also known as wildcards or globbing.
Package pattern allows working with shell pattern matching notation, also known as wildcards or globbing.
shell/syntax
Package syntax implements parsing and formatting of shell programs.
Package syntax implements parsing and formatting of shell programs.
shell/syntax/typedjson
Package typedjson allows encoding and decoding shell syntax trees as JSON.
Package typedjson allows encoding and decoding shell syntax trees as JSON.
Package network provides the sandboxed HTTP client used by gbash.
Package network provides the sandboxed HTTP client used by gbash.
Package packages documents the non-Go distribution packages shipped from this repository.
Package packages documents the non-Go distribution packages shipped from this repository.
gbash-wasm/wasm command
Package main exposes the js/wasm entrypoint for the GBashWasm browser API.
Package main exposes the js/wasm entrypoint for the GBashWasm browser API.
Package policy provides low-level sandbox policy types and enforcement helpers for gbash.
Package policy provides low-level sandbox policy types and enforcement helpers for gbash.
Package scripts documents the repository's Go-based maintenance and reporting utilities.
Package scripts documents the repository's Go-based maintenance and reporting utilities.
bench-compare command
Package main provides the benchmark comparison tool used by the gbash repository.
Package main provides the benchmark comparison tool used by the gbash repository.
bench-compare/gbash-runner command
Package main provides the helper command used by the gbash benchmark comparison harness.
Package main provides the helper command used by the gbash benchmark comparison harness.
compat-report command
Package main provides the GNU compatibility report renderer used by the gbash repository.
Package main provides the GNU compatibility report renderer used by the gbash repository.
Package server exposes a shared JSON-RPC server mode for gbash runtimes.
Package server exposes a shared JSON-RPC server mode for gbash runtimes.
Package trace provides the structured execution event model used by gbash.
Package trace provides the structured execution event model used by gbash.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL