diff command is the primary workflow entry point in supaschema. It compares a before-state (your live database or a git ref) against an after-state (your declarative schema directory) and renders an idempotent, replay-safe SQL migration. By default it writes the migration to supabase/migrations/TIMESTAMP_name.sql and then refreshes your TypeScript types automatically. You can redirect output to stdout, preview without writing, or run continuously in watch mode.
Default Behavior
When you runnpx supaschema diff with no flags, supaschema:
- Reads
--fromfrom your live local database (orgit:HEADwhen no database connection is configured). - Reads
--tofromdir:supabase/schemas. - Writes the resulting migration to
supabase/migrations/<TIMESTAMP>_migration.sql. - Refreshes TypeScript types from the updated schema.
0 and writes no file.
TypeScript type generation runs automatically after every successful migration write. Pass
--dry-run or --out stdout to skip the write step and suppress type generation.Examples
Flags
The before-state source to diff against. Accepts a database URL, a
git:<ref> specifier (e.g. git:HEAD, git:origin/main), or a dir:<path> pointing to a schema directory. Defaults to your live local database, falling back to git:HEAD when no database is reachable.The after-state source representing the desired schema. Accepts the same specifiers as
--from. Defaults to dir:supabase/schemas.Where to write the rendered SQL. Pass a file path to override the default timestamped filename, or pass
stdout to print directly to standard output without touching the filesystem. Using --out stdout skips TypeScript type generation.Overrides the descriptive segment of the generated migration filename. For example,
--name add_accounts produces 20240101000000_add_accounts.sql. Has no effect when --out is set to stdout or an explicit path.Overrides the directory where migrations are written. Defaults to
supabase/migrations. Useful when your project layout differs from the Supabase convention.A comma-separated list of PostgreSQL schema names to include in the diff. When omitted, all schemas tracked by your configuration are diffed. Example:
--schema public,auth.Renders the SQL plan and prints it without writing any file. Combine with
--summary to get a human-readable operation count alongside the SQL.Outputs a structured JSON payload instead of raw SQL. The payload includes the rendered SQL, the operation list, and any diagnostics. Useful for programmatic consumption in custom CI scripts.
Exits with code
3 when the computed plan contains at least one operation. Use this as a drift gate in CI: your pipeline fails if the live database has diverged from the declared schema.Skips the migration lineage chain gate. By default, supaschema verifies that the new migration’s parent hash matches the tip of the existing chain. Pass this flag when you intentionally operate outside normal linear history (e.g. merging a squashed migration).
Prints a human-readable summary of operations and diagnostics after rendering the SQL. Shows counts of creates, alters, drops, and any warnings.
Path where supaschema writes the gated destructive object keys as a
hints.destructive skeleton for review. When the plan contains blocked destructive operations (e.g. a column drop), this file lists each object key so you can explicitly approve them before supaschema will write the real migration. The file is never overwritten if it already exists.Prints per-phase timing information to
stderr after the command completes. Useful for profiling slow diffs on large schemas.Re-runs the diff automatically whenever files in the
dir: source change. Implies --dry-run and --summary — watch mode never writes migration files. Press Ctrl+C to stop. Intended for tight feedback loops during schema authoring.Suppresses all non-essential output, including progress spinners and informational messages. Errors and the migration SQL itself are still emitted.
Path to a supaschema config file. Defaults to
supaschema.config.ts (or .js / .json) in the current working directory.Selects a named environment block from your config file (e.g.
--env staging). Named environments let you store per-environment database URLs and schema paths in one config without repeating flags.Source Specifiers
The--from and --to flags accept the following source formats:
| Format | Example | Description |
|---|---|---|
| Database URL | postgresql://user:pass@host/db | Live database introspection |
git:<ref> | git:HEAD, git:origin/main | Schema files at a git ref |
dir:<path> | dir:supabase/schemas | Schema files on disk |
Exit Codes
| Code | Meaning |
|---|---|
0 | Success — migration written (or nothing to migrate) |
1 | Error — command failed to complete |
2 | Diagnostics errors — static analysis found blocking issues |
3 | --fail-on-diff triggered — plan was non-empty |
CI Integration
Use--fail-on-diff to gate merges on schema drift:
--json to consume the plan in downstream pipeline steps: