Skip to main content

CLI Reference

The EdgeBase CLI manages project scaffolding, local development, and deployment workflows.

Installation

npm install -g @edgebase/cli
# or use npx (no install needed)
npx edgebase <command>

Core Commands

init

Create a new EdgeBase project:

npx edgebase init [dir]
# Options:
# --no-dev Scaffold only; do not start the local dev server
# --no-open Do not open the Admin Dashboard when auto-starting dev

After scaffolding, init automatically starts the dev server and opens the Admin Dashboard in your browser — no extra commands needed. Use --no-dev for CI, monorepos, or when you want to wire the app before booting the backend.

This scaffolds the following files:

FileDescription
edgebase.config.tsDB blocks, access rules, auth settings
functions/onPostCreated.tsExample app function
.env.developmentLocal dev secrets (JWT keys auto-generated, git-ignored)
.env.development.exampleTemplate showing required env vars (committed)
.env.release.exampleTemplate for production env vars (committed)
.gitignoreIgnores .env.development, .env.release, node_modules, etc.
tip

Copy .env.release.example to .env.release and fill in production secrets before deploying. .env.release is git-ignored — your production keys never enter version control.

dev

Start the local development server:

npx edgebase dev
# Options:
# --port 8787 Port number (default: 8787)
# --no-open Do not open admin dashboard in browser (opens by default)

