# sbx CLI Cheatsheet: Sandboxer Commands by Task

> Sign in once, then most work takes seven commands. sbx new creates a sandbox, sbx exec or sbx ssh runs commands in it, sbx scp moves files, sbx host gives a port an HTTPS URL, sbx stop pauses it with its memory, and sbx resume continues. The tables below map each task to its command.

Source: https://sandboxer.com/guides/sbx-cli-cheatsheet. Updated 2026-10-27.

**Short answer:** Sign in once, then most work takes seven commands. sbx new creates a sandbox, sbx exec or sbx ssh runs commands in it, sbx scp moves files, sbx host gives a port an HTTPS URL, sbx stop pauses it with its memory, and sbx resume continues. The tables below map each task to its command.

This page is organized by task. For every flag and its default, see the [CLI reference](/docs/cli). `$id` below is a sandbox id such as `sb_6fx00ghdhk`; you can also write `current` for the last sandbox you created.

## The core loop, as we ran it

One `small` sandbox on prod, start to finish. Output is real, trimmed with `…`.

```bash
$ sbx new --type small --name aeo-cheatsheet-1
✓ sb_6fx00ghdhk is ready
URL:        https://green-fuzzy-pond.box.sandboxer.com
Type:       small (2 vCPU, 4 GB)
Auto-stop:  2026-10-27 10:12 (in 59m57s)

$ sbx exec sb_6fx00ghdhk 'uname -r; nproc'
6.18.56-sandboxer
2

$ sbx scp ./local.txt sb_6fx00ghdhk:/home/user/
local.txt                                     100%   18     0.1KB/s   00:00

$ sbx exec sb_6fx00ghdhk --detach 'cd site && python3 -m http.server 8000'
{"ok":true,"type":"command.started",…,"processId":656,…}

$ sbx host sb_6fx00ghdhk 8000
https://green-fuzzy-pond-8000.box.sandboxer.com?_token=…
Private URL: keep the _token secret. `sbx host sb_6fx00ghdhk 8000 --public` makes it ungated.

$ sbx stop sb_6fx00ghdhk --wait
✓ sb_6fx00ghdhk is archived

$ sbx resume sb_6fx00ghdhk
✓ sb_6fx00ghdhk is ready

$ sbx exec sb_6fx00ghdhk 'pgrep -af http.server'
656 python3 -m http.server 8000

$ sbx delete sb_6fx00ghdhk --yes
✓ Deleted sb_6fx00ghdhk
```

`sbx new` took 3.2 seconds and `sbx resume` 3.1 seconds. The web server kept PID 656 across the stop, because resume restored memory. Without the token, the hosted URL answered `401`; with it, `302`.

## Create, find and tidy up

| I want to… | Command |
| - | - |
| Sign in on this computer | `sbx login` (browser) or `sbx login --key-stdin <<< "$SANDBOXER_API_KEY"` |
| Check who I'm signed in as | `sbx status` |
| Create a sandbox | `sbx new` (size `default`) or `sbx new --type small` |
| Give it a name | `sbx new --name api-test` |
| Create it with no secrets from my account | `sbx new --no-env` |
| Pass variables | `sbx new -e KEY=value -e OTHER=value` |
| Run a setup script once it's ready | `sbx new --setup-file ./setup.sh` |
| Start from a saved snapshot | `sbx new --from web-stack` |
| List running sandboxes | `sbx list` (alias `sbx ls`) |
| List stopped ones too | `sbx list --filter sr` or `sbx list --all` |
| See one sandbox's URL, size and auto-stop time | `sbx info $id` |
| Rename it or change its subdomain | `sbx rename $id --name "api server"` or `--subdomain blue-owl-api` |
| Delete it for good | `sbx delete $id --yes` |

## Run commands

| I want to… | Command |
| - | - |
| Run one command and get its exit code | `sbx exec $id 'npm test'` |
| Run in a folder, with a longer timeout | `sbx exec $id --cwd app --timeout 120 -- npm run build` |
| See output as it's written | `sbx exec $id --stream 'npm run build'` |
| Open a shell | `sbx ssh $id` |
| Run a local script remotely | `sbx ssh $id -- bash -s < ./setup.sh` |
| Get an interactive TTY over the API | `sbx exec -it $id` |
| See what's running, busiest first | `sbx ps $id` |
| List past commands | `sbx history $id --limit 20` |
| Print an old command's output | `sbx history $id cmd_… [--stderr]` |
| Find a past command by text | `sbx history $id --grep pytest` |

`--cwd` is relative to `/home/user`; an absolute path such as `/tmp` also worked. `sbx exec` returns the remote exit code: `exit 3` in the sandbox gave exit 3 locally.

## Long jobs

