Skip to content

Releases: streamingfast/sbox

v1.9.0

12 May 14:43

Choose a tag to compare

Fixed

  • Fix sbox run hanging on startup when stdin is not a terminal but no data is piped to it (e.g. when launched from certain IDEs, shells, or CI environments). The command now uses a zero-timeout select call to check if stdin data is immediately available before attempting to read it, preventing the indefinite block.

  • Fix sbox run prompt argument being rejected when it starts with --- (e.g. YAML front-matter): dashes-only strings are no longer treated as CLI flags.

  • Fix extra blank lines in markdown rendering for both claude and opencode stream printers. Glamour pads rendered lines with ANSI-colored spaces that strings.TrimSpace cannot detect as blank, causing those padding lines to appear as blank lines in the output. The fix applies ANSI-aware blank detection using ansi.Strip before trimming, and switches glamour word wrap to 0 to prevent trailing-space padding entirely.

  • Fix Label output for long values (e.g. Prompt, Goal): values are now collapsed to a single line and truncated to 100 characters with a trailing ... to prevent multi-line or excessively long terminal output.

Added

  • Add --watch <regex> flag to sbox run. When specified (can be given multiple times), after the interactive session exits the command stays alive and watches for changes to workspace files whose relative path matches any of the given regex patterns. Any matching write or create event triggers a new session. Watches are inactive while the agent is running.

  • Add stdin support to sbox run. When stdin is not a terminal (i.e., piped), its content is automatically used as the prompt. For example: cat TASK.md | sbox run. If a prompt argument is also provided, the argument takes precedence over stdin.

  • Add optional prompt argument to sbox run. Running sbox run "<prompt>" launches the agent interactively with the given prompt pre-seeded. For Claude, the prompt is passed as a positional argument; for OpenCode, it is passed via --prompt. The session remains interactive after the prompt is processed. Extra agent args via -- continue to work alongside the prompt.

  • Add timing summary to sbox loop completion report. When a loop finishes (goal confirmed or max iterations reached), the output now includes a "Timing Summary" section showing the total elapsed time for the entire loop and the duration of each individual iteration.

  • Add --watch <regex> flag to sbox loop. When specified (can be given multiple times), after the loop completes the command stays alive and watches for changes to workspace files whose relative path matches any of the given regex patterns. Any matching write or create event triggers a new loop run with the same prompt. Watches are inactive while the loop is running. The sandbox/container is kept warm between watch-triggered runs and only stopped on exit (Ctrl+C or error).

  • Add git worktree support for all three isolation backends (container, sandbox, sbx). When the workspace is a git linked worktree (has a .git file instead of a .git/ directory), sbox automatically makes the main repository root accessible inside the sandbox at the same absolute path. This allows git operations to resolve the gitdir path embedded in the worktree's .git file. Container backend uses a bind mount; sandbox and sbx backends pass it as an extra workspace to docker sandbox create / sbx create.

  • Add sbox stop all, sbox stop sandbox, and sbox stop container subcommands for globally stopping least-recently-used sandboxes and containers without removing them. Each subcommand supports --keep N (default 3) to keep the N most recently used running, and --force to actually stop (dry-run by default). Useful to free file descriptor limits when many sandboxes/containers are running simultaneously.

  • Add disk size information to sbox info output. For container backend, shows the container's writable layer size and, if present, the associated named volume size (e.g. 234 MB (container) + 1.1 GB (volume)). For sandbox backend, attempts to retrieve the sandbox VM disk size via docker sandbox inspect. Size is omitted silently if unavailable.

  • Add sbx backend for Docker Sandbox MicroVMs managed by the top-level sbx CLI tool. Sandbox names follow the <agent>-<workspace> convention (no sbox- prefix). Select it via --backend sbx, sbox.yaml, or project/global config.

  • Add sbox stop sbx subcommand for LRU-based stopping of sbx sandboxes (mirrors sbox stop sandbox).

v1.8.0

