npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

bunny-tools

v0.1.5

Published

Bunny.net CLI + MCP server. Deploy static sites to Bunny Storage and purge CDN with one command. Manage Storage, Pull Zones, DNS, Stream, Edge Scripting from a single binary - plus AI-native MCP for Claude Code & Claude Desktop.

Readme

Bunny CLI and MCP Server

npm npm downloads CI e2e nightly License: MIT

Package: bunny-tools · Binary: bunny · Node: ≥20

Why bunny-tools

Bunny.net is a great CDN/storage/DNS/streaming platform but managing it from the terminal was DIY territory. bunny-tools fixes that with one binary covering Storage, CDN, DNS, Stream, and Edge Scripting - and a built-in MCP server so AI agents can drive every command:

  • bunny deploy for static sites. Familiar ergonomics if you've used firebase deploy - walk public dir → SHA-cached diff → parallel upload → CDN purge, in one command.
  • bunny.json is your single source of truth. Versioned in git. Every command honors it. JSON Schema published at unpkg.com/bunny-tools/schema/bunny.schema.json.
  • AI-native via MCP. AI agents see the same surface you do - no separate plugin per agent. bunny install mcp registers it with Claude Code in one shot.
  • Verified end-to-end. 185 unit tests + nightly drift detection against a real Bunny account. We catch Bunny API changes before they break your deploys.

Install

As a CLI

npm install -g bunny-tools

As an MCP server (recommended for AI workflows)

For Claude Code:

claude mcp add bunny-tools npx -y bunny-tools mcp

For Claude Desktop, add to claude_desktop_config.json:

{
  "mcpServers": {
    "bunny-tools": {
      "command": "npx",
      "args": ["-y", "bunny-tools", "mcp"]
    }
  }
}