Opens http://localhost:8787 with:

  • REST API at /api/*
  • Admin Dashboard at /admin
  • WebSocket at /api/realtime

Environment variable loading:

Place your secrets in .env.development. On startup, dev automatically makes them available to the Wrangler process. You only need to edit .env.development.

deploy

Deploy to Cloudflare Workers:

npx edgebase deploy
# Options:
# --dry-run Validate config without deploying

Automatic Cloudflare login: On first deploy, EdgeBase checks your Cloudflare authentication status. If not logged in, it automatically opens browser login — no manual wrangler login needed. Your account_id is auto-detected and saved to wrangler.toml.

On first deploy, a SERVICE_KEY is auto-generated and stored in .edgebase/secrets.json.

Automatic secret upload:

If a .env.release file exists in your project root, deploy automatically uploads all variables to Cloudflare Workers Secrets via wrangler secret bulkbefore the actual deployment.

.env.release  →  wrangler secret bulk  →  Cloudflare Workers Secrets  →  c.env.*
BehaviorDetail
SERVICE_KEYExcluded from upload (auto-managed by deploy pipeline)
.env.release missingSilently skipped — no error, no warning
Manual secretsStill works: npx edgebase secret set KEY is unaffected

Deploy pipeline order:

  1. Cloudflare authentication (auto-login if needed)
  2. Config validation
  3. .env.release → Cloudflare Secrets (automatic)
  4. Turnstile provisioning (if captcha: true)
  5. KV / D1 / Vectorize provisioning
  6. wrangler deploy
  7. URL summary output
CI/CD

For non-interactive environments (GitHub Actions, etc.), set CLOUDFLARE_API_TOKEN as an environment variable. The auto-login flow only activates in interactive terminals.

No code changes needed

Your Worker code accesses secrets the same way regardless of source: c.env.STRIPE_SECRET_KEY, c.env.JWT_USER_SECRET, etc. Cloudflare injects secrets into the Worker environment automatically.

neon

Manage Neon PostgreSQL setup:

npx edgebase neon setup --namespace shared
npx edgebase neon setup --auth

neon setup can:

  • use the EdgeBase app name as the default Neon project name
  • reuse an existing Neon project with the same name before creating a new one
  • run the official neonctl auth flow when Neon credentials are missing
  • create a Neon project, database, and role or use an existing project/context
  • fetch a connection string for the selected target
  • write the connection string to .env.development and .env.release

Use this after setting provider: 'neon' on a DB block or auth.provider: 'neon' in edgebase.config.ts.

upgrade

Upgrade EdgeBase framework packages (DECISIONS #82):

npx edgebase upgrade
# Options:
# --check Dry-run: check for updates without installing
# --target <ver> Upgrade to a specific version
# --force Skip confirmation prompt

Auto-detects package manager (npm/pnpm/yarn) and checks for major/minor/patch updates across all EdgeBase packages.

Type & Observability

typegen

Generate TypeScript types from edgebase.config.ts:

npx edgebase typegen
npx edgebase typegen --output src/edgebase.d.ts

logs

Stream real-time logs from deployed Worker:

npx edgebase logs
npx edgebase logs --format json
npx edgebase logs --filter status:500
npx edgebase logs --name my-worker
OptionDescription
--format <format>Output format: json or pretty (default: pretty)
--filter <filter>Filter by status:500, method:POST, or free text search
--name <name>Worker name (auto-detected from wrangler.toml)

Data Management

backup

Create or restore portable backups across all environments:

# Create backup (DB only)
npx edgebase backup create --url <URL> --service-key <KEY>

# Create backup with secrets + storage
npx edgebase backup create --include-secrets --include-storage

# Create backup from Edge (Cloudflare API for DO enumeration)
npx edgebase backup create --account-id <CF_ID> --api-token <CF_TOKEN>

# Restore from backup file
npx edgebase backup restore --from backup.json --url <URL> --service-key <KEY>

# Restore without confirmation prompt
npx edgebase backup restore --from backup.json --yes

backup create always includes the two internal D1 databases: CONTROL_DB (plugin/control-plane metadata) and AUTH_DB (auth data).

Required backup state is strict: if DO enumeration, any DO dump, CONTROL_DB, or AUTH_DB dump fails, backup create exits non-zero and does not emit a completed backup file. backup restore also exits non-zero if required restore stages fail (CONTROL_DB, AUTH_DB, orphan cleanup, DO restore, and requested R2 restore). Only _users_public resync is warning-only.

In --json mode, stdout is reserved for the final JSON result object. backup restore requires --yes in JSON mode, while backup create --include-storage auto-confirms the storage download because the flag is already an explicit opt-in.

Create options:

FlagDescription
--url <url>Worker URL (or EDGEBASE_URL env)
--service-key <key>Service Key (or EDGEBASE_SERVICE_KEY env)
--output <path>Output file/directory path
--include-secretsInclude JWT/Service Key in backup
--include-storageInclude R2 files (outputs .tar.gz)
--account-id <id>Cloudflare Account ID (Edge only)
--api-token <token>Cloudflare API Token (Edge only)

Restore options:

FlagDescription
--from <path>Path to backup file (.json or .tar.gz)
--url <url>Target Worker URL
--service-key <key>Target Service Key
--yesSkip confirmation prompt
--skip-secretsDon't restore secrets
--skip-storageDon't restore R2 files
--account-id <id>Cloudflare Account ID (Edge target)
--api-token <token>Cloudflare API Token (Edge target)

See the Backup & Restore guide for architecture details and migration scenarios.

migration

Generate migration skeleton snippets (DECISIONS #62):

npx edgebase migration create add-category
npx edgebase migration create add-views --table posts
OptionDescription
-c, --table <name>Target table (enables auto version numbering)

The create subcommand outputs a migration snippet to paste into your edgebase.config.ts migrations array. When --table is provided, it reads the config to auto-increment the version number.

seed

Load seed data from edgebase.seed.json into local dev server:

npx edgebase seed
npx edgebase seed --file data/test-seed.json
npx edgebase seed --reset
OptionDescription
--file <path>Path to seed data file (default: edgebase.seed.json)
--url <url>Dev server URL (default: http://localhost:8787)
--resetDelete existing data before seeding
--service-key <key>Service Key for authenticated requests

export

Export table data as JSON:

# Export a table to a file
npx edgebase export --table posts --url <URL> --service-key <KEY>

# Custom output path
npx edgebase export --table posts --output my-data.json
OptionDescription
--table <name>(Required) Table to export
--format <type>Export format (json only, default: json)
--url <url>Worker URL (or EDGEBASE_URL env)
--service-key <key>Service Key (or EDGEBASE_SERVICE_KEY env)
--output <path>Output file path (default: <table>-export.json)

Behavior notes:

  • Dynamic DB blocks (user:{id}, workspace:{id} etc.) — automatically discovers all DO instances and merges their data into a single JSON array
  • View tables — returns an empty array with X-EdgeBase-Notice header indicating the source table should be exported instead
  • Grouped tables — correctly routes to the group DO and extracts only the requested table

Secrets & Keys

secret

Manage Cloudflare Worker secrets:

npx edgebase secret set JWT_USER_SECRET
# Prompts for value via stdin (wraps `wrangler secret put`)
npx edgebase secret list
npx edgebase secret delete JWT_USER_SECRET

keys

Manage Service Keys and JWT signing secrets:

These are the same Service Keys used by all Admin SDKs.

npx edgebase keys list
npx edgebase keys rotate
npx edgebase keys rotate-jwt
SubcommandDescription
listShow current Service Key (masked) with created/updated timestamps
rotateRotate Service Key immediately
rotate-jwtRotate JWT signing secrets (JWT_USER_SECRET + JWT_ADMIN_SECRET) with 28-day grace period

JWT Key Rotation (rotate-jwt):

Rotates both JWT_USER_SECRET (user tokens) and JWT_ADMIN_SECRET (admin tokens) simultaneously. The old secrets are preserved as JWT_USER_SECRET_OLD and JWT_ADMIN_SECRET_OLD with a 28-day grace period — matching the Refresh Token TTL so no users are logged out during rotation.

npx edgebase keys rotate-jwt
# → Saves old secrets as JWT_USER_SECRET_OLD / JWT_ADMIN_SECRET_OLD
# → Sets new JWT_USER_SECRET / JWT_ADMIN_SECRET
# → Updates .edgebase/secrets.json
npx edgebase deploy # Required: redeploy to activate new secrets
note

Access Tokens (15m TTL) expire naturally after rotation — no grace period needed. Only Refresh Tokens require the 28-day grace period.

Key data is stored in .edgebase/secrets.json (chmod 0o600).

Admin

admin

Admin account management:

npx edgebase admin reset-password
OptionDescription
--url <url>Worker URL (default: http://localhost:8787)
--service-key <key>Service Key (or EDGEBASE_SERVICE_KEY env)

Prompts interactively for admin email and new password (min 8 characters).

Admin password recovery is CLI-based and expects a configured root Service Key in config.serviceKeys using the canonical secretRef: 'SERVICE_KEY'.

For local development, make sure SERVICE_KEY=... is available to the Worker, typically through .dev.vars, .env.development, or wrangler dev --var SERVICE_KEY:....

Plugins

plugins

Manage installed plugins:

# List installed plugins, manifest metadata, and config templates
npx edgebase plugins list

# Remove namespaced data for a removed plugin
npx edgebase plugins cleanup <prefix>
npx edgebase plugins cleanup <prefix> --account-id <CF_ID> --api-token <CF_TOKEN>
SubcommandDescription
listShow configured plugins with manifest metadata, plugin API version, tables/functions/hooks, and configTemplate
cleanup <prefix>Remove namespaced plugin tables and plugin migration metadata for a removed plugin

plugins cleanup options:

FlagDescription
--url <url>Worker URL (or EDGEBASE_URL env)
--service-key <key>Service Key (or EDGEBASE_SERVICE_KEY env)
--account-id <id>Cloudflare Account ID for dynamic DO enumeration
--api-token <token>Cloudflare API Token for dynamic DO enumeration
-y, --yesSkip confirmation prompt

plugins cleanup refuses to run if the plugin is still configured in edgebase.config.ts. It removes namespaced plugin tables plus plugin migration metadata stored in CONTROL_DB. On Cloudflare Edge, pass --account-id and --api-token when the plugin may have written to dynamic Durable Object instances; otherwise the CLI can only clean currently known namespaces and metadata.

create-plugin

Scaffold a new EdgeBase plugin project with server-side and optional client-side boilerplate:

npx edgebase create-plugin <name>
npx edgebase create-plugin my-plugin
npx edgebase create-plugin @myorg/analytics-plugin
npx edgebase create-plugin my-plugin --with-client js
npx edgebase create-plugin my-plugin --with-client all
OptionDescription
<name>(Required) Plugin name (e.g., my-plugin or @scope/plugin-name)
--with-client [langs]Include client SDK scaffolding (js, or all)
--forceOverwrite existing files

Generated structure:

my-plugin/
server/
src/index.ts # Plugin definition (tables, functions, hooks)
package.json
tsconfig.json
client/js/ # Only with --with-client
src/index.ts
package.json
tsconfig.json
README.md

The generated server template uses:

  • manifest for CLI-facing metadata such as description, docsUrl, and configTemplate
  • automatic pluginApiVersion stamping through definePlugin()
  • access + handlers as the preferred config grammar for plugin tables
  • optional trigger.path for clean public HTTP routes

The generated server/src/index.ts uses definePlugin() from @edgebase/plugin-core to declare tables, functions, and hooks. Existing files are skipped by default unless --force is used.

Next steps after scaffolding:

cd my-plugin/server && npm install
# Edit server/src/index.ts to define your tables, functions, and hooks
npm run build
# In your EdgeBase project:
npm install ../my-plugin/server
# Import the plugin in edgebase.config.ts and add it to config.plugins
npx edgebase deploy

webhook-test

Send test webhook events to a local development server. Useful for testing payment or plugin webhook handlers without relying on external services like Stripe CLI:

npx edgebase webhook-test [provider]
npx edgebase webhook-test stripe
npx edgebase webhook-test stripe --all
npx edgebase webhook-test stripe --event checkout.session.completed
npx edgebase webhook-test stripe --url http://localhost:8787/api/functions/my-handler/webhook
OptionDescription
[provider]Provider to simulate (default: stripe)
-u, --url <url>Target webhook URL (default: http://localhost:8787/api/functions/plugin-stripe/webhook)
-e, --event <type>Send a specific event type only
-a, --allSend all test events for the provider

Available Stripe test events:

Event TypeDescription
checkout.session.completedCheckout completed (sent by default)
customer.subscription.updatedSubscription created/updated
customer.subscription.deletedSubscription canceled
invoice.payment_succeededInvoice payment succeeded

If no --event or --all flag is provided, only the first event (checkout.session.completed) is sent. Each event generates a unique evt_test_* ID with realistic test data.

Self-Hosting

docker

Docker-based self-hosting commands:

# Build EdgeBase Docker image
npx edgebase docker build
npx edgebase docker build --tag myorg/edgebase:v1.0

# Run EdgeBase in a Docker container
npx edgebase docker run
npx edgebase docker run --port 3000 --detach

Build options:

OptionDescription
-t, --tag <tag>Image tag (default: edgebase:latest)
--no-cacheBuild without cache

Run options:

OptionDescription
-t, --tag <tag>Image tag (default: edgebase:latest)
-p, --port <port>Host port (default: 8787)
-v, --volume <name>Data volume name (default: edgebase-data)
-d, --detachRun in background
--name <name>Container name (default: edgebase)
--env-file <path>Path to environment variables file

Environment Variables

File Strategy

EdgeBase uses a dual-file strategy to separate development and production secrets:

FilePurposeGitUsed by
.env.developmentLocal dev secrets (Stripe test keys, etc.)Ignorednpx edgebase dev
.env.releaseProduction secrets (Stripe live keys, etc.)Ignorednpx edgebase deploy
.env.development.exampleTemplate — shows required variablesCommitted
.env.release.exampleTemplate — shows required variablesCommitted

Getting started:

# After `npx edgebase init`, secrets are ready for dev:
npx edgebase dev # reads .env.development (auto-generated with JWT keys)

# For production, copy the example and fill in real keys:
cp .env.release.example .env.release
# Edit .env.release with production secrets
npx edgebase deploy # auto-uploads .env.release to Cloudflare

Variable Reference

VariableDescriptionDefault
PORTDev server port8787
JWT_USER_SECRETUser JWT signing secretAuto-generated by init
JWT_USER_SECRET_OLDPrevious user JWT secret (28d grace period after rotate-jwt)
JWT_USER_SECRET_OLD_ATISO 8601 timestamp of last user JWT rotation
JWT_ADMIN_SECRETAdmin JWT signing secretAuto-generated by init
JWT_ADMIN_SECRET_OLDPrevious admin JWT secret (28d grace period after rotate-jwt)
JWT_ADMIN_SECRET_OLD_ATISO 8601 timestamp of last admin JWT rotation
SERVICE_KEYAdmin service keyAuto-generated on first deploy
EDGEBASE_URLWorker URL for CLI commands
EDGEBASE_SERVICE_KEYService Key for CLI commands

Example .env.development

# Auto-generated by `npx edgebase init`
JWT_USER_SECRET=a1b2c3... (64-char hex)
JWT_ADMIN_SECRET=d4e5f6... (64-char hex)

# Add your development API keys below:
# STRIPE_SECRET_KEY=sk_test_...
# EMAIL_API_KEY=re_test_...

Example .env.release

# Production secrets — uploaded to Cloudflare on deploy
JWT_USER_SECRET=<production-secret>
JWT_ADMIN_SECRET=<production-secret>

# STRIPE_SECRET_KEY=sk_live_...
# EMAIL_API_KEY=re_...