Skip to main content
bunny lab holds commands we are still shaping. The name is the warning: the flags and the output can change between CLI releases, so a workflow built on one should expect to be updated. Astro is the first, and it has two commands and no more:
Server-side rendering only. A build that prerenders every page is a directory of files, and bunny sites deploy deploys one; this command refuses it and says which command to run.
The full Astro guide is at Deploy an Astro site. This page is the command reference.

Deploy

1

Log in

2

Run the command in your Astro project

Nothing above asks for a password. The CLI creates the storage zone, so it already holds the credentials. It sets them on the script as secrets.

What it creates

Three resources, all named after your app: The suffix is there because a storage zone name and a pull zone name are unique across all of bunny.net. The app name comes from --name, then .bunny/astro.json, then your package.json. The script is the pull zone’s origin, so nothing sits between a request and the code. That is the difference from bunny sites, where the script is a router in front of a storage origin. .bunny/astro.json links this directory to those three resources, and the command adds .bunny/ to your .gitignore. It is a pointer, not a source of truth: --name finds the same resources by name, which is what a fresh clone or a CI runner does.

What one deploy does

  1. Finds the project. A monorepo root is not one, so it offers the projects below it.
  2. Checks the Astro version. The adapter needs Astro 7. An older project stops here, and the message names npx @astrojs/upgrade.
  3. Puts the adapter in. It installs @bunny.net/astro-adapter and sets it in the Astro config. Another host’s adapter is replaced, and its package uninstalled.
  4. Builds, unless --no-build.
  5. Reads .bunny/build.json. It has to say kind: "ssr".
  6. Reads the bundle. Over 10 MB the platform refuses it, so this refuses first, before any resource exists.
  7. Finds or creates the three resources. Each is looked up before it is made, so a half-finished create re-runs cleanly.
  8. Applies the pull zone settings. What the manifest asks for, and the zone’s cache override off.
  9. Sets the script’s variables.
  10. Uploads the client build, then publishes the code. In that order, always.
  11. Purges, waits, purges.
  12. Asks the site for a page, and for a path it does not hold.
  13. Deletes every deploy folder but this one and the one before it.
A deploy that changes nothing does nothing, and says so. --force publishes it again.
A green line above a URL that answers 400 is the worst thing this command can do, so a script that does not start is reported instead:
A script has 500 ms to start, and every byte of it is parsed first. Measured in August 2026: the same code served every request at 7.4 MB, and none at 7.8 MB, well under the documented 10 MB limit.

Undeploy

It lists the three resources first, then asks you to type the app’s name:
The pull zone goes first, because it is the only public thing. A resource the API already reports as missing counts as deleted, so a run that failed halfway can simply be repeated.

Unattended runs

--yes is what lets the command install the adapter and edit the Astro config without asking. Without it, an unattended run prints the two changes and stops: a deploy command that silently rewrites your source in CI is worse than one that refuses. --output json carries the deploy’s ID, its URL, its sizes, whether the site is serving, and every variable the CLI could not set.

Every command

What is not here yet

  • Rollback. One Edge Script publishes one version at a time. Deploy the commit you want instead.
  • A preview URL per branch. Every deploy publishes to production. Deploy a second app for staging: --name my-app-staging.
  • A custom domain from the command line. Add it to the app’s pull zone in the dashboard, under CDN > your pull zone > Hostnames.
  • Any framework but Astro. SvelteKit and Next.js are planned.
Last modified on August 25, 2026