| I want to… | Command |
| - | - |
| Start a job and get my prompt back | `sbx exec $id --detach './train.sh'` (prints `processId`) |
| Check it later | `sbx exec $id --status <pid>` |
| Follow it until it ends | `sbx exec $id --attach <pid>` (exits with the job's code) |
| Stop it and everything it started | `sbx exec $id --kill <pid>` (in sandboxes created before 14:28 UTC on October 27, 2026, a child that starts its own session can keep running; use `pkill -f <name>` inside those) |
| Push auto-stop out | `sbx extend $id --hours 12` or `sbx extend $id --no-auto-stop` |
| Pause after idle minutes | `sbx idle $id 30` (`0` never pauses) |

On prod, `--attach` on a job that ended with `exit 4` exited 4, and `--kill` on a `sleep 600` showed it in `sbx history` as `killed 143`. The [long job guide](/guides/run-a-long-job-in-a-cloud-sandbox) covers this in depth.

## Files, ports and editors

| I want to… | Command |
| - | - |
| Upload a file | `sbx scp ./file $id:/home/user/` |
| Upload a folder | `sbx scp -r ./dir $id:/home/user/` |
| Download a file | `sbx scp $id:/home/user/out.zip .` |
| Get a private HTTPS URL for a port | `sbx host $id 3000` |
| Make it public | `sbx host $id 3000 --public` |
| Host an app bound to 127.0.0.1 | `sbx host $id 5173 --localhost` |
| List or take down hosted ports | `sbx host list $id` / `sbx host hide $id 3000` |
| Reach a sandbox port on my laptop | `sbx forward $id --remote 8000 --local 18000` |
| Expose a laptop port inside the sandbox | `sbx forward $id --reverse --local 11434` |
| Use plain ssh, rsync or VS Code Remote-SSH | `sbx ssh-config --install`, then `ssh $id.sbx` |
| Open the Linux desktop | `sbx desktop $id` |

With `sbx forward $id --remote 8000 --local 18000` running, `curl http://127.0.0.1:18000/` on the laptop returned the sandbox's page. See [moving files](/guides/move-files-in-and-out-of-a-sandbox) and [HTTPS URLs for ports](/guides/give-a-sandbox-port-an-https-url) for the details.

## Pause, resume and copy

| I want to… | Command |
| - | - |
| Stop billing, keep memory and disk | `sbx stop $id --wait` |
| Continue where it stopped | `sbx resume $id` |
| Resume on a bigger size (boots from disk) | `sbx resume $id --type large` |
| Refuse to boot from disk | `sbx resume $id --require-memory` |
| Copy its disk into a new sandbox | `sbx fork $id --wait` |
| Bring back a sandbox that stopped answering | `sbx recover $id` |
| Save it under a name | `sbx snapshot $id web-stack` |
| List snapshots | `sbx snapshots` or `sbx snapshots $id` |
| See files in a snapshot / download them | `sbx snapshot tree <snapshotId>` / `sbx snapshot pull <snapshotId> -o ./restore` |
| See what one sandbox has cost | `sbx usage $id` |

Use `--wait` on stop when a script resumes right after. A fork gets the files but no processes: our fork had `~/local.txt` and no web server. Moving to a smaller size isn't supported yet; create a new sandbox and copy. Details are in [pause and resume](/guides/pause-and-resume-a-sandbox-with-memory).

## Agents and scripting

| I want to… | Command |
| - | - |
| Prompt the coding agent in a sandbox | `sbx prompt $id "Fix the failing tests"` |
| Pick the provider and model | `sbx prompt $id --provider codex --model <model> "…"` |
| Move my local Claude Code or Codex session into a sandbox | `sbx handoff` (and `sbx handoff --back`) |
| Give an MCP client sandboxes | `claude mcp add sandboxer -- sbx mcp` |
| Get JSON for a script | add `--json` (automatic when output is piped) |
| Bill one command to an organization | `sbx --org acme new` |
| Check starts and hours left | `sbx limits` |
| Turn on tab completion | `eval "$(sbx completion bash)"` |
| Update the CLI | `sbx self-update` |

## Exit codes for scripts

| Code | Meaning |
| - | - |
| `0` | Success |
| `1` | Error |
| `2` | Usage error (`sbx new --type tiny` gave 2) |
| `3` | Not signed in or unauthorized |
| `4` | Not found (`sbx exec sb_doesnotexist true` gave 4) |
| `5` | Timed out |

`sbx exec` and `sbx ssh` exit with the remote command's code instead. In JSON mode an error is one `{"event":"error",…}` line on stderr, for example `{"event":"error","error":"Sandbox not found","code":"not_found","status":404,…}`.

## What we ran

Every command above appears in `sbx <command> --help` for CLI build `14c740d`. On prod we ran `status`, `limits`, `new`, `list`, `info` (including `info current`), `rename`, `exec` (plain, `--cwd`, `--detach`, `--status`, `--attach`, `--kill`), `ssh` with a command, `scp` both ways, `host`, `host list`, `host hide`, `forward`, `ps`, `history`, `extend`, `idle`, `stop --wait`, `resume`, `snapshots`, `fork --wait`, `usage` and `delete --yes`. The `prompt`, `handoff`, `mcp`, `desktop`, `recover`, named snapshot and interactive `-it` rows are checked against `--help` only.

## FAQ

### How do I get the sbx CLI?

Run `curl -fsSL https://sandboxer.com/install | sh` on macOS or Linux, or `irm https://sandboxer.com/install.ps1 | iex` in Windows PowerShell. `sbx self-update` keeps it current.

### Do I have to type the sandbox id every time?

No. `current` means the last sandbox you created, and commands that take an id use it when you leave the id out. In our run, `sbx info current` found the sandbox from an earlier, separate `sbx new`.

### How do I use sbx in CI without a browser?

Pipe the key in with `sbx login --key-stdin`, or set `SANDBOXER_API_KEY` in the job's environment. Output switches to JSON when it isn't a terminal, and `sbx delete` needs `--yes`.

### What's the difference between sbx exec and sbx ssh?

`sbx exec` runs through the API and returns output and the exit code, with `--detach` for long jobs. `sbx ssh` opens a real SSH session over an HTTPS tunnel, which you want for interactive work and piping scripts in.

## Related

- [CLI reference](/docs/cli)
- [How to move files in and out of a cloud sandbox](/guides/move-files-in-and-out-of-a-sandbox)
- [Give a port in a cloud sandbox an HTTPS URL](/guides/give-a-sandbox-port-an-https-url)
- [Pause and resume a cloud sandbox with its memory](/guides/pause-and-resume-a-sandbox-with-memory)
