CLI Reference
Every superwall command — create, dev, push, promote, publish — with flags, auth, and the checks that run before anything ships.
The CLI has git semantics on purpose: push saves, promote ships. Every push mints a sealed version; nothing users see changes until promote points production at it. This page is the command reference — Push, promote & publish explains the model.
superwall create # scaffold superwall/ inside your app
superwall dev # studio on http://localhost:6100
superwall push # build + version. Production untouched.
superwall promote # point production at the latest push
superwall publish # push + promote in one step
superwall publish -m "Q3 test" # record whyThe scaffolded package scripts mirror these (dev, push, promote, ship).
Auth
Run superwall login once interactively. In CI, set SUPERWALL_API_KEY (an sk_… key) — the project's .env is the usual home for it. dev needs no login.
superwall create
Scaffolds a complete project: the directory skeleton, a starter paywall, dependencies installed, your Superwall app connected, and a git init if needed.
| Flag | What it does |
|---|---|
--example <name> | Start from an example instead of the default starter. |
superwall dev
Hosts the studio for the project — or several at once with a glob (superwall dev examples/*). Regenerates superwall.d.ts first, so route and product types are always current.
| Flag | What it does |
|---|---|
--port, -p | Port, default 6100 — moves to the next free port if taken. |
--host | Bind address, for previewing from another device. |
Project problems (stray files in app/, duplicate routes) print as warnings here — the same ones that block a push, so fix them as they appear.
superwall push
Builds every paywall, versions the changed ones, and leaves production alone. Re-running with nothing changed is a no-op.
| Flag | What it does |
|---|---|
--id <id> | Limit to one paywall; repeatable. |
--rename <old>=<new> | Declare a directory rename so CI can resolve it. |
-m <note> | Record why, shown with the version in the dashboard. |
A push refuses — before anything is written — when:
- a selected paywall has diagnostics (publishing is immutable; fix first),
- a product in
config.tsdoesn't exist on the dashboard (every variable on it would be undefined on device), - a directory rename is unresolved (below).
The first push binds each paywall — creating it on Superwall if needed — and records the binding in superwall.lock; commit that file. After that, push always updates the same paywall; no IDs ever appear in your code.
Every push also snapshots your superwall/ source, so the dashboard can show and diff the code each version was built from. .env, node_modules/, and gitignored files never leave the machine.
Renames
Renaming a paywall directory is detected, never guessed. Interactively, push asks whether the unfamiliar directory is a rename (keeping the live paywall attached) or a new paywall. In CI, declare it — anything unresolved stops the push rather than creating a duplicate:
superwall push --rename plus-upgrade=pro-upgradeDeleting a paywall directory never blocks a push — the dashboard paywall keeps serving, and restoring the directory re-binds it.
superwall promote
Points production at a pushed version. Promote never rebuilds — it only moves the live pointer.
| Flag | What it does |
|---|---|
--id <id> | Limit to one paywall. |
--version, -v <n> | Pick a specific version (with a single --id) — which is also the rollback. |
superwall promote --id plus-upgrade --version 5
# → Rolled back version 7 → 5superwall publish
Push + promote in one step. Takes -m <note>. Also warns about other paywalls that are pushed-but-not-live, so nothing ships half-forgotten.
Before pushing: create the products
A push refuses if a config.ts names a product the dashboard doesn't have. The fix is a command away — the same CLI writes products directly:
superwall entitlements list --json # grab the NUMERIC entitlement id
superwall products create pro_3999_year \
--project <id> --app <id> \
--name "Annual" --price 39.99 --period year \
--trial-days 7 --entitlement <numeric-id> --json--entitlementtakes the numeric id (55688), not the identifier (pro) — the identifier fails with a decode error.- Pass
--projectexplicitly when your account has several, or the command errors with "Multiple projects found". --priceis major units (39.99);--periodisday|week|month|year;--trial-dayssets the intro offer.--dry-runconfirms the target before writing anything.
Two gates worth checking early
- Headless paywalls must be enabled on the application — otherwise every push fails with "Headless paywalls are not enabled for this application". It's a server-side feature flag; check with
superwall apps list --jsonand look forheadless_paywallsinfeatures_enabled. Contact us to have it turned on. - One broken surface blocks the whole push. A leftover scaffold aimed at a nonexistent product stops everything — push what you built with repeated
--idflags instead of touching unrelated directories.
For the full error-message-to-fix table, see Troubleshooting.
How is this guide?