Skip to main content
A devbox is not a separate product surface. It is a plain sandbox you keep around: durable storage so your working tree survives a stop, managed SSH for a real shell, and the ordinary lifecycle verbs to park it when you are done for the day. This guide walks that setup with the verbs that work today, then says plainly what a sandbox still does not do for a development loop, so you can decide whether it fits yours.
The shell in this guide needs the sandbox SSH endpoint, which an operator enables per deployment and which is off by default. On the hosted service it is currently enabled only in pre-release environments. Where it is off, a connect is refused with unsupported_capability. The authoritative status list is what’s live today.

Create it once

--storage-class durable is the part that makes this a devbox rather than a scratch sandbox. It mounts /workspace as storage with its own lifetime, so files written there survive a stop and survive losing the sandbox’s node. Everything outside /workspace comes back from the image. Leave --ttl off. An omitted TTL takes the deployment’s default lifetime, which on the hosted service is none, so the sandbox lives until you delete it. sandbox get shows the result in its expires field. With no --image, the sandbox starts from the platform default image: a Debian base carrying Python, Node, git, gcc, make, and an SSH client, so you can clone a repository and build it without installing anything first. Check what does not work yet before you invest in a long setup script.

Work in it

That is an interactive shell over stock OpenSSH, with no key for you to manage and no host-key prompt. Everything after -- is passed to ssh, so the usual flags work:
For scripted, non-interactive work, exec avoids a session entirely and returns the command’s real exit code with stdout and stderr kept separate:
ssh and exec land in the same container and see the same filesystem, so a file you write over SSH is visible to the next exec.

Get code and files in and out

Your /workspace starts empty. hiloop sandbox cp fills it, in either direction, with -r for directories. Write the sandbox side as <sandbox>:/absolute/path:
Each copy prints what landed:
cp needs nothing installed inside the sandbox: the sandbox serves the SFTP subsystem itself, so a copy works against any image, and it keeps working after a stop, when anything you installed yourself is gone. A transfer interrupted by a transient network failure is retried automatically. The sandbox path must be absolute, and exactly one of the two paths must name a sandbox. Copying a directory without -r is refused rather than silently skipped. Plain scp and sftp work too, for the same reason, if you would rather drive them yourself. Both take their remote-shell program as a path and do not split it into words, so give them a one-line wrapper on your PATHexec hiloop sandbox ssh "$@" — and pass that to -S. For a repository, clone rather than copy. A copy pays a network round trip per file, so a large working tree is slow to push file by file — a ten-thousand-file checkout takes tens of minutes. The default image carries git, so cloning into /workspace from inside the sandbox, over the sandbox’s own outbound network, is much faster. Use cp -r for directories you cannot clone: build outputs, datasets, config, results. rsync is different. It runs itself on both ends, so it needs the rsync binary in the sandbox, and the default image does not carry one. Given that, point its -e straight at the CLI:
Anything you install with a package manager lands outside /workspace and is therefore lost on the next stop, rsync included. Keep the setup in a script under /workspace and re-run it after a start, or stay on sandbox cp, which needs no installation. For large, versioned data shared across many sandboxes, the intended home is a volume (hiloop volume create / push) rather than a per-sandbox copy. Volumes can be created, pushed, and read back today, but mounting one into a sandbox is still refused, so a volume is not yet a way to get data into a devbox.

Park it and pick it up

Stopping releases the compute. /workspace reattaches on the way back with your files intact.
Delete is permanent and releases the durable /workspace with it. To keep a devbox’s workspace beyond the sandbox, or to branch it, snapshot it and create from the snapshot:
Snapshots capture disk, not processes; see snapshots and branching.

What does not work yet

These are current limitations, not settings you can change. They are the difference between this setup and a long-lived virtual machine. A stop loses your processes, not just your foreground shell. Only files under /workspace survive. A running build, a dev server, a tmux session, and anything you installed into the system directories are all gone on the next start, and your shell begins again from the image. You get your files back, not your session. Plan on a start-up script rather than expecting to resume where you left off. A start can report running before the sandbox can actually serve. sandbox start returns quickly, and sandbox get reads running, but the first exec or ssh afterwards can be refused for up to about two minutes while the previous instance finishes releasing its storage. If a connect fails right after a start, wait and retry rather than treating the sandbox as broken. The default image has no rsync. It carries Python, Node, git, gcc, make, and an SSH client, so you can clone a repository and build it without installing anything. rsync is the exception: it has to run on both ends of the connection, and the image does not include it. Use hiloop sandbox cp, or plain scp/sftp, all of which work against any image — or install rsync in the sandbox and remember that a stop will lose it. An image has to keep a process running. A sandbox lives exactly as long as its first process, so an image whose entrypoint exits immediately, which is true of most base images, fails to start. Give it something long-running after --:
Volume mounts are refused. The volume verbs publish and version data, but naming one with --volume at create is refused with unsupported_capability, so bulk data has to come in with sandbox cp for now, per sandbox rather than shared between them.