29 Apr 20:42

Choose a tag to compare

Added

  • Add libclang-dev to the rust profile, required by crates that use bindgen or link against LLVM/Clang.

  • Install cargo-nextest in the rust profile via the official pre-built binary from get.nexte.st. Architecture-aware (amd64linux, arm64linux-arm).

  • Add exclude_dirs config option to sbox.yaml and per-project config. Lists workspace-relative directories to shadow with anonymous Docker volumes, preventing them from being synced to the host. Solves "too many open files" on macOS when working with large build output trees (e.g. target/ for Rust, node_modules/ for Node). Only applies to the container backend. Anonymous volumes are cleaned up automatically when the container is removed (docker rm -v).

  • Add --backend=host support. The host backend runs the AI agent directly on the host machine with no Docker or MicroVM isolation. Supports interactive mode, single-prompt mode, and loop mode (sbox loop). The .sbox/ directory is still written for CLAUDE.md injection and env vars. sbox shell and sbox info print a clear unsupported message with exit code 1 when the host backend is active. Using --profile with the host backend shows a warning that profiles are ignored.

  • Add support for forwarding extra arguments to the agent binary via -- on sbox run (e.g. sbox run -- --resume <session-id>). Arguments after -- are passed verbatim to the agent.

  • Add sbox prune <all|sandbox> command to reclaim disk space by removing old and stale sandboxes. Sandboxes whose workspace directory no longer exists are always pruned; the rest are kept based on a --keep N (default 5) most-recently-used policy. Dry-run by default; use --force to actually delete. Each pruned sandbox removes the Docker sandbox, its .sbox/ directory, and the project config entry in ~/.config/sbox/projects/. Projects are inspected concurrently (2×CPU) using destel/rill for faster scanning on large project lists or slow filesystems.

  • Add sbox stop support for the host backend. When the host backend starts an agent, its PID is recorded in .sbox/host.pid. sbox stop reads this file, sends SIGTERM to the process, and escalates to SIGKILL after 5 seconds if needed. The PID file is removed after the process exits.

  • Add load_claude_skills setting in sbox.yaml (opt-in, default off). When enabled for OpenCode sessions, installed Claude Code plugin SKILL.md files are automatically converted to OpenCode rules at startup and written to ~/.config/opencode/rules/. This bridges Claude Code's on-demand skill concept to OpenCode's always-on rules system. !command interpolation in skill bodies is preserved as-is for the agent to handle.

  • Forward host git identity (user.name, user.email) into the sandbox automatically. Values are read from the host's global git config and injected via GIT_CONFIG_COUNT/GIT_CONFIG_KEY_n/GIT_CONFIG_VALUE_n env vars (git 2.31+), making them available to the agent without touching ~/.gitconfig. Skipped silently if not set on the host, or if GIT_CONFIG_COUNT is already present in the environment.

Added

  • Add sbox prune container subcommand to find and prune orphan Docker containers whose name starts with sbox- and whose workspace no longer exists or that have not been used recently. On prune: stops the container, removes it, then removes its associated named sbox- volume. Supports the same --keep, --force, and --protect/-p flags as sbox prune sandbox. Renders candidates in lipgloss tables with Container, Workspace, and Last Used columns.
  • Add ContainerPruneCandidate type, FindContainerPruneCandidates, PruneOneContainer, and getContainerVolumeName to the sbox package to support container-level pruning.

