Build and deploy scripts at the edge with the bunny.net CLI

Posted by:

A few weeks ago we introduced the bunny.net CLI, one command-line tool for managing your entire bunny.net stack. That first release shipped with full Database support, and we promised more would follow.

Today, Edge Scripting lands in the CLI.

You can scaffold a new script from a template, develop and test it locally with Node or Deno, deploy a built bundle to the global network, manage environment variables, and step through deployment history from your terminal.

A two-minute tour

If you've already got the CLI installed and you're logged in, three commands will get you to a deployed function:

bunny scripts init --name my-edge-app --type standalone --template "Return JSON" --deploy
cd my-edge-app
npm run build
bunny scripts deploy dist/index.js

If you haven't installed the CLI yet, do that first:

npm install -g @bunny.net/cli
bunny login

Scaffold a project from a template

bunny scripts init creates a new edge script project on your machine. Run it with no flags and the CLI walks you through it interactively, asking you to pick a template, name the project, and choose whether to install dependencies:

bunny scripts init

You can also pass everything as flags, which is handy when you're in a hurry or when an agent is driving:

bunny scripts init \
  --name my-edge-app \
  --type standalone \
  --template "Return JSON"

Add --deploy to also create the remote script on bunny.net and link the directory in the same step. Without it, init only scaffolds the local project, and you create the remote script later with bunny scripts create.

The built-in templates are Empty, Return JSON, and Simple Middleware. Each one comes with a working project layout and sensible defaults so you can build and deploy straight away.

You can also bring your own template from a Git repo:

bunny scripts init --name my-edge-app --repo user/my-template

Custom templates always prompt before installing dependencies, since a template's install scripts run on your machine. Review the repo before you let it install.

Run it locally

Edge Scripts are JavaScript and TypeScript projects built on Web-standard APIs. You develop them locally with your own editor and the debugging tools you already use.

The CLI auto-detects your package manager from the template's lockfile (bun, npm, pnpm, or yarn) and uses the template's own dev and build scripts:

cd my-edge-app
npm install
npm run dev

The CLI doesn't yet ship a custom runtime emulator. It wraps the tools you'd reach for anyway, so local development stays fast and predictable.

Once you've got something you want to deploy, connect the working directory to a script on bunny.net:

bunny scripts link

Run it once, and it writes a small .bunny/script.json manifest into your project that records which script on bunny.net this directory belongs to. From that point on, every other scripts command knows what you're targeting:

  • bunny scripts deploy deploys this project
  • bunny scripts env set API_KEY=... writes to this script's environment
  • bunny scripts deployments list shows this script's history

The script ID stays out of your shell history, and you don't pass it on every command. Run bunny scripts link with no flags to choose from a list, or bunny scripts link --id 12345 to link directly.

The manifest holds per-developer state, so it shouldn't be committed. bunny scripts init adds .bunny/ to your .gitignore automatically. If you ran bunny scripts link or bunny scripts create in an existing repo, add .bunny/ to .gitignore yourself, then anyone who clones the repo links their own script.

For those deploying scripts in CI, you can skip the project linking by passing the Edge Script ID when you deploy:

bunny scripts deploy dist/index.js 12345

Build and deploy

Edge Scripts deploy as a single built bundle. The CLI doesn't build for you, so run the template's own build step first, then point deploy at the output:

npm run build
bunny scripts deploy dist/index.js

deploy uploads the file as a new release and publishes it live by default. On success it prints the script's live hostname:

✓ Published my-edge-app
  https://my-edge-app.bunny.run

If you want to upload a release without publishing it, stage it with --skip-publish and publish later.

Put it on your own domain

Every script gets a bunny.run URL, but you can also bring your own domain. We've made it super easy with a new command:

bunny scripts domains add shop.example.com

bunny scripts domains add sets up HTTPS on your own domain. bunny.net issues SSL certificates for free and can do so as soon as your DNS points to the network, so the command prints the exact CNAME record to create, along with the follow-up command to run. Once DNS has propagated, request your certificate:

bunny scripts domains ssl shop.example.com

HTTPS is enforced by default, so anyone arriving over http:// is redirected.

List a script's domains any time to check their SSL status:

bunny scripts domains list

Manage environment variables and secrets

Most edge functions need configuration values like API tokens, feature flags, or region hints. The CLI handles two kinds. Plain variables are stored on bunny.net and can be read back. Secrets are encrypted, and their values can never be read back once set:

bunny scripts env set DATABASE_URL "libsql://..."
bunny scripts env set API_KEY "sk_..." --secret
bunny scripts env list
bunny scripts env remove API_KEY

Names are uppercased automatically, and a name can be a variable or a secret but not both. env list shows secret values as blank, since the API never returns them.

To pull plain variables into a local file for development, use env pull. It writes NAME=VALUE lines to .bunny/.env. Secrets are never included, so keep their source values somewhere safe:

bunny scripts env pull