Once installed, any Claude session can use 15 high-level tools (bunny.deploy, bunny.purge, zone/dns CRUD) plus 3 resources (bunny://manifest, bunny://agents, bunny://config/current) without needing prior context. See MCP server below for the full tool surface.

Quickstart

bunny init                   # interactive: auth + feature picker + bunny.json
bunny deploy --dry-run       # preview
bunny deploy                 # storage sync + CDN purge

bunny init walks you through:

  1. Bunny account API key (skipped if already in env or keychain)
  2. Feature multi-select - Storage+CDN, DNS, Stream, Magic Containers, Edge Scripting
  3. Per-feature config (e.g. for Storage+CDN: public dir, storage zone, password, pull zone, purge strategy)

Non-interactive form for CI:

bunny init --non-interactive --features=storage \
  --api-key=$BUNNY_API_KEY \
  --storage-zone=my-app \
  --storage-password=$BUNNY_STORAGE_PASSWORD \
  --pull-zone=12345

Add --ci to also generate .github/workflows/bunny-deploy.yml for GitHub Actions.

Quickstart for AI agents

With the MCP server installed (see Install), Claude Code and Claude Desktop can drive every command. Drop into any project and try:

| What you say | What happens | | --- | --- | | "Use bunny-tools to set up CI/CD for this project" | Runs bunny init, writes .github/workflows/deploy.yml using the official action, and lists the secrets you need to add | | "Deploy this site to Bunny" | Reads existing bunny.json, runs bunny deploy (with dry-run preview first) | | "Purge the CDN cache for tag release-2026-04" | Calls bunny.purge with tag:release-2026-04 | | "Show me what's on my Bunny account" | Calls bunny.whoami + lists reachable zone counts | | "Add an A record for www → 1.2.3.4 on my Bunny DNS zone for example.com" | Resolves the zone id, calls bunny.dns_record_add |

For best results in a new project, drop a 2-line hint into the project's CLAUDE.md:

## Deploy
This project uses bunny-tools. Run `bunny init` for first-time setup, then `bunny deploy`.

This anchors Claude to bunny-tools for that project's deploy work.


Setup & Auth

| Command | Description | | --- | --- | | bunny init | Interactive setup - auth + feature picker + bunny.json | | bunny configure | Walkthrough - store credentials in a named profile | | bunny configure list | List all credential profiles + scopes (masked) | | bunny configure switch <name> | Set the active profile | | bunny configure remove <name> [scope] | Remove a profile, or a single scope inside one | | bunny use [alias] | Switch active alias from .bunnyrc (or list aliases) | | bunny whoami | Show current account context + reachable zone counts | | bunny docs [topic] | Open Bunny.net docs in browser |

Example

bunny configure --profile=staging
bunny configure switch staging

Deploy & Purge

| Command | Description | | --- | --- | | bunny deploy | Sync public dir to storage zone and purge CDN cache | | bunny purge <target> | Purge by URL, tag:<name>, or pullzone:<id> |

Example

bunny deploy --dry-run
bunny purge tag:release-2026-05

Storage (file operations)

| Command | Description | | --- | --- | | bunny storage upload <local> <remote> | Upload a single file to the active zone | | bunny storage download <remote> <local> | Download a single file from a zone | | bunny storage list [path] | List a storage-zone path | | bunny storage delete <path> | Delete a file or path (use --recursive for dirs) | | bunny storage sync <local-dir> | Mirror local dir to zone - SHA-cached diff, parallel upload |

Example

bunny storage sync ./dist --zone=my-app

Storage Zones

| Command | Description | | --- | --- | | bunny storagezone list | List storage zones | | bunny storagezone get <id\|name> | Get a storage zone | | bunny storagezone create <name> | Create a storage zone | | bunny storagezone update <id> --body=<json> | Update a storage zone (raw JSON body) | | bunny storagezone delete <id> | Delete a storage zone |

Pull Zones (CDN)

Tip: bunny cdn ... works everywhere bunny pullzone ... does - Bunny's dashboard calls these "CDN", so the alias is there for muscle memory. Canonical name follows Bunny's API (pullzone).

| Command | Description | | --- | --- | | bunny pullzone list (or bunny cdn list) | List pull zones | | bunny pullzone get <id> | Get a pull zone | | bunny pullzone create <name> | Create a pull zone | | bunny pullzone update <id> --body=<json> | Update a pull zone (raw JSON body) | | bunny pullzone delete <id> | Delete a pull zone | | bunny pullzone edgerule list <id> | List edge rules on a pull zone | | bunny pullzone edgerule add <id> --rule=<json> | Add an edge rule (raw JSON rule) | | bunny pullzone edgerule delete <id> <rule-id> | Delete an edge rule | | bunny pullzone hostname list <id> | List custom hostnames linked to a pull zone | | bunny pullzone hostname add <id> <hostname> | Link hostname + provision Let's Encrypt cert + ForceSSL. Idempotent. --no-force-ssl opts out of HTTP→HTTPS redirect | | bunny pullzone hostname remove <id> <hostname> | Unlink a custom hostname |

Example

bunny cdn edgerule list 12345

# Wire DNS to a pull zone (2 steps - `add` does link + cert + ForceSSL
# in one idempotent call; the DNS record points at the wired-up PZ):
bunny pullzone hostname add 5780316 example.com           # ~2-90s
bunny dns record add 783181 PULLZONE @ --pull-zone=5780316

# Or do everything in one shot via the atomic Connect Domain command:
bunny domain connect 5780316 example.com --dns-zone=783181

DNS

| Command | Description | | --- | --- | | bunny dns list | List DNS zones | | bunny dns get <id\|domain> | Get a DNS zone | | bunny dns create <domain> | Create a DNS zone | | bunny dns delete <id> | Delete a DNS zone | | bunny dns record list <zone> | List records on a zone | | bunny dns record add <zone> <type> <name> <value> | Add a record (positional args) | | bunny dns record update <zone> <record-id> --body=<json> | Update a record | | bunny dns record delete <zone> <record-id> | Delete a record |

Supported record types: standard A, AAAA, CNAME, TXT, MX, SRV, CAA, NS plus Bunny routing types REDIRECT, PULLZONE, PTR, SCRIPT. PULLZONE and SCRIPT need --link-name=<id> (the linked pull zone / script id). For PULLZONE you can use the convenience flag --pull-zone=<id> instead and the CLI will fill in both the value and link-name from the pull zone's metadata. (FLATTEN is documented in Bunny's OpenAPI spec but the live API rejects it; dropped from supported types - re-add when Bunny enables it server-side.)

Examples

# Standard A record
bunny dns record add 783181 A www 1.2.3.4 --ttl=300

# Redirect www → https://example.com
bunny dns record add 783181 REDIRECT www https://example.com

# Wire DNS to a pull zone - auto-fills value + link-name
bunny dns record add 783181 PULLZONE "" --pull-zone=5780316

# Or raw form if you already know the pz name
bunny dns record add 783181 PULLZONE "" my-pz-name --link-name=5780316

Stream

| Command | Description | | --- | --- | | bunny stream library list | List Stream libraries | | bunny stream library create <name> | Create a Stream library | | bunny stream library delete <id> | Delete a Stream library | | bunny stream video list <library> | List videos in a library | | bunny stream video upload <library> <file> | Upload a video to a library | | bunny stream video delete <library> <video-id> | Delete a video |

Example

bunny stream video upload 42 ./demo.mp4 --title="My demo"

Magic Containers

| Command | Description | | --- | --- | | bunny containers app list | List container apps | | bunny containers app delete <id> | Delete a container app |

containers app create is deferred to v0.2 - Bunny's v3 schema requires runtimeType + containerTemplates[] + autoScaling which the current CLI surface doesn't yet model. Manage creation via the Bunny dashboard for now.

Edge Scripting

| Command | Description | | --- | --- | | bunny scripting list | List edge scripts | | bunny scripting deploy <name> --code=<file> | Create or update a script (dual-mode) | | bunny scripting delete <id> | Delete a script |

Example

bunny scripting deploy my-router --code=./worker.js

Discovery & AI