Changed

  • Update sbox prune all to run both sandbox pruning and container pruning, displaying results in separate === Sandboxes === and === Containers === sections. Previously all was equivalent to sandbox.
  • Remove plugin forwarding from the host backend. When running with --backend=host the agent is already on the host where plugins live natively in its own config directory (e.g. ~/.claude/plugins). Passing redundant --plugin-dir flags is no longer needed and has been removed.
  • Rework sbox prune output into three styled lipgloss table sections — "Pruning N sandbox(es) | Missing", "Pruning N sandbox(es) | Too old", and "Keeping N sandbox(es)" — each only shown when non-empty. Uses the new stylex/ package and github.com/charmbracelet/lipgloss/table for consistent terminal styling.
  • Add blank line between each prune table section for readability.
  • Add named-sandbox targeting to sbox prune sandbox: pass one or more sandbox names as arguments to target them specifically for deletion. Matched sandboxes are shown in a "Pruning N sandbox(es) | Named" table; unrecognised names appear in a separate "Unknown N sandbox(es)" table. Dry-run and --force behaviour are preserved.
  • Add --protect/-p flag to sbox prune all and sbox prune sandbox to exempt specific sandboxes from deletion. Accepts comma-separated names per flag value and can be repeated (-p a,b -p c). Protected candidates that would otherwise have been pruned appear in a "Protected N sandbox(es)" table instead.

Fixed

  • Fix sbox prune orphan detection including Docker sandboxes created by unrelated tools. Orphan candidates are now limited to sandboxes whose name starts with sbox-.
  • Fix sbox prune incorrectly associating a live Docker sandbox with a stale project entry when both share the same sandbox name but different workspaces (e.g. two reth directories). The name-based fallback lookup now verifies that the sandbox's recorded workspace matches the project before claiming it; if it differs the sandbox is considered unrelated and is left untouched.
  • Fix terminal env vars (TERM, COLORTERM, TERM_PROGRAM, TERM_PROGRAM_VERSION) not being forwarded to existing containers, causing broken TUI rendering and non-functional OSC 8 hyperlinks (Cmd+click on URLs). The previous approach set them via docker run -e flags which only apply at container creation time. They are now written to .sbox/env on every run and loaded by the entrypoint via loadEntrypointEnv, making them available to both Claude and OpenCode regardless of whether the container is new or pre-existing.
  • Fix sandbox firewall instructions inside the sandbox injecting the wrong sandbox name (e.g. firehose-core instead of sbox-opencode-firehose-core). The sandbox context MD now uses a {{SBOX_SANDBOX_NAME}} placeholder that is substituted with the actual Docker sandbox name at prep time. The command is also wrapped in backticks for clean copy-paste.

v1.7.1

31 Mar 17:58

Choose a tag to compare

Fixed

  • Fixed image building mismatch between Golang version and Docker build binary version.

v1.7.0

31 Mar 17:54

Choose a tag to compare

Added

  • Add sbox backend command group (list, set, show) to manage the default container backend globally, mirroring the existing sbox agent command group.
  • Add default_backend and default_agent keys to sbox config for viewing and setting defaults via the config command.

Changed

  • Clarify .sbox/ directory purpose in both backend instruction files: it is a bidirectional host↔sandbox exchange directory, not read-only. Document what belongs there (user uploads, dependency repos being fixed) vs what does not (temporary logs, reference clones, scratch files).
  • Replace direct bind-mounts of settings.json/settings.local.json (both container and sandbox backends) with a copy-merge approach: host settings are copied to .sbox/ with bypass-permissions enforced, then merged into the sandbox agent home on startup. Sandbox-side changes (e.g. model, theme) are preserved across restarts while host-side updates (e.g. MCP servers) are applied on each run.

Fixed

  • Fix sbox info showing claude in docker sandbox create command regardless of the configured agent. Now correctly displays the resolved agent binary (e.g. opencode).
  • Fix container backend not forwarding TERM and COLORTERM env vars from host, causing incorrect colors and broken ANSI links compared to sandbox mode.
  • Fix container backend mounting settings.json and settings.local.json as read-only, causing EROFS errors when the agent tries to modify settings (e.g. setting effort level).

v1.6.0

16 Mar 19:48

Choose a tag to compare

Added

  • sbox loop and prompt mode now support OpenCode agent (--agent=opencode). OpenCode JSON stream output (opencode run --format=json) is parsed and displayed with the same visual style as Claude stream output.
  • Add opencode package with StreamPrinter for parsing OpenCode's JSON stream format (step_start, tool_use, text, step_finish events).
  • Add PromptArgs() and NewStreamPrinter() to AgentSpec interface, making prompt/loop mode agent-agnostic.

