Repository navigation
sandbox download fails on busybox-based images: ssh probe uses GNU-only 'realpath -e' #4909
Description
User Story
As a user running agents in Alpine/busybox-based images (including the official ghcr.io/anomalyco/opencode:latest example image), I want openshell sandbox download to retrieve my results, so that the documented upload → run → download workflow works on any standard base image.
Problem Statement
openshell sandbox download always fails on images where realpath is busybox:
Error: × failed to resolve sandbox source path '/sandbox/probe.txt'
╰─▶ ssh probe exited with status exit status: 1
Upload and sandbox exec are unaffected; only download breaks.
Impact / Why This Matters
The official OpenCode example image (ghcr.io/anomalyco/opencode:latest, Alpine-based) is affected, so the documented agent workflow (upload a project, run the agent, download results — e.g. the "Run Pi with OpenRouter" tutorial) is broken on that image unless the user knows to install GNU coreutils.
Acceptance Criteria
sandbox downloadworks on busybox-based images, or- the image requirements documentation explicitly states GNU coreutils is required.
Reproduction Steps
OpenShell v0.1.5, docker compute driver:
openshell sandbox create --name repro-alpine --from alpine:3
echo hello > /tmp/probe.txt
openshell sandbox upload repro-alpine /tmp/probe.txt /sandbox/probe.txt # works
openshell sandbox download repro-alpine /sandbox/probe.txt /tmp/out.txt
# Error: failed to resolve sandbox source path '/sandbox/probe.txt'
# ╰─▶ ssh probe exited with status exit status: 1Control: identical steps on an Ubuntu 24.04-based image succeed.
Root-cause analysis:
- The CLI's ssh probe (extracted via
stringsfrom the v0.1.5openshellbinary) runs:pwd -P && realpath -e -- <path> - busybox
realpathhas no-eflag and treats it (and--) as a filename:
/sandbox # realpath -e -- /sandbox/probe.txt
realpath: -e: No such file or directory
realpath: --: No such file or directory
/sandbox/probe.txt
/sandbox # echo $?
1
- GNU coreutils
realpath -eexits 0 for the same path. - Fix verification: adding
apk add coreutilsto the image makesdownloadsucceed with no other changes — the probe is the only blocker.
Suggested UX (if applicable)
Use a POSIX-compatible probe, e.g. test -e <path> && realpath -- <path>, or detect a usage error from realpath -e and fall back. Alternatively, document the GNU coreutils requirement for sandbox images.
Environment
- OpenShell v0.1.5 (Homebrew install, macOS Apple Silicon 26.6.2)
- Docker compute driver; Docker provider: OrbStack 2.2.4 (Docker Engine 29.8.2, API 1.56). Note: OrbStack is not in the support matrix, but this bug is client-side parsing of probe output and depends only on the sandbox image's
realpath, not on the Docker provider. - Images tested:
alpine:3(fails), Ubuntu 24.04-based custom image (works),alpine:3+ coreutils (works),ghcr.io/anomalyco/opencode:latest(fails)
Logs
$ openshell sandbox upload repro-alpine /tmp/probe.txt /sandbox/probe.txt
✓ Upload complete
$ openshell sandbox download repro-alpine /sandbox/probe.txt /tmp/out.txt
Error: × failed to resolve sandbox source path '/sandbox/probe.txt'
╰─▶ ssh probe exited with status exit status: 1
Activity
O96a commentedon Oct 25, 2026
The probe shouldn't canonicalize at all —
realpath -eis doing an existence check and a path resolution, and only the existence check matters for a download.Pass the path through verbatim; canonicalization only earns its keep when you're comparing two paths for equality, which a download probe isn't. If resolution genuinely is needed, busybox ships
readlink -f, and the pure-POSIX fallback iscd "$(dirname "$p")" && pwd -Pplus basename — both work on Alpine and on GNU. Guard withcommand -v realpath >/dev/nullso a missing applet degrades to the fallback instead of failing the probe.Worth grepping the rest of the ssh probe path for other
-e/--canonicalizeusage before shipping the fix, otherwise the next busybox image hits the same wall one step later.addozhang commentedon Oct 25, 2026
Thanks — agreed that the probe shouldn't canonicalize at all; the existence check is the only thing the download decision needs.
Following your suggestion, I grepped the v0.1.5 CLI binary for every command the ssh path runs inside the sandbox, and tested each on Alpine (busybox):
strings)pwd -Pif [ -d <dst> ]; then printf dir; elif [ -e <dst> ]; then printf file; else printf missing; fipwd -P && realpath -e -- <path>tar cf - -C <dir> -- <entry>So there is no second busybox wall behind this one on the download path: with the probe fixed, the remaining
tar cf - -C … -- …invocation works as-is on Alpine.(Upload is unaffected for a different reason: it goes through the
openshell-upload-v1supervisor protocol, which runs no commands inside the sandbox over ssh.)One nuance on the suggested
command -v realpathguard: on Alpine,realpathexists (busybox applet) but rejects-e, treating it as a filename — so presence-detection doesn't discriminate here; the failure mode is flag compatibility, not a missing applet. For reference, verified on the same Alpine sandbox:readlink -f -- <path>→ exit 0 (and GNU supports-ftoo), so it's a drop-in replacement if resolution is ever needed;cd "$(dirname …)" && pwd -P+ basename) also works on busybox.So the minimal robust fix is exactly your
[ -e "$path" ]existence check;readlink -fis the compatible resolver if one is ever required.