You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
bug: openshell sandbox upload <local-dir> <remote-dir> flattens contents instead of creating named subdirectory #885
Loaded openshell-cli skill and walked the sandbox upload command path in crates/openshell-cli/.
When <local> is a directory, the CLI walks the directory and uploads each entry into <remote> directly. The local directory's name is dropped from the destination path.
Confirmed by the minimal repro below. Behavior diverges from the standard scp -r and cp -r semantics operators expect from any *nix-style file-transfer tool.
Agent identified the workaround: tar -czf foo.tgz -C parent foo && openshell sandbox upload <name> foo.tgz /tmp/ && ssh ... 'tar -xzf /tmp/foo.tgz -C <remote>/'. The tarball preserves the source-directory prefix deterministically.
Description
openshell sandbox upload <local-dir> <remote-dir> flattens the local directory's contents into the remote destination instead of creating a subdirectory named after the local directory.
In our case this caused a real near-miss: a directory of content was uploaded into a sibling location alongside existing files at the destination. No data was lost (all uploaded files were new and didn't collide), but the recovery path required a full diff against backups to confirm. A future variant of the same operation could silently shadow files at the destination with no warning.
Reproduction Steps
Create a local directory with content:
mkdir -p /tmp/upload-test/sub
echo a > /tmp/upload-test/a.txt
echo b > /tmp/upload-test/sub/b.txt
Match scp -r / cp -r semantics — preserve the source directory's basename as a subdirectory of the destination. Principle-of-least-surprise fix; aligns with every comparable file-transfer tool.
Keep current flatten behavior, add a --preserve-dir flag for the standard semantics, plus a CLI help update calling out the divergence loudly.
I prefer (1). The current behavior is a quiet footgun for any operator with prior file-transfer experience. Cost is one breaking-change note in the release. Happy to convert this to a PR if a maintainer signals direction.
Agent-First Checklist
I pointed my agent at the repo and had it investigate this issue
I loaded relevant skills (openshell-cli)
My agent could not resolve this — the diagnostic above explains the root cause; resolution needs an upstream code change.
This issue appears to have been opened without an agent investigation.
OpenShell is an agent-first project - please point your coding agent at the repo and have it diagnose this before we triage. Your agent can load skills like debug-openshell-cluster, debug-inference, openshell-cli, and generate-sandbox-policy.
Both proposed-direction variants are pushed to the fork as reference branches, ready to convert to PRs once a maintainer signals direction. Each compiles clean and includes unit tests for the directory-prefix logic.
Single-file change to crates/openshell-cli/src/ssh.rs. Always wraps a directory's contents under the source basename. Paths without a meaningful basename (., /) preserve the legacy flat extraction. Tests cover both branches.
Adds preserve_dir_name: bool parameter to sandbox_sync_up (with false for backward compat at non-CLI call sites), wires --preserve-dir into the Upload command, and updates the command help to call out the default-flatten behavior so operators discover the flag without a production incident first.
Variant A is what I'd reach for personally — the breaking change is small (one release-note line) and the current behavior is a quiet footgun. Variant B is the safer option if backward compatibility weighs heavier. Happy to open whichever you prefer as a PR; reply with the variant name and I'll mark it ready for review.
Heads-up for triage: the body has been edited from H2 (## ) to H3 (### ) headers so the agent diagnostic section now matches the regex at .github/workflows/issue-triage.yml:26. The bot's only complaint was header level — the diagnostic content was substantive on first filing. Safe to drop the state:triage-needed label on review.
Activity
github-actions commentedon Apr 19, 2026
This issue appears to have been opened without an agent investigation.
OpenShell is an agent-first project - please point your coding agent at the repo and have it diagnose this before we triage. Your agent can load skills like
debug-openshell-cluster,debug-inference,openshell-cli, andgenerate-sandbox-policy.See CONTRIBUTING.md for the full workflow.
fix(cli): preserve directory basename when uploading to sandbox
feat(cli): add --preserve-dir flag to sandbox upload for scp -r seman…
mjamiv commentedon Apr 19, 2026
Both proposed-direction variants are pushed to the fork as reference branches, ready to convert to PRs once a maintainer signals direction. Each compiles clean and includes unit tests for the directory-prefix logic.
Variant A — match
scp -rsemantics by default (breaking)Branch:
fix/sandbox-upload-preserve-dir-defaultDiff: main...mjamiv:OpenShell:fix/sandbox-upload-preserve-dir-default
Single-file change to
crates/openshell-cli/src/ssh.rs. Always wraps a directory's contents under the source basename. Paths without a meaningful basename (.,/) preserve the legacy flat extraction. Tests cover both branches.Variant B — opt-in
--preserve-dirflag (non-breaking)Branch:
feat/sandbox-upload-preserve-dir-flagDiff: main...mjamiv:OpenShell:feat/sandbox-upload-preserve-dir-flag
Adds
preserve_dir_name: boolparameter tosandbox_sync_up(withfalsefor backward compat at non-CLI call sites), wires--preserve-dirinto theUploadcommand, and updates the command help to call out the default-flatten behavior so operators discover the flag without a production incident first.Variant A is what I'd reach for personally — the breaking change is small (one release-note line) and the current behavior is a quiet footgun. Variant B is the safer option if backward compatibility weighs heavier. Happy to open whichever you prefer as a PR; reply with the variant name and I'll mark it ready for review.
mjamiv commentedon Apr 19, 2026
Heads-up for triage: the body has been edited from H2 (
##) to H3 (###) headers so the agent diagnostic section now matches the regex at.github/workflows/issue-triage.yml:26. The bot's only complaint was header level — the diagnostic content was substantive on first filing. Safe to drop thestate:triage-neededlabel on review.johntmyers commentedon Apr 20, 2026
Thanks @mjamiv - I agree on variant A. Happy to reivew a PR.
fix(cli): preserve directory basename when uploading to sandbox
fix(cli): preserve directory basename when uploading to sandbox (#952)
fix(cli): cp-style sandbox download and workspace-boundary check (#1353)