Changed

  • Remove prompt file indirection in loop/prompt mode — prompt is now passed directly as a CLI argument instead of writing to a file and asking the agent to read it.

Fixed

  • Claude stream printer now displays context for many more tools: ToolSearch, WebSearch, WebFetch, Skill, TaskCreate, TaskUpdate, TaskOutput, NotebookEdit. Unknown tools fall back to extracting common field names (query, description, prompt, etc.) from their input.

v1.5.1

16 Mar 15:53

Choose a tag to compare

Added

  • Background agent auto-updater: sbox entrypoint now wraps the agent as a child process instead of exec'ing, runs a background update check every 15 minutes, and updates the agent binary if the last update was more than 24 hours ago. After each update, the shim wrapper is automatically repaired so the sbox entrypoint remains the entry point.
  • Disable agent's built-in auto-updater (DISABLE_AUTOUPDATER=1) to prevent it from overwriting the sbox shim wrapper. Updates are now managed by sbox itself.

v1.5.0

12 Mar 15:48

Choose a tag to compare

Added

  • sbox run --startup-delay flag to delay agent startup inside the sandbox. If set to 0, waits forever without starting the agent (useful for attaching a shell and debugging). Otherwise accepts a Go duration (e.g. 30s, 5m).
  • sbox loop --confirmations flag to configure the number of consecutive goal completions required (default: 2). Also configurable via loop_confirmations in global config (~/.config/sbox/config.yaml) or sbox.yaml.
  • sbox loop <prompt> command: runs the agent in a loop until the goal described by the prompt is completed
    • Same --backend and --agent support as sbox run
    • Augments the prompt with loop instructions so the agent knows to assess and work toward the goal
    • Agent writes .sbox/loop.completion when the goal is reached
    • Loop stops after the agent confirms completion the required number of consecutive times

Fixed

  • sbox loop now stops immediately when the agent exits with an error or is killed, instead of continuing to loop
  • sbox loop now stops the sandbox when the loop exits (completion, error, or Ctrl+C), preventing the container from running in the background
  • Fix container backend not producing output in loop/prompt mode due to TTY allocation (-it) mangling stream-json output
  • Transfer tui.json from ~/.config/opencode/tui.json to .sbox/ (host→sandbox) and from .sbox/tui.json to agent home (sandbox entrypoint) for OpenCode
  • OpenCode state persistence across sbox stop and sbox run --recreate
    • ~/.config/opencode synced to .sbox/opencode-cache/ on stop/recreate; restored on next run
    • ~/.local/share/opencode synced to .sbox/opencode-share-cache/ on stop/recreate; restored after initial file seeding so cached auth/session data takes precedence

v1.4.0

05 Mar 02:59

Choose a tag to compare

