Skip to content

CLI Reference

The sandbox CLI is your primary authoring tool. Run any command from inside a sandbox directory — the CLI searches upward from your current directory to find sandbox.yaml.

Version requirements

This reference covers Sandbox CLI v1.27.0. Check the installed version before using the newer workflows:

sandbox version
Available since Author-facing changes
v1.25 Borrowed sandbox attach terminals, including --ux; corrected Bashp quote tracking inside nested command and parameter substitutions.
v1.26 Read-only, AST-based Bashp MCP tools: bashp_find, bashp_explain, and bashp_resolve, with paginated results and retrievable expansions.
v1.27 Background live reload for every VM selected by sandbox start, including scripts, assets, and local library dependencies.

Devbox and Nix installations use the repository's pinned CLI. See updating the CLI if that pin predates the feature you need.

Command overview

Command What it does
sandbox init Scaffold a new sandbox directory
sandbox build Build VM disk images
sandbox shell Start VMs and open an interactive shell
sandbox attach Open a separate terminal in an already-running VM
sandbox setup Run setup.sh, then open a shell
sandbox answer Run setup.sh + answer.sh, then open a shell
sandbox score Run setup.sh + answer.sh + score.sh, then open a shell
sandbox test Run the full lifecycle non-interactively and report results
sandbox exec Run a single command in a running VM
sandbox instructions Preview the candidate instructions with live reload
sandbox validate Run static checks without building
sandbox start Start VMs and independent background source watchers
sandbox stop Stop selected watchers, then stop and delete their VMs
sandbox mcp Expose Bashp discovery, explanation, and resolution to agents
sandbox version Print the installed CLI version

sandbox init

Scaffold a new sandbox directory.

sandbox init [itemname]

Without itemname, the interactive wizard runs. With itemname, a single-VM scaffold is created immediately.

Flag Default Description
--type auto-detected exam or lab. Detected from the git remote URL if omitted.
sandbox init                        # interactive wizard
sandbox init foobar                 # single-VM fast path
sandbox init --type exam foobar

sandbox build

Build VM disk images from build.sh and the base image.

sandbox build [PATH]
Flag Default Description
--vms all Comma-separated list of VM names to build.
--no-refresh-images false Skip the registry check and use the local cache.
-q, --quiet auto Suppress Lima and image-helper output; local builds are quiet by default.
sandbox build
sandbox build --vms cp,worker
sandbox build --no-refresh-images

Base images are cached locally after the first pull. sandbox shell runs sandbox build automatically if images are not yet built.


sandbox shell

Start VMs and open an interactive shell. Builds images first if needed. Plain sandbox shell does not execute setup.sh; use sandbox setup when you need the configured starting state.

sandbox shell [PATH]
Flag Default Description
--target first VM VM to open the shell in.
--vms all VMs to start.
--ux false SSH as the configured user to replicate the candidate experience.
sandbox shell
sandbox shell --target worker
sandbox shell --vms cp,worker --target cp
sandbox shell --ux

This shell owns the VM session. Exiting it deletes all VMs it started and disconnects any attached terminals. Its live-reload watcher follows only the target VM while the owning shell remains open.

For independently attached terminals and automatic reload on every VM, use background start and stop.


sandbox setup / answer / score / test

These commands create an owned VM session and run lifecycle scripts in sequence. setup, answer, and score then open an interactive shell; test prints results and exits.

Command Runs Then
sandbox setup setup.sh Opens a shell
sandbox answer setup.sh + answer.sh Opens a shell
sandbox score setup.sh + answer.sh + score.sh Opens a shell
sandbox test setup.sh → score → answer.sh → score Prints results, no shell

sandbox test is the acceptance test. It passes when scoring returns zero checks before the answer is applied, and full marks after.

All accept --target and --vms. Lifecycle scripts run on every selected VM; --target chooses the interactive shell. Interactive modes watch only the target VM until their owning shell exits. sandbox test has no live-reload watcher.

Stop any background VMs for this sandbox before starting an owned session. Exiting an owning shell or completing test deletes its VMs; exiting an attached terminal does not.

sandbox setup                       # verify the environment starts correctly
sandbox answer                      # verify your reference solution works
sandbox score                       # verify scoring sees the correct result
sandbox test                        # run the full lifecycle and report

sandbox attach

Available since v1.25. Open a borrowed terminal in an existing VM without building images, starting or stopping VMs, running lifecycle scripts, or creating a watcher.

sandbox attach [PATH] --target VM
Flag Default Description
--target required Exact VM name from sandbox.yaml.
--ux false Connect as the configured VM user and exercise the platform SSH experience.
sandbox attach --target cp
sandbox attach --target worker --ux

