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:
| File | Description |
|---|---|
edgebase.config.ts | DB blocks, access rules, auth settings |
functions/onPostCreated.ts | Example app function |
.env.development | Local dev secrets (JWT keys auto-generated, git-ignored) |
.env.development.example | Template showing required env vars (committed) |
.env.release.example | Template for production env vars (committed) |
.gitignore | Ignores .env.development, .env.release, node_modules, etc. |
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 bulk — before the actual deployment.
.env.release → wrangler secret bulk → Cloudflare Workers Secrets → c.env.*
| Behavior | Detail |
|---|---|
SERVICE_KEY | Excluded from upload (auto-managed by deploy pipeline) |
.env.release missing | Silently skipped — no error, no warning |
| Manual secrets | Still works: npx edgebase secret set KEY is unaffected |
Deploy pipeline order:
- Cloudflare authentication (auto-login if needed)
- Config validation
.env.release→ Cloudflare Secrets (automatic)- Turnstile provisioning (if
captcha: true) - KV / D1 / Vectorize provisioning
wrangler deploy- URL summary output
For non-interactive environments (GitHub Actions, etc.), set CLOUDFLARE_API_TOKEN as an environment variable. The auto-login flow only activates in interactive terminals.
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
neonctlauth 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.developmentand.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
| Option | Description |
|---|---|
--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:
| Flag | Description |
|---|---|
--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-secrets | Include JWT/Service Key in backup |
--include-storage | Include R2 files (outputs .tar.gz) |
--account-id <id> | Cloudflare Account ID (Edge only) |
--api-token <token> | Cloudflare API Token (Edge only) |
Restore options:
| Flag | Description |
|---|---|
--from <path> | Path to backup file (.json or .tar.gz) |
--url <url> | Target Worker URL |
--service-key <key> | Target Service Key |
--yes | Skip confirmation prompt |
--skip-secrets | Don't restore secrets |
--skip-storage | Don'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
| Option | Description |
|---|---|
-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
| Option | Description |
|---|---|
--file <path> | Path to seed data file (default: edgebase.seed.json) |
--url <url> | Dev server URL (default: http://localhost:8787) |
--reset | Delete 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
| Option | Description |
|---|---|
--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-Noticeheader 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
| Subcommand | Description |
|---|---|
list | Show current Service Key (masked) with created/updated timestamps |
rotate | Rotate Service Key immediately |
rotate-jwt | Rotate 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
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
| Option | Description |
|---|---|
--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>
| Subcommand | Description |
|---|---|
list | Show 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:
| Flag | Description |
|---|---|
--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, --yes | Skip 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
| Option | Description |
|---|---|
<name> | (Required) Plugin name (e.g., my-plugin or @scope/plugin-name) |
--with-client [langs] | Include client SDK scaffolding (js, or all) |
--force | Overwrite 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:
manifestfor CLI-facing metadata such asdescription,docsUrl, andconfigTemplate- automatic
pluginApiVersionstamping throughdefinePlugin() access + handlersas the preferred config grammar for plugin tables- optional
trigger.pathfor 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
| Option | Description |
|---|---|
[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, --all | Send all test events for the provider |
Available Stripe test events:
| Event Type | Description |
|---|---|
checkout.session.completed | Checkout completed (sent by default) |
customer.subscription.updated | Subscription created/updated |
customer.subscription.deleted | Subscription canceled |
invoice.payment_succeeded | Invoice 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:
| Option | Description |
|---|---|
-t, --tag <tag> | Image tag (default: edgebase:latest) |
--no-cache | Build without cache |
Run options:
| Option | Description |
|---|---|
-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, --detach | Run 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:
| File | Purpose | Git | Used by |
|---|---|---|---|
.env.development | Local dev secrets (Stripe test keys, etc.) | Ignored | npx edgebase dev |
.env.release | Production secrets (Stripe live keys, etc.) | Ignored | npx edgebase deploy |
.env.development.example | Template — shows required variables | Committed | — |
.env.release.example | Template — shows required variables | Committed | — |
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
| Variable | Description | Default |
|---|---|---|
PORT | Dev server port | 8787 |
JWT_USER_SECRET | User JWT signing secret | Auto-generated by init |
JWT_USER_SECRET_OLD | Previous user JWT secret (28d grace period after rotate-jwt) | — |
JWT_USER_SECRET_OLD_AT | ISO 8601 timestamp of last user JWT rotation | — |
JWT_ADMIN_SECRET | Admin JWT signing secret | Auto-generated by init |
JWT_ADMIN_SECRET_OLD | Previous admin JWT secret (28d grace period after rotate-jwt) | — |
JWT_ADMIN_SECRET_OLD_AT | ISO 8601 timestamp of last admin JWT rotation | — |
SERVICE_KEY | Admin service key | Auto-generated on first deploy |
EDGEBASE_URL | Worker URL for CLI commands | — |
EDGEBASE_SERVICE_KEY | Service 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_...