From 18fd57ace787da2e3a2f553c0afe3d0b3a20e5e0 Mon Sep 17 00:00:00 2001 From: jamie-at-bunny Date: Wed, 15 Jul 2026 16:54:24 +0100 Subject: [PATCH 1/4] docs(sandbox): document Claude Code auth, add sandbox skill reference --- packages/cli/README.md | 5 + skills/bunny-cli/SKILL.md | 8 +- skills/bunny-cli/references/sandbox.md | 163 +++++++++++++++++++++++++ 3 files changed, 175 insertions(+), 1 deletion(-) create mode 100644 skills/bunny-cli/references/sandbox.md diff --git a/packages/cli/README.md b/packages/cli/README.md index 248d953c..51511c76 100644 --- a/packages/cli/README.md +++ b/packages/cli/README.md @@ -855,6 +855,8 @@ 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. +Claude Code is pre-installed but needs your own Anthropic credentials before it can do anything: pass an API key at create time (`-e ANTHROPIC_API_KEY=sk-ant-...` or `--env-file .env`), or run `claude` inside the sandbox and complete the login prompt it prints. Either way the credentials persist for the life of the sandbox. + Sandbox credentials (app ID, hostname, SSH endpoint, agent token) are stored in `~/.config/bunnynet.json` so you can reconnect without re-creating. #### `bunny sandbox create` @@ -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 +bunny sandbox create my-sandbox -e ANTHROPIC_API_KEY=sk-ant-... ``` | Flag | Alias | Description | Default | diff --git a/skills/bunny-cli/SKILL.md b/skills/bunny-cli/SKILL.md index 3d79a4e6..367a755a 100644 --- a/skills/bunny-cli/SKILL.md +++ b/skills/bunny-cli/SKILL.md @@ -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 @@ -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? @@ -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`) diff --git a/skills/bunny-cli/references/sandbox.md b/skills/bunny-cli/references/sandbox.md new file mode 100644 index 00000000..94eee975 --- /dev/null +++ b/skills/bunny-cli/references/sandbox.md @@ -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, hostname, SSH endpoint, agent token) are stored in the local config (`~/.config/bunnynet.json`), 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 (`-e ANTHROPIC_API_KEY=...` or `--env-file .env`), set it later with `bunny sandbox env set`, or run `claude` inside the sandbox and complete the login prompt. Credentials persist for the life of the sandbox. + +## Typical workflows + +```bash +# Create, run a command, expose a dev server, tear down +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 # 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 -e ANTHROPIC_API_KEY=sk-ant-... # ready 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, public HTTPS hostname, and SSH address. + +--- + +## `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 `:`; 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/ +``` + +--- + +## `bunny sandbox files` + +Inspect files over SFTP. A bare sandbox name targets `/workplace`; use `:` 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. From 14acbfe0148b0d29b568479994e02e6de2251d1f Mon Sep 17 00:00:00 2001 From: jamie-at-bunny Date: Wed, 15 Jul 2026 16:56:10 +0100 Subject: [PATCH 2/4] fmt --- skills/bunny-cli/references/sandbox.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/skills/bunny-cli/references/sandbox.md b/skills/bunny-cli/references/sandbox.md index 94eee975..11d0ea2d 100644 --- a/skills/bunny-cli/references/sandbox.md +++ b/skills/bunny-cli/references/sandbox.md @@ -37,11 +37,11 @@ bunny sandbox create my-sandbox -e NODE_ENV=production --env-file .env bunny sandbox create my-sandbox -e ANTHROPIC_API_KEY=sk-ant-... # ready 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 | | +| 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, public HTTPS hostname, and SSH address. From 219c05e60ab4d76cddd80d7cb529a9c1ff3fe4cc Mon Sep 17 00:00:00 2001 From: jamie-at-bunny Date: Wed, 15 Jul 2026 17:05:00 +0100 Subject: [PATCH 3/4] docs(sandbox): address review feedback on create output, key handling, config paths --- packages/cli/README.md | 12 ++++++------ skills/bunny-cli/references/sandbox.md | 12 ++++++------ 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/packages/cli/README.md b/packages/cli/README.md index 51511c76..50b9b9dc 100644 --- a/packages/cli/README.md +++ b/packages/cli/README.md @@ -855,9 +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. -Claude Code is pre-installed but needs your own Anthropic credentials before it can do anything: pass an API key at create time (`-e ANTHROPIC_API_KEY=sk-ant-...` or `--env-file .env`), or run `claude` inside the sandbox and complete the login prompt it prints. Either way the credentials persist for the life of the sandbox. +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, hostname, SSH endpoint, agent token) are stored in `~/.config/bunnynet.json` so you can reconnect without re-creating. +Sandbox credentials (app ID, SSH endpoint, agent token) are stored in `~/.config/bunnynet.json` so you can reconnect without re-creating. #### `bunny sandbox create` @@ -877,8 +877,8 @@ bunny sandbox create my-sandbox --region NY 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 -bunny sandbox create my-sandbox -e ANTHROPIC_API_KEY=sk-ant-... +# 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 | @@ -889,7 +889,7 @@ bunny sandbox create my-sandbox -e ANTHROPIC_API_KEY=sk-ant-... 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` @@ -900,7 +900,7 @@ bunny sandbox list bunny sandbox ls # alias ``` -Columns: Name, App ID, Hostname, SSH. +Columns: Name, App ID, SSH. #### `bunny sandbox delete` diff --git a/skills/bunny-cli/references/sandbox.md b/skills/bunny-cli/references/sandbox.md index 11d0ea2d..ed1e0184 100644 --- a/skills/bunny-cli/references/sandbox.md +++ b/skills/bunny-cli/references/sandbox.md @@ -2,15 +2,15 @@ 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, hostname, SSH endpoint, agent token) are stored in the local config (`~/.config/bunnynet.json`), so commands reference sandboxes by name. +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 (`-e ANTHROPIC_API_KEY=...` or `--env-file .env`), set it later with `bunny sandbox env set`, or run `claude` inside the sandbox and complete the login prompt. Credentials persist for the life of the sandbox. +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 # Create, run a command, expose a dev server, tear down -bunny sandbox create my-sandbox -e ANTHROPIC_API_KEY=sk-ant-... +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 @@ -34,7 +34,7 @@ bunny sandbox create # interactive: prompts fo 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 -e ANTHROPIC_API_KEY=sk-ant-... # ready for Claude Code +bunny sandbox create my-sandbox --env-file .env # bake in ANTHROPIC_API_KEY for Claude Code ``` | Flag | Alias | Description | Default | @@ -43,7 +43,7 @@ bunny sandbox create my-sandbox -e ANTHROPIC_API_KEY=sk-ant-... # ready for Cl | `--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, public HTTPS hostname, and SSH address. +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`. --- @@ -98,7 +98,7 @@ Copy a single file between the local machine and a sandbox over SFTP. Exactly on 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/ +bunny sandbox cp my-sandbox:/workplace/out.log ./logs/ # ./logs must already exist ``` --- From 172fff5fcf99980affd6536ef8d76848b6e99438 Mon Sep 17 00:00:00 2001 From: jamie-at-bunny Date: Thu, 16 Jul 2026 08:40:05 +0100 Subject: [PATCH 4/4] docs(sandbox): note default config path is not the only candidate --- packages/cli/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/cli/README.md b/packages/cli/README.md index 50b9b9dc..c26f48bf 100644 --- a/packages/cli/README.md +++ b/packages/cli/README.md @@ -857,7 +857,7 @@ Manage on-demand cloud sandbox environments backed by Bunny Magic Containers. Ea 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 `~/.config/bunnynet.json` so you can reconnect without re-creating. +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`