You can attach to VMs owned by either sandbox shell or sandbox start. Closing an attachment closes only that connection. An owning shell must remain open; background VMs remain available until sandbox stop.

--ux temporarily installs a unique SSH key for the configured user and normally removes it on exit. Cleanup is best-effort after abrupt process or transport failure.


sandbox exec

Run a single command in a running VM. The VM must be started first. This command does not run lifecycle preparation or create a watcher; an existing background watcher continues independently.

sandbox exec [PATH] -- COMMAND [ARGS...]
Flag Default Description
--target first VM VM to run the command in.
sandbox exec -- whoami
sandbox exec -- cat /etc/os-release
sandbox exec --target worker -- systemctl status kubelet

sandbox instructions

Start a local preview server for the candidate instructions with live reload.

sandbox instructions [PATH]
Flag Default Description
-o, --open false Open the browser automatically.
-p, --port random Port to serve on.
sandbox instructions
sandbox instructions -o
sandbox instructions -p 3000 -o

Uses the production instructions image, so the preview matches exactly what candidates see. Requires Docker.


sandbox validate

Validate the sandbox without building VM images. Base-image manifest checks can contact the registry, so a registry error is not necessarily a local source error.

sandbox validate [PATH]

Checks:

  • sandbox.yaml schema
  • Each tool's targetHost references a known VM
  • Required scripts exist in each VM's source directory, have executable permissions, and have shebangs
  • score.sh ends with scoring::report
  • Instructions sourcePath resolves to a Markdown file or a directory with index.md
  • Each base image has a reachable registry manifest
  • dist/ contains no git-tracked files
sandbox validate
sandbox validate ./items/foobar

sandbox start and stop

Since v1.27, start launches one independent source watcher for every selected VM and returns after the VMs and watchers are ready. Build the images first; start does not build missing disks.

sandbox build --vms cp,worker
sandbox start --vms cp,worker

Both commands accept an optional sandbox path. Omitting --vms selects all VMs declared in the blueprint.

Open separate terminals in the same sandbox directory:

Control-plane terminal
sandbox attach --target cp
Worker terminal
sandbox attach --target worker

Edit source files in your editor while either terminal is open or after closing both. The watchers are independent of attachments and of the completed start command.

What reloads

For each started VM, the CLI recompiles Bashp scripts and copies assets into dist/<vm>/, mounted in the guest at /sandbox.

