Skip to content

Mount the sandbox scripts directory and fail loudly when sbx exec can't start a command - #12

Merged
mxriverlynn merged 5 commits into
mainfrom
fix/sandbox-scripts-mount
Sep 22, 2026
Merged

mxriverlynn merged 5 commits into
mainfrom
fix/sandbox-scripts-mount

Conversation

@mxriverlynn

Copy link
Copy Markdown
Collaborator

Problem

Running an eval from a repo other than skillwalker (for example han) failed on every test:

OCI runtime exec failed: executable file `/Users/.../skillwalker/build/sandbox-run.sh` not found: No such file or directory
[DONE] "Prompt: /architectural-analysis of go-project runner module"
  - Duration (ms): 0
  - Input Tokens:  0

There were two bugs:

  1. The sandbox couldn't see skillwalker's scripts. sbx exec runs sandbox-run.sh and sandbox-extract.sh by their host path, but the sandbox only sees host paths under a mounted workspace. sandbox create mounted only --repo-root, which is the target repo. So this failed whenever the target repo wasn't the skillwalker repo.
  2. The failure was reported as a pass. When sbx exec can't start the command, it prints OCI runtime exec failed and still exits 0. The test runner's exit-code check never fired, so the test showed [DONE] with zero tokens.

Changes

  • createSandbox and updateSandbox take optional extraWorkspaces, mounted read-only after the repo root (sbx run ... claude <repoRoot> <dir>:ro). A workspace already inside the repo root is skipped.
  • sandbox create and sandbox update pass the scripts directory: build/ for the compiled binary, packages/claude-integration/ from source. It's exported as sandboxScriptsDir from a new claude-integration/src/sandbox-scripts.ts, which run-claude.ts and extract-output-files.ts now also use.
  • execInSandbox throws SandboxError when any stdout or stderr line starts with OCI runtime exec failed. The error includes a hint to run skillwalker sandbox update.
  • cli/index.ts prints SandboxError as Error: <message> and exits 1, instead of printing a stack trace.
  • Updated docs/sandbox-integration.md and docs/sandbox-integration-package.md.

After merging

Existing sandboxes still have the old single mount. Run skillwalker sandbox update from the target repo once to recreate the sandbox with both mounts.

Testing

  • make test: all 1022 tests pass, including new tests for the mount args, skipping nested workspaces, and detecting the exec failure. Detection matches only at the start of a line, so Claude output that merely mentions the message doesn't trigger it.
  • Typecheck and make build pass. Biome is clean on the changed files.
  • Confirmed by hand that sbx exec exits 0 on a missing executable. Also confirmed that the new execInSandbox throws the expected SandboxError against a sandbox that's missing the mount.
  • Not yet verified: a full eval run after sandbox update. That step needs the interactive OAuth login.

mxriverlynn and others added 5 commits September 22, 2026 12:32
…t repo

sbx exec runs sandbox-run.sh and sandbox-extract.sh by their host path, but
the sandbox only sees host paths under a mounted workspace. sandbox create
mounted only the target repo, so every test run failed whenever the target
repo was not the skillwalker repo.

sandbox create and sandbox update now also mount the scripts directory
read-only, skipping it when it is already inside the target repo.

Co-Authored-By: Claude <noreply@anthropic.com>
sbx exec prints "OCI runtime exec failed" and still exits 0 when the command
cannot be started, so a test run reported [DONE] with zero tokens instead of
failing. execInSandbox now throws SandboxError when it sees that message,
and the CLI prints SandboxError as a clean error instead of a stack trace.

Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Claude <noreply@anthropic.com>
With no fail handler, yargs catches a rejected command handler itself: it
prints help and the raw error (which Bun renders with a source snippet and
stack trace), then exits before the catch in index.ts runs. The clean
"Error: ..." output for SkillwalkerError and SandboxError never appeared.

A .fail() handler now rethrows handler errors to that catch. Parse errors
still print help and the message.

Co-Authored-By: Claude <noreply@anthropic.com>
… run

A sandbox created before the scripts mount was added keeps its original
workspaces, so it passed "Checking sandbox..." and failed only at the first
sbx exec. ensureSandboxExists now reads `sbx ls --json` and throws a
SandboxError naming any required path the sandbox does not mount, with a
hint to run `skillwalker sandbox update`. runEvals and the SCIL and ACIL
loops require sandboxScriptsDir.

Co-Authored-By: Claude <noreply@anthropic.com>
@mxriverlynn
mxriverlynn marked this pull request as ready for review September 22, 2026 19:15
@mxriverlynn
mxriverlynn merged commit 0492c4d into main Sep 22, 2026
7 checks passed
@mxriverlynn
mxriverlynn deleted the fix/sandbox-scripts-mount branch September 22, 2026 19:15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant