Skip to content

CLI reference

Short, wrangler-consistent verbs. Every command below accepts --help.

Scaffold a new app. In a terminal it asks where the app will run, where uploaded files go, then for the theme, the sign-in methods and the social providers; flags answer those questions up front, and --yes skips any left unanswered.

Flag
--stack <name> next (default) or cloudflare (Choosing a stack)
--storage <provider> Where uploads go: r2 (default), disk (Next.js only), cloudinary or uploadthing (Storage providers)
--signup <mode> Who may create an account: open (default), invite or closed (Who may sign up)
--theme <name> default, coral, amber, sky, mono or emerald (Themes)
--auth <list> Sign-in methods: magic-link, email-otp, passkeys, 2fa-app, 2fa-email, or all (default) / none
--auth-providers <list> Social sign-in: google, github, apple, microsoft
-y, --yes Don’t ask; use the flags given and defaults for the rest
--pm <manager> pnpm, npm, yarn, or bun (default: detected)
--skip-install Write files without installing dependencies
Terminal window
npx @flaredev/cli create shop
npx @flaredev/cli create shop --stack next
npx @flaredev/cli create shop --theme mono --auth passkeys,2fa-app --auth-providers google,github --yes

The stack is chosen once and recorded in package.json. There is no command that moves an app from one to the other: the descriptors, validators, policies and dashboard are the same either way, but the schema, migrations and deployment aren’t.

List the themes (the current one marked), or switch the app to one by rewriting lib/site.ts. Restart flare dev to see it.

Terminal window
npx flare theme mono

Generate (or update) a resource — see what it emits and the field grammar.

Flag
--fields <fields> e.g. "name:string, email:string!, status:enum(lead,customer)"
--force Overwrite a hand-edited generated block
Terminal window
npx flare gen resource Contact --fields 'name:string, email:string!, company:belongsTo(Company)?'

The resource comes first, positionally. There is no --resource flag.

An endpoint of your own beside the generated CRUD routes, with the session check, the policy check and the store already wired. No generated block: the file is yours.

Terminal window
npx flare gen endpoint Order publish --method POST --record
Flag
--method <verb> GET (default), POST, PATCH, PUT, DELETE
--action <action> Policy action to require (default: read for GET, update otherwise)
--record Put it under one record: /api/orders/[id]/<name>

Scaffold a migration by hand, or diff the current schema.

Flag
--from-schema Diff current tables instead of writing a blank migration. On Next.js it also turns a rename in a descriptor into an ALTER TABLE … RENAME COLUMN; without it Prisma emits a drop and an add, and the data goes with them
Terminal window
npx flare gen migration backfill_contact_status
npx flare gen migration add_phone_to_contacts --from-schema

Write (or update) a resource-level policy.

Flag
--roles <roles> Roles allowed to read, create, and update, e.g. admin,staff
--delete-roles <roles> Roles allowed to delete (default: the first --roles entry)
--force Overwrite a hand-edited roles block
Terminal window
npx flare gen policy Invoice --roles admin,staff --delete-roles admin

Add Stripe billing: the Plan, Customer and Purchase resources, their policies, Checkout, the Customer Portal, the webhook, and /dashboard/billing.

Flag
--provider <provider> Payment provider. Only stripe is supported.
--mode <mode> Only subscriptions, which also covers one-time checkout
--force Overwrite hand-edited generated blocks, including a hand-edited Customer fields block
--skip-install Write the files without installing the stripe dependency
--skip-migration Skip generating the migration
Terminal window
npx flare gen billing --provider stripe --mode subscriptions

Add security: security.config.ts, the SecurityEvent resource and policy, the request guard in lib/security.ts, the /dashboard/security dashboard, and the KV, Durable Object and rate-limit bindings in wrangler.jsonc.

Flag
--force Overwrite hand-edited generated blocks
--skip-migration Skip generating the migration
Terminal window
npx flare gen security

Mirror this app’s Stripe Products (those with metadata flare_app=<package name>) and their active prices into the Plan table. Deactivate plans whose price is gone. Configure the Customer Portal to allow switching between the synced plans.

Flag
--remote Write to the deployed database
--env <name> Wrangler environment
--all Import every active Product, not only this app’s
Terminal window
npx flare billing:sync-plans --remote

Remove a resource’s generated files. Refuses on hand-written code outside generated blocks, or while another resource still references it — see the codegen overwrite contract.

Flag
--force Delete even when files contain hand-written code
Terminal window
npx flare rm resource Tag

Register an additional role users can be assigned. admin and staff are seeded by the initial migration.

