How to Diff Against a Local Clone
Clone production, develop locally, then diff - without noise from the services a clone doesn't have.
npm install -g @akal/supaforge. A hosted dashboard is on the way - to hear when it opens.Cloning an Environment
supaforge clone copies a remote environment's database - schema and data, or schema only - into a local PostgreSQL database. It previews first; add --apply to run it, and --start-local to have SupaForge start a local PostgreSQL container with Podman or Docker.
supaforge clone --env=production --start-local --applyAfterwards the config's target points at the clone, so a plain diff --apply writes to your local copy rather than to the remote.
The Post-Clone Drift Problem
A clone is plain PostgreSQL. Several parts of a Supabase project live in services around the database, and a clone has none of them:
- storage - buckets and their policies.
- auth - the auth service's configuration.
- edge-functions - deployed functions.
- vault - Supabase Vault secrets.
- realtime - Realtime publications and channel policies.
- roles - Supabase's own roles and their grants.
Diffing a clone against the remote reports those checks as drift every time - not because anything is wrong, but because the clone can't hold them. What you want to track locally is the database: schema, RLS, reference data and so on.
Suppress for a Single Run with --skip
--skip (short: -x) leaves a check out of one run, and can be repeated:
supaforge diff --skip=storage --skip=auth --skip=edge-functions --skip=vault --skip=realtime --skip=rolesIt combines with every other flag:
supaforge diff --detail --skip=storage --skip=auth --skip=edge-functions --skip=vault --skip=realtime --skip=rolesMake It Permanent with checks.exclude
Add a checks.exclude array to supaforge.config.json and those checks are skipped on every run:
{
"environments": { ... },
"source": "local",
"target": "production",
"checks": {
"exclude": ["storage", "auth", "edge-functions", "vault", "realtime", "roles"]
}
}Excluded checks never appear in the output and never count towards the drift score. checks.exclude can also be set on one environment, where it applies whenever that environment is the target. Commit the config so every teammate and CI job uses the same list.
Pushing Local Changes Back
With the clone as the source, --apply makes the remote match the clone - including what the clone doesn't have. SupaForge notices when the source is a clone and says so, and it holds back anything destructive until you add --allow-destructive. Always look at the plan first:
supaforge clone --env=production --apply
# to push local work back, make the clone the "source" and production the "target",
# then make your changes locally: schema, RLS policies, reference data…supaforge diffsupaforge diff --apply --dry-runsupaforge diff --apply --proveFor changes you want reviewed and versioned, supaforge migrate create writes the drift to a migration file instead, and supaforge migrate run applies it.
Install
npm install -g @akal/supaforgeSummary
A clone has the database but not Supabase's services. Skip storage, auth, Edge Functions, Vault, Realtime and roles with --skip for one run, or with checks.exclude for good, and read the plan with --dry-run before pushing local changes to a shared environment.
Ready to try SupaForge?
Install the CLI and run your first diff in a minute. Nothing is changed until you add --apply.
npm install -g @akal/supaforge