Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 8 additions & 3 deletions packages/cli/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -855,7 +855,9 @@ bunny scripts docs

Manage on-demand cloud sandbox environments backed by Bunny Magic Containers. Each sandbox is a fully isolated Ubuntu container with Node.js, Bun, Python, and Claude Code pre-installed. A 10 GB persistent volume is mounted at `/workplace`, your default working directory.

Sandbox credentials (app ID, hostname, SSH endpoint, agent token) are stored in `~/.config/bunnynet.json` so you can reconnect without re-creating.
Claude Code is pre-installed but needs your own Anthropic credentials before it can do anything: pass an API key at create time (prefer `--env-file .env` so the key stays out of your shell history), or run `claude` inside the sandbox and complete the login prompt it prints. Both survive restarts and redeploys: baked env vars live on the container, and the login flow writes to `/workplace/.claude` on the persistent volume.

Sandbox credentials (app ID, SSH endpoint, agent token) are stored in the CLI's local config file (`~/.config/bunnynet.json` by default) so you can reconnect without re-creating.

#### `bunny sandbox create`

Expand All @@ -874,6 +876,9 @@ bunny sandbox create my-sandbox --region NY
# Bake in environment variables (persisted for the sandbox's lifetime)
bunny sandbox create my-sandbox -e NODE_ENV=production -e PORT=8080
bunny sandbox create my-sandbox --env-file .env

# Give Claude Code your Anthropic API key at create time (.env holds ANTHROPIC_API_KEY)
bunny sandbox create my-sandbox --env-file .env
```

| Flag | Alias | Description | Default |
Expand All @@ -884,7 +889,7 @@ bunny sandbox create my-sandbox --env-file .env

Variables set at creation are baked into the container and persist across restarts. Values from `--env` override those loaded from `--env-file`. To change them later, use [`bunny sandbox env`](#bunny-sandbox-env).

Once ready, the output shows the app ID, public HTTPS hostname, and SSH address.
Once ready, the output shows the app ID and SSH address. Public URLs come later via [`bunny sandbox url add`](#bunny-sandbox-url-add).

#### `bunny sandbox list`

Expand All @@ -895,7 +900,7 @@ bunny sandbox list
bunny sandbox ls # alias
```

Columns: Name, App ID, Hostname, SSH.
Columns: Name, App ID, SSH.

#### `bunny sandbox delete`

Expand Down
8 changes: 7 additions & 1 deletion skills/bunny-cli/SKILL.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
name: bunny-cli
description: Manage bunny.net resources from the command line (databases, DNS, Edge Scripts, authentication, and raw API requests). Use when working with bunny.net (pullzones, DNS zones/records, databases, storage, Edge Scripts, Magic Containers), invoking the `bunny` CLI, or making authenticated API calls to api.bunny.net.
description: Manage bunny.net resources from the command line (databases, DNS, Edge Scripts, sandboxes, authentication, and raw API requests). Use when working with bunny.net (pullzones, DNS zones/records, databases, storage, Edge Scripts, Magic Containers, cloud sandboxes), invoking the `bunny` CLI, or making authenticated API calls to api.bunny.net.
---

# bunny.net CLI Skill
Expand Down Expand Up @@ -40,6 +40,11 @@ bunny scripts init
bunny scripts deploy dist/index.js
bunny scripts list

# manage cloud sandboxes (isolated containers with Claude Code inside)
bunny sandbox create my-sandbox -e ANTHROPIC_API_KEY=sk-ant-...
bunny sandbox exec my-sandbox -- bun install
bunny sandbox url add my-sandbox 3000

# manage DNS
bunny dns zones add example.com
bunny dns zones nameservers example.com # is the registrar delegated to bunny yet?
Expand All @@ -56,6 +61,7 @@ Use this to route to the correct reference file:
- **Database management (create, list, show, link, delete, shell, studio, regions, tokens)** -> `references/database.md`
- **DNS (zones, delegation checks, records, presets, BIND import/export, DNSSEC, logging, Scriptable DNS scripts)** -> `references/dns.md`
- **Edge Scripts (init, create, deploy, link, stats, deployments/rollback, env vars, custom domains)** -> `references/scripts.md`
- **Sandboxes (create, exec, ssh, cp, files, public URLs, persistent env vars, Claude Code auth)** -> `references/sandbox.md`
- **Make raw API requests** -> `references/api.md`
- **CLI doesn't have a command for it** -> use `bunny api` as a fallback (see `references/api.md`)

Expand Down
163 changes: 163 additions & 0 deletions skills/bunny-cli/references/sandbox.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,163 @@
# Sandbox Commands

All sandbox commands live under `bunny sandbox`. Each sandbox is a fully isolated Ubuntu container (Bunny Magic Containers) with Node.js, Bun, Python, and Claude Code pre-installed. A 10 GB persistent volume is mounted at `/workplace`, the default working directory; relative remote paths resolve against it.

Sandbox credentials (app ID, SSH endpoint, agent token) are stored in the CLI's local config (same candidate paths as in SKILL.md), so commands reference sandboxes by name.

Claude Code is pre-installed but needs the user's own Anthropic credentials: bake an API key in at create time (prefer `--env-file .env` so the key stays out of shell history), set it later with `bunny sandbox env set`, or run `claude` inside the sandbox and complete the login prompt. Both paths survive restarts and redeploys: baked env vars live on the container, and interactive login writes to `/workplace/.claude` (the image pins `CLAUDE_CONFIG_DIR` there) on the persistent volume.

## Typical workflows