Listing supports --output json, useful for diffing or syncing with another tool:

bunny scripts env list --output json | jq '.[].name'

Deployment history

Every release is recorded, and the CLI gives you a view into that history:

bunny scripts deployments list

ID       Status      Author   Released   Published
14021    ● Live      jamie    2m ago     yes
14008    ○ Archived  jamie    1h ago     yes
13990    ○ Archived  jamie    1d ago     yes

The live release is marked with a filled dot, and archived releases are marked with an open one. If a release is live and the script has a linked pull zone, the hostname is printed at the end.

Need to roll back? You don't have to rebuild anything. The bundle for every past release is already on bunny.net, so grab the ID of a known-good one from that list and republish it:

bunny scripts deployments publish 13990

This flips which release is live without re-uploading anything, so a bad deploy can be undone in seconds. deploy ships new code. publish re-promotes a release that has already shipped.

See how it's doing

Once a script is serving traffic, you'll want to know how much traffic it's handling and what it's costing. bunny scripts stats pulls request, CPU, and cost totals for the script and draws a per-day bar chart of requests served right in your terminal:

bunny scripts stats

Key                   Value
Script                bunny-cards
Period                last 30 days
Total Requests        1,455
Total CPU             43,336ms
Avg CPU / Execution   29.78ms
Total Cost            $0.00

Requests served
May 18, 2026  ░░░░░░░░░░░░░░░░░░░░░░░░    0
May 19, 2026  ████████████████████████  504
May 20, 2026  ██████████████████░░░░░░  383
May 21, 2026  ░░░░░░░░░░░░░░░░░░░░░░░░    0
May 22, 2026  ░░░░░░░░░░░░░░░░░░░░░░░░    0
May 23, 2026  ░░░░░░░░░░░░░░░░░░░░░░░░    0
May 24, 2026  ░░░░░░░░░░░░░░░░░░░░░░░░    0
May 25, 2026  █░░░░░░░░░░░░░░░░░░░░░░░    4
May 26, 2026  ░░░░░░░░░░░░░░░░░░░░░░░░    0
May 27, 2026  █░░░░░░░░░░░░░░░░░░░░░░░    5
May 28, 2026  ██░░░░░░░░░░░░░░░░░░░░░░   37
May 29, 2026  ████░░░░░░░░░░░░░░░░░░░░   90
May 30, 2026  ░░░░░░░░░░░░░░░░░░░░░░░░    0
May 31, 2026  ░░░░░░░░░░░░░░░░░░░░░░░░    0
Jun 1, 2026   ░░░░░░░░░░░░░░░░░░░░░░░░    0
Jun 2, 2026   ░░░░░░░░░░░░░░░░░░░░░░░░    0
Jun 3, 2026   ░░░░░░░░░░░░░░░░░░░░░░░░    0
Jun 4, 2026   ███████████░░░░░░░░░░░░░  223
Jun 5, 2026   █████████░░░░░░░░░░░░░░░  191
Jun 6, 2026   █░░░░░░░░░░░░░░░░░░░░░░░   11
Jun 7, 2026   █░░░░░░░░░░░░░░░░░░░░░░░    5
Jun 8, 2026   █░░░░░░░░░░░░░░░░░░░░░░░    2

By default, it covers the last 30 days. Narrow the window with --from and --to, or switch to an hourly breakdown when you're chasing a spike:

bunny scripts stats --from 2026-05-01 --to 2026-05-31
bunny scripts stats --hourly

Like everything else, it uses your linked script when you don't pass an ID, and --output json gives you the data to pipe into whatever you use to track usage.

Works with your agent and CI

Prompts and spinners are TTY-aware, so they disappear in CI. Commands support --output json, and destructive commands like delete and env remove take --force so they don't block on a confirmation prompt in a pipeline.

In CI you can skip the global install and run the CLI through npx:

# .github/workflows/deploy.yml
- run: npm ci
- run: npm run build
- run: npx @bunny.net/cli scripts deploy dist/index.js ${{ secrets.SCRIPT_ID }}
  env:
    BUNNYNET_API_KEY: ${{ secrets.BUNNYNET_API_KEY }}

When you scaffold with bunny scripts init --deploy, the command prints the SCRIPT_ID to add as a repo secret, so CI deploys to the right script without committing the link manifest.

AI coding assistants use the CLI directly, either from a global install or through npx @bunny.net/cli. We ship Edge Scripting skills alongside it, so Claude Code, Cursor, Windsurf, or any agent that runs shell commands can scaffold a project, link it, set environment variables, and deploy.

What's next

Edge Scripting joins Bunny Database in the CLI today. Storage, Magic Containers, and the rest of the bunny.net stack are coming next.

Get started and create your first Edge Script with the bunny.net CLI:

npm install -g @bunny.net/cli
bunny login
bunny scripts init

The CLI is open source and developed in public. If something's broken, open an issue. If you want to share what you've built, find us in Discord.