Host source What changes in the running VM
<vm_dir>/scripts/*.sh Compiled Bash at /sandbox/scripts/<name>.sh.
<vm_dir>/assets/ Files under /sandbox/assets/, including additions, renames, and deletions.
<vm_dir>/libs/ or <vm_dir>/scripts/libs/ The compiled scripts that inline those helpers, even when the lifecycle source itself is unchanged.
The nearest existing ancestor libs/, or the sandbox's bashp-packages/libs/ Compiled scripts in every started VM watching that shared library root.
Sandbox metadata.yaml Regenerated script settings from the updated metadata.

Here, <vm_dir> is the VM's source directory, normally its named directory such as cp/; a configured sourceDir override is respected. A script can call a local helper that itself calls a vendored or bundled helper: the dependency chain is inlined into the generated Bash. See the library reload example.

Reload updates files, not VM state

Neither start nor a reload executes setup.sh, answer.sh, or score.sh. Functions already loaded into a shell remain unchanged until you source or execute the regenerated script again. Asset changes update /sandbox/assets/, not copies previously installed elsewhere in the image.

Run a regenerated script explicitly when its effects are needed:

sandbox exec --target cp -- bash /sandbox/scripts/setup.sh

Changes to sandbox.yaml, the base image, or files installed by build.sh are not live configuration or image updates. To apply image-time changes, stop the affected VMs, rebuild them, and start them again.

Errors and shutdown

start prints a watcher log path for each VM. Check that log when a source edit does not appear. Compilation failures retain the previous compiled files, and a later valid edit is retried automatically. Successful publication replaces individual files atomically, then removes stale entries; it is not an atomic snapshot of the entire directory tree.

Starting an already-running selected VM fails before changing its mounted files. If startup partially fails, successful VMs retain their watchers; watcher-startup failure triggers cleanup of only that newly started VM, with any cleanup failure reported.

Stop one VM and its watcher without interrupting the others:

sandbox stop --vms worker

Stop all remaining VMs and their watchers:

sandbox stop

stop waits for selected watchers to finish any in-flight reload before deleting their VMs. A watcher also exits when its VM stops or disappears. Use sandbox exec for commands or sandbox attach for terminals; neither takes ownership of these background watchers.


sandbox cache

Manage locally cached base images.

sandbox cache ls       # list cached images and sizes
sandbox cache df       # show total disk usage
sandbox cache prune    # remove orphaned cache objects
sandbox cache rm <image-ref>

Cache location:

  • macOS: ~/Library/Caches/sandbox-cli/images/
  • Linux: ~/.cache/sandbox-cli/images/

sandbox mcp

The v1.26 MCP interface gives coding agents read-only Bashp discovery, source-grounded explanations, and resolution of saved scripts or unsaved buffers. The server reads and parses files; it does not execute shell commands, run analyzers, or make network requests.

Start it with the content repository as its working directory. Most clients launch this stdio server themselves:

sandbox mcp

For clients using .mcp.json, the server entry is:

{
  "mcpServers": {
    "bashp": {
      "command": "sandbox",
      "args": ["mcp"]
    }
  }
}

Find, explain, resolve

These are MCP tool calls, not sandbox subcommands:

Tool Purpose
bashp_find Search by name or intent; omit query to browse namespaces, or supply only namespace to browse its helpers.
bashp_explain Explain exact helper names in a batch, with selected source, dependencies, potential effects, and limitations.
bashp_resolve Check a saved file or an inline script; mode: "expand" retrieves the generated Bash in chunks.

For a saved lifecycle script, use the same file context throughout:

  1. Discover a helper:
bashp_find arguments
{
  "query": "install apt packages",
  "file": "items/hello-image/host1/scripts/build.sh"
}
  1. Inspect the selected implementation before using it:
bashp_explain arguments
{
  "names": ["install::apt_packages"],
  "level": "full",
  "file": "items/hello-image/host1/scripts/build.sh"
}
  1. Save the script and resolve its dependencies:
bashp_resolve arguments
{
  "file": "items/hello-image/host1/scripts/build.sh"
}

For an unsaved buffer, provide script instead of file; context_path selects the item, VM, and library context:

bashp_resolve arguments for an unsaved buffer
{
  "script": "#!/usr/bin/env bashp\ninstall::apt_packages curl jq\n",
  "context_path": "items/hello-image/host1/scripts/build.sh",
  "mode": "check"
}

The server identifies the selected source and any shadowed helper implementations. Local overrides can therefore have a different contract from a bundled helper with the same name. An include_only artifact is not a callable function.

Optional MCP resources are bashp://guide, bashp://namespaces, and bashp://namespace/{ns}. Clients without resource browsing can use bashp_find instead.

Scope and result handling

The startup workspace and explicit --include-dir roots define filesystem access:

sandbox mcp --include-dir ./libs

Client roots can narrow that access. A file or context_path argument selects context but cannot grant access to another checkout.

Resolution returns scope: "bashp_resolution" and a status:

  • pass: applicable resolution checks completed without an established error or blocking uncertainty.
  • fail: an established error exists, such as a missing static helper or include.
  • incomplete: dynamic references, unreadable dependencies, or the dependency-closure limit prevent a complete answer.

Inspect diagnostics, evaluated, and not_evaluated along with the status. A resolution pass does not replace Skills lint, ShellCheck, shfmt, content validation, sandbox validate, or sandbox build && sandbox test; it cannot prove guest files or runtime behavior.

Results have structured JSON and an equivalent JSON text fallback. When next is present, call its named tool with exactly its arguments; continuation calls contain only cursor. Follow continuations until next is null. After stale_cursor, discard the partial result and restart the original request against the changed sources.

An expansion page is not executable by itself. Reassemble chunks in byte_offset order and verify the complete byte count and SHA-256 before treating the result as generated Bash. Expansion refuses environment-sourced SANDBOX_SETTING_* values rather than disclosing them.

Upgrading older MCP clients

v1.26 removed the old tools and resource below without compatibility aliases. Update client configuration, tool allowlists, and authoring instructions that still name them:

Removed surface Replacement
bashp_search, bashp_list_namespaces, bashp_list_functions bashp_find
bashp_get_function, bashp_get_dependencies bashp_explain
bashp_validate_script, bashp_preprocess bashp_resolve
bashp://catalog Namespace resources or bashp_find

sandbox update

Update the CLI to the latest release.

sandbox update
sandbox update --force    # reinstall even if already on latest

For Devbox/Nix-managed installations, including managed Codespaces, use the repository's toolchain upgrade process. sandbox update does not replace the managed CLI. Run sandbox version afterward to confirm the version actually selected by your environment.