| Command | Description | | --- | --- | | bunny manifest --pretty | Full registry as JSON (machine-readable surface) | | bunny manifest --names | One command name per line - handy for shell completion | | bunny <any-command> --help-json | Help for any command as JSON | | bunny mcp | Boot MCP stdio server (15 tools, 3 resources) |

See AGENTS.md for AI-agent guidance.


Global flags

Apply to any command:

| Flag | Effect | | --- | --- | | -c, --config <path> | Override bunny.json location | | --cwd <dir> | Run as if launched from this directory | | -e, --env <alias> | One-shot .bunnyrc alias | | -p, --profile <name> | One-shot credential profile |

Example

bunny --profile=staging deploy

Configuration

bunny.json (per-project, git-tracked):

{
  "$schema": "https://unpkg.com/bunny-tools/schema/bunny.schema.json",
  "deploy": {
    "publicDir": "dist",
    "ignore": ["bunny.json", ".bunnyrc", "**/.*", "**/node_modules/**"],
    "storageZone": "my-app",
    "region": "ny",
    "concurrency": 8,
    "pullZones": [{ "id": 12345, "purge": "all" }]
  }
}

.bunnyrc (per-developer aliases, gitignored):

{
  "default": "prod",
  "aliases": {
    "prod":    { "storageZone": "my-app",     "pullZones": [12345] },
    "staging": { "storageZone": "my-app-stg", "pullZones": [12346] }
  }
}

Multi-account profiles (~/.config/bunny-tools/credentials.json):

{
  "active": "default",
  "profiles": {
    "default": { "account": "...", "storage:my-app": "..." },
    "staging": { "account": "...", "storage:my-app-stg": "..." }
  }
}

Switch the active profile with bunny configure switch <name>, or one-shot with bunny --profile=<name> <cmd> or BUNNY_PROFILE=<name>.

Auth model

Four credential scopes (all use the AccessKey HTTP header):

  • account - Account API key
  • storage:<zone> - Storage zone password (per zone)
  • stream:<lib> - Stream library API key (per library)
  • database:<name> - Database access key

Resolver chain (per call site): --flag → scoped env (e.g. BUNNY_STORAGE_PASSWORD_MY_APP) → generic env (BUNNY_STORAGE_PASSWORD) → OS keychain (<profile>:<scope> keys) → ~/.config/bunny-tools/credentials.json → interactive prompt.

GitHub Actions

bunny init --ci generates a workflow that uses npm-install + bunny deploy:

- name: Install bunny-tools
  run: npm install -g bunny-tools
- name: Deploy
  env:
    BUNNY_API_KEY: ${{ secrets.BUNNY_API_KEY }}
    BUNNY_STORAGE_PASSWORD_MY_APP: ${{ secrets.BUNNY_STORAGE_PASSWORD_MY_APP }}
  run: bunny deploy

A composite action wrapper (bytekcorp/bunny-tools-deploy-action@v1) is on the v0.2 roadmap for tighter ergonomics. The npm-install form above is the canonical path for v0.1.

MCP server (AI integration)

Install steps are at the top under Install → As an MCP server. Once configured, the server exposes:

Tools (15): bunny.deploy, bunny.purge, bunny.init, bunny.manifest, bunny.whoami, storage zone CRUD, pull zone CRUD, DNS zone + record CRUD, plus bunny.run as an escape hatch for any CLI invocation.

Resources (3):

  • bunny://manifest - full command registry as JSON
  • bunny://agents - AGENTS.md (workflows, gotchas, conventions for AI agents)
  • bunny://config/current - resolved config from bunny.json + active alias

Cross-project usage. With the MCP server installed, drop a 2-line hint into any new project's CLAUDE.md to anchor Claude to bunny-tools for that project:

## Deploy
This project uses bunny-tools. Run `bunny init` for first-time setup, then `bunny deploy`. See `bunny manifest --pretty` for the full command surface.

Development

git clone https://github.com/bytekcorp/bunny-tools
cd bunny-tools
npm ci
npm run build
npm test
npm run dev -- manifest --pretty

For end-to-end testing against a real Bunny account (drift detection), see docs/e2e-testing.md.

For release instructions, see docs/deployment-guide.md.

FAQ

Is this the official Bunny.net CLI? No. bunny-tools is a community CLI. Bunny.net publishes @bunny.net/cli, which focuses on Databases, Magic Containers, and Edge Scripts. bunny-tools covers a different surface (Storage, CDN, DNS, Stream, Edge Scripting) and ships an MCP server for AI agents.

Why the binary name bunny? Short and matches the brand. Note that @bunny.net/cli also installs a bunny binary, so installing both globally will collide - pick one or use npx for the other.

Can I use this in CI? Yes. bunny init --ci generates a .github/workflows/bunny-deploy.yml. All commands honor BUNNY_API_KEY and per-zone scoped env vars.

Does it work without Node.js? Currently npm-only (Node 20+). A standalone binary is on the v0.2 roadmap.

License

MIT - see LICENSE.