```bash
Comment thread
greptile-apps[bot] marked this conversation as resolved.
# Create, run a command, expose a dev server, tear down
bunny sandbox create my-sandbox --env-file .env # .env holds ANTHROPIC_API_KEY for Claude Code
bunny sandbox exec my-sandbox -- bun install
bunny sandbox url add my-sandbox 3000 # public HTTPS URL for port 3000
bunny sandbox delete my-sandbox --force

# Move files in and out
bunny sandbox cp ./app.js my-sandbox:app.js # relative paths resolve against /workplace
bunny sandbox cp my-sandbox:out.log ./out.log

# Interactive work
bunny sandbox ssh my-sandbox
```

---

## `bunny sandbox create`

Create and start a new sandbox. Waits for the container's SSH port to become reachable. Prompts for a name when omitted (in `--output json` mode the positional is required).

```bash
bunny sandbox create # interactive: prompts for a name
bunny sandbox create my-sandbox
bunny sandbox create my-sandbox --region NY
bunny sandbox create my-sandbox -e NODE_ENV=production --env-file .env
bunny sandbox create my-sandbox --env-file .env # bake in ANTHROPIC_API_KEY for Claude Code
```

| Flag | Alias | Description | Default |
| ------------ | ----- | ------------------------------------------------ | ------- |
| `--region` | | Region ID to deploy in (e.g. `AMS`, `NY`, `LA`) | `AMS` |
| `--env` | `-e` | Environment variable as `KEY=VALUE` (repeatable) | |
| `--env-file` | | Load environment variables from a dotenv file | |

Variables set at creation are baked into the container and persist across restarts; `--env` overrides `--env-file`. Output shows the app ID and SSH address; public URLs come later via `bunny sandbox url add`.

Comment thread
greptile-apps[bot] marked this conversation as resolved.
---

## `bunny sandbox list` / `delete`

```bash
bunny sandbox list # sandboxes in local config (alias: ls)
bunny sandbox delete my-sandbox # destroys the underlying Magic Containers app
bunny sandbox rm my-sandbox -f # alias; --force skips confirmation
```

---

## `bunny sandbox exec`

Run a shell command inside a sandbox over SSH. Defaults to `/workplace`. Exit code is propagated; use `--` before the command so its flags are not consumed by the CLI.

```bash
bunny sandbox exec my-sandbox ls -la
bunny sandbox exec my-sandbox --cwd /tmp env
bunny sandbox exec my-sandbox --env DEBUG=1 -- node app.js
bunny sandbox exec my-sandbox --timeout 30 -- bun run build # exit 124 on timeout
```

| Flag | Description | Default |
| ------------ | --------------------------------------------------------------- | ------------ |
| `--cwd` | Working directory inside the sandbox | `/workplace` |
| `--env` | Temporary environment variable as `KEY=VALUE` (repeatable) | |
| `--env-file` | Load temporary environment variables from a dotenv file | |
| `--timeout` | Close the SSH connection and exit `124` after this many seconds | |

Variables passed here apply to that single command only. For persistent variables, use `bunny sandbox env`.

---

## `bunny sandbox ssh`

Open a full interactive SSH session (bash at `/workplace`). `exit` or Ctrl-D closes it.

```bash
bunny sandbox ssh my-sandbox
bunny sandbox ssh my-sandbox -e DEBUG=1 --env-file .env # session-only variables
```

---

## `bunny sandbox cp`

Copy a single file between the local machine and a sandbox over SFTP. Exactly one path must be `<sandbox>:<path>`; relative remote paths resolve against `/workplace`. Uploads preserve the local Unix mode. Directory and sandbox-to-sandbox copies are not supported.

```bash
bunny sandbox cp ./app.js my-sandbox:/workplace/app.js
bunny sandbox cp ./app.js my-sandbox:app.js # relative to /workplace
bunny sandbox cp ./app.js my-sandbox:/workplace/src/ # trailing slash keeps the filename
bunny sandbox cp my-sandbox:/workplace/out.log ./logs/ # ./logs must already exist
```

---

## `bunny sandbox files`

Inspect files over SFTP. A bare sandbox name targets `/workplace`; use `<sandbox>:<path>` for a specific directory.

```bash
bunny sandbox files list my-sandbox # alias: ls
bunny sandbox files ls my-sandbox:src
bunny sandbox files ls my-sandbox --output json # name, type, size, mode
```

---

## Public URLs

Expose ports running inside a sandbox as public HTTPS endpoints (for dev servers and APIs).

### `bunny sandbox url add`

Waits until the URL is provisioned and prints it.

```bash
bunny sandbox url add my-sandbox 3000 # endpoint named "port-3000"
bunny sandbox url add my-sandbox 8080 --label my-api
```

### `bunny sandbox url list` / `delete`

```bash
bunny sandbox url list my-sandbox # user-created endpoints (alias: ls)
bunny sandbox url delete my-sandbox port-3000
bunny sandbox url rm my-sandbox my-api -f # alias; --force skips confirmation
```

---

## Persistent environment variables

`bunny sandbox env` manages the variables baked into the container (unlike the temporary `--env` on `exec`/`ssh`). Changing them redeploys the sandbox and restarts running processes.

### `bunny sandbox env set`

Merges with the existing set.

```bash
bunny sandbox env set my-sandbox NODE_ENV=production
bunny sandbox env set my-sandbox A=1 B=2
bunny sandbox env set my-sandbox --env-file .env
```

### `bunny sandbox env list` / `delete`

```bash
bunny sandbox env list my-sandbox # alias: ls (internal AGENT_TOKEN hidden)
bunny sandbox env delete my-sandbox NODE_ENV
bunny sandbox env rm my-sandbox A B # aliases: rm, unset
```

Unset names are reported and skipped; if none match, the command errors and nothing is redeployed.
Loading