Supabase CLI cheat sheet

Status: 🟩 COMPLETE (🟦 LIVING — Supabase CLI evolves with the platform) Last updated: 2026-06-21 Plain-English tagline: Daily-use Supabase CLI commands grouped by intent. For the why, read Supabase.


Setup (once per machine)

npm install -g supabase                  # install globally (or use as devDep + npx)
supabase --version                       # verify
supabase login                           # interactive browser auth

Per-project:

supabase init                            # creates supabase/ folder in your project
supabase link --project-ref <ref>        # link to your hosted Supabase project

Find your project ref in the Supabase dashboard URL: app.supabase.com/project/<ref>.


Run Supabase locally (Docker required)

supabase start                           # spin up local Postgres + Auth + Storage + Studio
supabase stop                            # tear it down
supabase status                          # what's running, on which ports
supabase db reset                        # rebuild local DB from migrations + seeds

After supabase start:

  • Studio: http://localhost:54323
  • API: http://localhost:54321
  • DB: postgresql://postgres:postgres@localhost:54322/postgres

Migrations

supabase migration new add_users_table   # create a new migration file (timestamped)
supabase migration list                  # list applied + pending migrations
supabase db push                         # apply pending migrations to the LINKED remote
supabase db pull                         # generate a migration from remote schema diff
supabase db reset                        # rebuild LOCAL from scratch (uses all migrations)

The Bible Quest project’s migrations live in supabase/migrations/ (e.g. 20260507_001_initial_schema.sql). Naming pattern: YYYYMMDD_NNN_description.sql.


Type generation (TypeScript)

supabase gen types typescript --linked > lib/database.types.ts          # types from linked project
supabase gen types typescript --local  > lib/database.types.ts          # types from local DB
supabase gen types typescript --project-id <ref> > lib/database.types.ts # types from any project

Then in code:

import { Database } from "@/lib/database.types";
const supabase = createClient<Database>(...);
// Now table/column names autocomplete and type-check

Re-run after every migration. Many teams add this to npm run build:types and run it in CI.


Functions (Edge Functions)

supabase functions new my-function                       # scaffold a function
supabase functions serve                                 # run all functions locally
supabase functions serve my-function --no-verify-jwt     # run one, skip auth (dev)
supabase functions deploy my-function                    # deploy to remote
supabase functions deploy my-function --no-verify-jwt    # deploy without JWT enforcement
supabase functions delete my-function                    # remove from remote

Edge functions live in supabase/functions/<name>/index.ts. Written in Deno-flavored TypeScript.


Secrets (for Edge Functions)

supabase secrets list                              # what's set
supabase secrets set MY_KEY=value                  # set one
supabase secrets set --env-file ./.env.functions   # bulk-set from file
supabase secrets unset MY_KEY                      # remove

These are separate from your database env vars — they’re specifically for Edge Functions to access.


Storage

supabase storage cp ./photo.jpg ss:///bucket-name/photo.jpg     # upload
supabase storage cp ss:///bucket-name/photo.jpg ./photo.jpg     # download
supabase storage ls ss:///bucket-name                           # list
supabase storage rm ss:///bucket-name/photo.jpg                 # delete

Most app code uses the SDK (supabase.storage.from("bucket")); the CLI is for quick local file management.


Inspecting the linked project

supabase projects list                   # all projects in your account
supabase projects api-keys --project-ref <ref>  # get URL + anon + service_role keys
supabase db dump --linked                # dump remote DB to local file
supabase db dump --linked --data-only    # data only, no schema

supabase db dump is great for backups before risky operations.


Common workflows

Start a fresh project locally

supabase init                            # creates supabase/ folder
supabase start                           # spin up local stack
# Visit http://localhost:54323 for Studio

Add a new table

supabase migration new add_posts_table
# Edit supabase/migrations/<timestamp>_add_posts_table.sql
# (write your CREATE TABLE statement)
supabase db reset                        # apply to local
# (test locally)
supabase db push                         # apply to linked remote
supabase gen types typescript --linked > lib/database.types.ts  # refresh types

Reset local to match remote

supabase db pull                         # generate diff migration
supabase db reset                        # rebuild local from migrations

Move env vars across environments

# (Vercel side)
vercel env pull .env.local               # pull production env to .env.local
 
# (Supabase side — set secrets for Edge Functions)
supabase secrets set --env-file .env.local

Common gotchas

  • supabase start needs Docker. Make sure Docker Desktop is running on Windows/macOS.
  • Ports conflict. Default ports (54321, 54322, 54323) often clash with other dev tools. supabase status shows what’s bound; supabase stop cleans up.
  • supabase db push applies migrations to the LINKED REMOTE. Triple-check supabase status shows the right project before pushing.
  • supabase db reset wipes local data. Local seed data gets reloaded from supabase/seed.sql (if present). Remote data is untouched.
  • Generated types fall out of sync. Re-run supabase gen types after every migration, or types in your app start lying.
  • --no-verify-jwt for functions disables auth. Useful in dev; never deploy a function with --no-verify-jwt in production unless it’s intentionally public.
  • GRANTs aren’t generated by supabase db pull. If you ran raw SQL to grant privileges (the Bible Quest 20260507_002_grant_role_privileges.sql pattern), you may need to re-apply manually.
  • CLI version drift. If a command behaves unexpectedly: npm install -g supabase@latest.
  • db push won’t apply migrations already in the remote’s migration history. If a migration ran via the SQL Editor manually, the CLI won’t see it as “applied” — you may need supabase migration repair to sync.
  • Linked project URL contains the project ref. https://<ref>.supabase.co — the <ref> is what --project-ref expects.

See also


Sources