Added

  • OpenCode support as an alternative AI agent to Claude
    • --agent flag for sbox run to select the AI agent type (claude or opencode)
    • agent field in sbox.yaml to configure agent per-project
    • agent field in project config (persisted when using --agent flag)
    • default_agent field in global config (~/.config/sbox/config.yaml)
    • sbox agent command group for managing the default AI agent
      • sbox agent list — show available agents
      • sbox agent set <agent> — set default agent globally
      • sbox agent show — show current default agent
    • Agent resolution priority: CLI flag > sbox.yaml > project config > global config > default (claude)
    • Entrypoint automatically detects and launches the configured agent (claude or opencode)
    • Sandbox/container names now include agent type: sbox-<agent>-<workspace> (e.g., sbox-opencode-myproject)
      • This allows running different agents for the same workspace
      • Sandbox name is automatically regenerated when switching agents
      • Previous sandboxes named sbox-claude-<workspace> will be automatically detected for Claude agent
    • Agent-specific Docker sandbox templates:
      • Claude agent uses docker/sandbox-templates:claude-code
      • OpenCode agent uses docker/sandbox-templates:opencode
      • Template is automatically selected based on the configured agent
    • Agent abstraction via AgentSpec interface for extensibility
      • Encapsulates agent-specific behavior (binary name, wrapper name, template image, config directory, binary discovery, exec args)
      • Template builder generates agent-specific wrapper scripts (e.g., claude-wrapper or opencode-wrapper)
      • Wrapper script automatically renames agent binary to <name>-real and symlinks to wrapper for proper initialization
      • Template hash includes agent type to ensure separate template images for different agents
      • Entrypoint uses agent-specific config directories (.claude for Claude, .config/opencode for OpenCode)
      • Agent setup (CLAUDE.md/AGENTS.md, agents, plugins) works with appropriate config directory per agent
      • Container backend uses agent-specific volume names (sbox-claude-* vs sbox-opencode-*)
      • Container backend mounts agent config directory based on agent type (.claude or .opencode)
      • Settings.json mount location is agent-aware
      • Template build pre-creates agent config directory with proper ownership to avoid permission issues with volume mounts
      • OpenCode agent uses appropriate command-line arguments (no --dangerously-skip-permissions flag)
      • Entrypoint passes workspace path to OpenCode when no arguments provided
      • Config now supports agent-specific home directories (opencode_home defaults to ~/.config/opencode, claude_home defaults to ~/.claude)
      • Plugins and agents are loaded from agent-specific home directories (~/.config/opencode for OpenCode, ~/.claude for Claude)
      • Settings.json files mounted from appropriate agent home directory
      • Container config directory matches host XDG conventions (.config/opencode for OpenCode)
      • OpenCode config file (~/.config/opencode/opencode.json) is automatically prepared via .sbox/ directory:
        • If no config exists, a default one is created with full permissions
        • Existing config is loaded and permissions are automatically set to {"*": "allow"} for sandbox/container environment
        • All other user config fields (like model, preferences, etc.) are preserved
        • Ensures OpenCode runs with full permissions in the isolated environment
      • OpenCode authentication file (~/.local/share/opencode/auth.json) is automatically copied if present:
        • Shares local authentication credentials with the sandbox/container
        • Enables seamless OpenCode usage without re-authentication
        • Copied to /home/agent/.local/share/opencode/auth.json in the container
      • CLAUDE.md/AGENTS.md concatenation works for both agents:
        • Same walking and concatenation logic for all agents
        • Claude: Final file placed at ~/.claude/CLAUDE.md
        • OpenCode: Final file placed at ~/.config/opencode/AGENTS.md
        • Discovers and merges all CLAUDE.md and AGENTS.md files from parent directories
        • Includes backend-specific context (sandbox vs container)
        • Symlink deduplication: If CLAUDE.md is a symlink to AGENTS.md (or vice versa), only includes the file once
        • Renamed functions for clarity: setupCLAUDEMDsetupRules, prepareCLAUDEMDprepareRules

Fixed

  • OpenCode config file preparation now correctly preserves all user fields (like model, preferences, etc.) while only adding/overriding the permission field for sandbox safety

v1.3.3

03 Mar 21:29

Choose a tag to compare

Changed

  • sbox run --recreate now automatically pulls the latest base image to ensure you get the newest Claude Code version

Fixed

  • sbox run --recreate now properly removes existing containers in container backend (previously only worked for sandbox backend)

v1.3.2

26 Feb 18:35

Choose a tag to compare

Added

  • cpp profile for C/C++ development (Boost, libc++, libstdc++, autoconf, automake, libtool, ninja-build, libzstd-dev, zlib1g-dev)

Changed

  • Sensitive environment variables (KEY, TOKEN, SECRET, PASSWORD, etc.) are now masked in sbox info and sbox env list output

Fixed

  • Fix Docker image tag format to include v prefix for semantic versions (e.g., v1.3.1 instead of 1.3.1) to match published image tags