Flag
--label <label> Display label (default: humanized name)
--remote Target the deployed database
--env <name> Wrangler environment
Terminal window
npx flare role:add support --label "Customer support"

Set a user’s role — e.g. make the first admin. Refuses an unregistered role name.

Flag
--remote Target the deployed database
--env <name> Wrangler environment
Terminal window
npx flare user:role you@example.com admin --remote

Make the database match the schema. On Cloudflare, apply pending D1 migrations. On Next.js, prisma migrate dev — diff the schema, write a migration if one is needed, apply it — then prisma generate, because Prisma 7 no longer regenerates the client from migrate dev and a stale client fails the next command. You never run a prisma command yourself.

Terminal window
npx flare migrate # local; writes a migration if the schema changed
npx flare migrate --name init # same, without Prisma asking for a name
npx flare migrate --deploy # CI/production: apply committed migrations, invent nothing
Flag
--name <name> Next.js: name the migration up front
--deploy Next.js: prisma migrate deploy — committed migrations only

On Cloudflare it is D1 (local by default — shared state with flare dev/flare start).

Flag
--remote Target the deployed database
--env <name> Wrangler environment
--database <binding> Which D1 binding, when the app has more than one

Undo the most recently applied migrations — see migrations & seeds for exactly how downs are resolved.

Flag
--steps <n> How many migrations to roll back (default 1)
--remote Target the deployed database (requires --yes)
--yes Confirm a remote rollback
--env <name> Wrangler environment
--database <binding> Which D1 binding

Run seed files from seeds/ against the local D1 database.

Terminal window
npx flare seed # every seed, file-name order
npx flare seed contacts # just seeds/contacts.seed.ts

Fill a resource’s table with sample rows built from its descriptor. About 14,000 rows a second locally on Cloudflare.

Terminal window
npx flare seed:resource Contact --count 1000
npx flare seed:resource Contact 1m
npx flare seed:resource Contact 5k --remote --yes # Cloudflare

Both stacks, by different routes. Cloudflare writes SQL straight at D1. Next.js goes through the app’s own Prisma client, because that is the only thing that knows how this schema maps to Postgres — a multiselect is a real text[], a json field is jsonb, and an enum is a Postgres enum whose member identifier is not always the value in the column.

A belongsTo field points at rows that already exist, so seed the parent first; the command says which one is empty rather than failing partway.

Flag
--count <rows> 1000, 25k, 1m (default 25)
--truncate Delete the table’s rows first
--seed <number> Same number, same rows
--remote Cloudflare: the deployed database (requires --yes). On Next.js there is no second database — DATABASE_URL is whichever one you point it at
--database <binding> D1 binding, when the app has several (Cloudflare)
--env <name> Wrangler environment (Cloudflare)

Copy rows from your local database to the deployed one. Seeds run locally, so the first deploy leaves a gap: the catalogue, the price list, the countries table — the reference data the app needs before anyone can use it — exists on your machine and nowhere else. This sends it up.

It only writes to the remote database. Nothing is read back, and nothing local changes.

Terminal window
npx flare db:push categories products --yes
npx flare db:push countries --truncate --yes
Flag
--yes Required: this writes to production
--truncate Delete each table’s remote rows first
--database <binding> D1 binding, when the app has several
--env <name> Wrangler environment

Create seeds/<name>.seed.ts, with example rows if the name matches a resource.

Flag
--resource <name> Write example rows for this resource explicitly

What differs between this app’s copies of Flare’s code and the version the installed CLI ships.

Terminal window
npx flare diff
npx flare diff store # only paths containing "store"

The code under lib/ and components/ is copied into your app rather than imported, so a fix in a later release doesn’t arrive on its own. This says what has changed, per file, with your lines as - and Flare’s as +. A file Flare ships that your app doesn’t have is listed as missing.

It reads; it never writes.

Replace this app’s copies with the version the installed CLI ships.

Terminal window
npx flare update # lists what would change, and stops
npx flare update --yes # applies it
Flag
-y, --yes Apply. Without it the command only lists what it would overwrite

This discards your edits to the files it touches. Run flare diff first. Without --yes nothing is written, which is deliberate: quietly overwriting someone’s changes is the one failure this design can’t afford.

A filter narrows it to one file, so you can take an upstream fix to store.ts while keeping your own query.ts.

Regenerate every derived file from the descriptors and report drift — see drift & sync-types.

Flag
--check Change nothing; exit 1 if anything is out of sync (CI)
--force Overwrite generated blocks that were edited by hand

Seed the development admin account: admin@example.com / Password, role admin — the same account every new app’s docs and dashboard name. Safe to run again after a database reset: an existing account is left alone.

Terminal window
npx flare db:seed

It goes through the same path as flare user:add, so the account is indistinguishable from one made through the sign-up form. Replace it before the app is anywhere but your machine.

Create an account from the command line — the way in when sign-up is closed.

Terminal window
npx flare user:add ada@example.com --role admin
Flag
--role <role> Role to give them; checked against the registered roles
--password <password> Their password (generated and printed when omitted)
--name <name> Display name (default: the part before the @)
--remote Against the deployed database rather than the local one
--env <name> Wrangler environment
--skip-existing Succeed quietly if that account is already there

It writes the same two rows a sign-up writes, so the account behaves like any other. --skip-existing is what makes it safe in a seed: a new app’s pnpm db:seed is this command, and it has to survive being run again after someone resets their database. The generated password is printed once and stored only as a hash. See who may sign up.

The things that are usually wrong, before anything runs. The first thing to try when something does not work.

Terminal window
npx flare doctor
✔ Node v22.14.0
✔ Package manager pnpm 10.4.1 (pnpm-lock.yaml).
✔ Stack Cloudflare (vinext, D1, Drizzle).
✔ Flare version app and CLI are both 0.12.0.
✔ Environment .dev.vars has every key .dev.vars.example lists.
✔ Bindings D1 and R2 are both bound.
✔ Descriptors 4 resources load cleanly.
! Policies Payment has no policy, so any signed-in user can read and write it.
→ flare gen policy <Name> --roles admin
✖ Migrations 1 not applied locally: 0005_create_gadgets.sql.
→ flare migrate
1 problem, 1 warning.
What it checks
Node The major version, against the minimum Workers and Next 16 both need
Package manager Which lockfile the app has, and whether that manager is installed
Stack Cloudflare or Next.js, so the rest of the output makes sense
Flare version The app’s @flaredev/core against this CLI
Prisma Next.js only: that prisma, @prisma/client and @prisma/adapter-pg are all on the same Prisma 7 — prisma@latest is an 8.0 release candidate
Environment Keys .dev.vars.example (or .env.example) lists that the real file lacks, and a required secret left empty
Bindings D1 and R2 on Cloudflare; DATABASE_URL on Next.js
Descriptors That every resource descriptor loads
Generated files Files out of date, and generated blocks edited by hand
Rate limits Limits a descriptor declares, and whether anything is configured to count them
Policies Resources with no policy, which any signed-in user can read and write
Renames A rename declared in a descriptor with no migration for it yet
Migrations Migration files on disk against the ones the local database has run
Flag
--offline Skip the checks that ask the database

Three things worth knowing. It changes nothing, so it is safe on production config and safe when the app is already broken — the only time anybody runs it. A check that cannot run says so (–) rather than passing, because “cannot tell” and “fine” are different answers. And the exit code is 1 only for a ✖, so CI can run it without failing on a warning you have decided to live with.

Share a local server on a public https://*.trycloudflare.com URL through a Cloudflare Quick Tunnel. No account is needed. The target defaults to http://localhost:3000. See Sharing your local app.

Terminal window
npx flare tunnel 8787

These forward straight through to the app’s own installs, so the four verbs are the same on both stacks even though what they run isn’t. Anything after the command name is passed on unchanged.

On Cloudflare — see deploying to Cloudflare for what deploy adds on top:

Command Runs
flare dev vinext dev
flare build vinext build
flare start wrangler dev --config dist/server/wrangler.json --persist-to .wrangler/state (runs flare build first if there’s no build yet)
flare deploy Migrations → vinext-cloudflare deploy → secrets → zone security rules

On Next.js — see deploying to Vercel:

Command Runs
flare dev next dev
flare build prisma generate, then next build
flare start next start (runs flare build first if there’s no build yet)
flare deploy vercel deploy --prod

The Next.js deploy does nothing besides run the CLI: migrations, secrets and domains all belong to the Vercel project rather than to Flare. Migrations are flare migrate against the production DATABASE_URL, run deliberately.

flare dev and flare start also accept --tunnel on either stack, which shares the running server on a public URL (Sharing your local app).

flare deploy on Cloudflare additionally accepts --skip-migrations, --skip-secrets, --skip-security, --env <name>, and --preview (shorthand for --env preview). On Next.js, the Vercel CLI’s own flags work instead — --yes, --scope <team>, and so on.

On either stack, flare deploy first names any resource with no policy, since that resource is readable and writable by any signed-in user. It warns rather than refuses; --allow-open silences it (Deployment).