> ## Documentation Index
> Fetch the complete documentation index at: https://supaschema.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Sources

> supaschema reads schemas from SQL files on disk, Git refs, SQL dump files, migration histories, saved catalog snapshots, or explicit live-database workflows. No Docker or shadow database required.

Every diff compares two schema sources:

* **from**: current state;
* **to**: desired state.

A source is any PostgreSQL schema representation that supaschema can parse into a SchemaModel.

Use the format `<prefix>:<location>`, such as `dir:database/schemas`.

The configured `migrationsDir` is always a planning input for source intent and lineage proof. A matching `migrations:<migrationsDir>` reference can also supply the generation before-state for migration-first adoption; migration replay is never a generation target. Existing reviewed migrations form the source-intent corpus for row backfills, explicit DML/`DO` workflows, enum rewrite recipes, Vault references, workload-proven index intent, and provider bootstrap constraints. Generated migration lineage in that same directory proves the current migration-tree baseline. supaschema should model that intent and verify that baseline before blocking; when the intent or baseline proof is absent, the diagnostic should tell an agent where to declare or pin it.

## Source reference

<CardGroup cols={3}>
  <Card title="Directory" icon="folder-open">
    **Syntax:** `dir:database/schemas`

    SQL files on disk. The default `--to` source for most commands. supaschema recursively reads every `.sql` file in the specified path.
  </Card>

  <Card title="Git snapshot" icon="code-branch">
    **Syntax:** `git:INDEX`, `git:HEAD`, `git:origin/main`, `git:abc1234`

    Schema in the staged index or at any committed Git ref. supaschema reads the `schemaPaths` files without touching your working tree.
  </Card>

  <Card title="Live database" icon="database">
    **Syntax:** `database:$DATABASE_URL`

    Read-only introspection of a live PostgreSQL connection. Use this for explicit inspect, verify, selfcheck, drift, target-safety, or catalog-snapshot workflows, not migration generation.
  </Card>
</CardGroup>

<CardGroup cols={3}>
  <Card title="SQL dump" icon="file-arrow-down">
    **Syntax:** `dump:path/to/schema.sql`, `dump:-`

    A single SQL file, or standard input (`-`). Useful for one-off analysis of `pg_dump` output.
  </Card>

  <Card title="Catalog snapshot" icon="camera">
    **Syntax:** `catalog:path/to/snapshot.json`

    A JSON file produced by `supaschema inspect`. Lets you compare against a saved point-in-time without a live database.
  </Card>

  <Card title="Empty baseline" icon="circle">
    **Syntax:** `empty:`

    A zero-object schema model. Useful for first migrations when there is no database and no valid Git baseline.
  </Card>
</CardGroup>

***

## `dir:` files

Use `dir:` for schema files on disk.

supaschema walks the directory, parses `.sql` files, and builds a SchemaModel from supported `CREATE` statements.

```bash theme={null}
supaschema diff --from git:HEAD --to dir:database/schemas
```

**When to use it:**

* Local development — your schema files live in the repository alongside your application code.
* Any command where the desired state is what you have currently checked out.

<Tip>
  You can specify multiple schema directories using the `schemaPaths` key in
  `supaschema.config.json` for project-wide defaults so you don't have to type
  the path on every command.
</Tip>

### Directory layout example

```text theme={null}
database/
└── schemas/
    ├── tables/
    │   ├── users.sql
    │   ├── orders.sql
    │   └── products.sql
    ├── functions/
    │   └── place_order.sql
    └── policies/
        └── orders_rls.sql
```

supaschema does not care about subdirectories or file names — it reads everything recursively and merges the results into one SchemaModel.

***

## `git:` refs

Use `git:` to read schema files from the staged index, a commit, branch, or tag.

It does not modify your working tree. It does not need a database connection.

```bash theme={null}
# Compare a new worktree edit with the staged schema closure
supaschema diff --from git:INDEX --to dir:database/schemas

# Compare the current working tree against the main branch
supaschema diff --from git:origin/main --to dir:database/schemas

# Compare two branches against each other
supaschema diff --from git:origin/main --to git:feature/add-subscriptions
```

**When to use it:**

* **Sequential local changes** — use `git:INDEX` as the proven before-state after `supaschema sync` stages a complete schema closure.
* **CI pull request checks** — generate the migration that would be produced by merging this branch, and fail the pipeline if it contains unreviewed destructive operations.
* **Release diffs** — quickly see what changed between two tagged versions.
* **Code review** — produce a human-readable SQL diff alongside the file diff in your PR.

<Note>
  supaschema resolves `git:` refs against the repository that contains your
  `schemaPaths`. The working directory must be inside a Git repository, and the
  ref must be reachable (fetched). For remote refs like `git:origin/main`, run
  `git fetch` first in your CI step.
</Note>

### CI pipeline example

```yaml theme={null}
# .github/workflows/migration-check.yml
- name: Check migration safety
  run: |
    supaschema diff \
      --from git:origin/main \
      --to dir:database/schemas \
      --dry-run \
      --fail-on-diff
```

***

## `database:` catalogs

Use `database:` to read a live PostgreSQL catalog.

supaschema queries system catalogs and builds a SchemaModel from what is deployed. It does not execute DDL against a `database:` source.

```bash theme={null}
# Generate a migration from live DB to your local schema files
supaschema diff \
  --from database:$DATABASE_URL \
  --to dir:database/schemas

# Detect drift: compare live DB against the last saved snapshot
supaschema diff \
  --from database:$DATABASE_URL \
  --to catalog:snapshots/last-deploy.json
```

**When to use it:**

* **Applied-state reconciliation** — you have an existing database and want a migration from what is deployed to your declarative files.
* **Drift detection** — check whether someone has made out-of-band changes directly on the server.
* **Generating a migration from scratch** — when you have no prior snapshot, the live database is the most authoritative "from" state.

<Warning>
  The `DATABASE_URL` you pass is used for introspection only. supaschema does
  not cache credentials or send them anywhere. However, treat this URL as a
  secret — pass it via environment variable rather than hard-coding it in
  scripts that end up in version control.
</Warning>

### Connection string formats

```bash theme={null}
# Standard PostgreSQL URL
database:postgresql://user:password@host:5432/dbname

# Supabase pooler URL (transaction mode)
database:postgresql://postgres.abcxyz:password@aws-0-us-east-1.pooler.supabase.com:6543/postgres

# Via environment variable
database:$DATABASE_URL
```

***

## `dump:` files

Use `dump:` for one SQL file, such as `pg_dump --schema-only` output.

Pass a file path or `-` for standard input.

```bash theme={null}
# Analyse a pg_dump file
supaschema diff \
  --from dump:backups/prod-schema-2024-06-01.sql \
  --to dir:database/schemas

# Pipe pg_dump directly
pg_dump --schema-only $PROD_URL | supaschema diff --from dump:- --to dir:database/schemas
```

**When to use it:**

* **One-off analysis** — you received a schema dump from a client or legacy system and want to diff it against your current declarative files.
* **Audit trails** — archive periodic `pg_dump` snapshots and compare them over time.
* **Offline workflows** — you have a dump but no live connection to the source database.

<Note>
  `dump:` sources are parsed through the same fail-closed extraction path as
  schema-tree SQL. Use a cleaned schema-only dump that omits `SET` statements,
  ownership comments, and other `pg_dump` preamble statements, or filter the
  dump before passing it to supaschema.
</Note>

***

## `migrations:` histories

Use `migrations:` when a project owns schema shape through reviewed migration files instead of a maintained declarative tree.

```bash theme={null}
npx supaschema types --from migrations:supabase/migrations

supaschema diff \
  --from migrations:supabase/migrations \
  --to dir:supabase/schemas
```

supaschema reads filename-sorted `.sql` files, replays supported DDL in memory, and emits a schema model without a database connection. The replay model is valid for `types --from` and as the `diff`/`plan`/`sync` before-state when it resolves to the configured `migrationsDir`. It is not a generation target, `verify` target, or drift target. A different migration directory fails with `SUPA_MIGRATION_BASELINE_UNSUPPORTED`; using replay as `--to` fails with `SUPA_SOURCE_MIGRATIONS_TARGET_UNSUPPORTED`.

Replaying the configured `migrationsDir` rebuilds the before-state from the whole corpus, so it is its own baseline proof. It stays valid whether or not generated lineage is present, and whether or not hand-authored migrations follow the newest generated migration. The lineage checks that produce `SUPA_MIGRATION_BASELINE_UNSUPPORTED` and `SUPA_MIGRATION_BASELINE_MISMATCH` apply to snapshot sources such as `git:`, `dir:`, `dump:`, and `catalog:`, which must match a recorded generated baseline.

Replay is fail-closed for shape-corrupting gaps. Missing directories, duplicate `CREATE` objects, absent non-optional `DROP` targets, absent non-ignored targets for supported `ALTER` statements, and absent enum neighbors raise `SUPA_REPLAY_ORDER_GAP` and return no objects. Unsupported top-level DDL, unsupported `ALTER TABLE` subtypes, unsupported `DROP` kinds, and unsupported rename targets raise `SUPA_REPLAY_UNSUPPORTED` and return no objects.

For policies, replay supports only definition changes expressed by `ALTER POLICY ... TO`, `USING`, and `WITH CHECK` in existing reviewed migrations. Omitted clauses retain their current definition. Policy renames remain unsupported; this boundary does not imply support for every `ALTER POLICY` form.

Replay skips configured managed or excluded schemas before planner input, so Supabase-managed history noise such as `auth` DDL can be omitted without emitting `unknown` shapes. Simple schema DDL inside idempotent `DO` blocks is replayed from the block body when it can be parsed; other data and control-plane statements remain outside the schema model.

Generated migration lineage uses `migration-baseline:<dir>@<version>` as a display label. That label is not a runtime source; `migrations:<dir>` is the runtime typegen input.

***

## `catalog:` snapshots

A catalog snapshot is JSON from `supaschema inspect`.

It captures a SchemaModel and fingerprint at one point in time.

```bash theme={null}
# Save a snapshot after a successful deployment
supaschema inspect --from database:$DATABASE_URL > snapshots/post-deploy.json

# Later: check if the live DB has drifted from that snapshot
supaschema diff \
  --from database:$DATABASE_URL \
  --to catalog:snapshots/post-deploy.json
```

**When to use it:**

* **Drift detection without a second live connection** — store the post-deploy snapshot in your repo and compare against it in CI instead of needing credentials to a second environment.
* **Reproducible comparisons** — a `catalog:` file is deterministic and version-controllable, unlike a live database connection.
* **Debugging** — share a `catalog:` file with a teammate so they can reproduce a diff locally without access to your database.

```json theme={null}
// snapshots/post-deploy.json (abbreviated)
{
  "fingerprint": "e7b4a1d3f2c9...",
  "capturedAt": "2024-06-01T14:32:00Z",
  "objects": [
    {
      "kind": "table",
      "schema": "public",
      "name": "orders",
      "hash": "a3f9c2..."
    }
  ]
}
```

***

## Common combinations

The table below summarises the most useful source pairings and the workflow each one powers.

| Scenario                        | `--from`                         | `--to`                               | Purpose                                                                         |
| ------------------------------- | -------------------------------- | ------------------------------------ | ------------------------------------------------------------------------------- |
| Local development               | `database:$LOCAL_URL`            | `dir:database/schemas`               | Generate a migration from your local DB to edited schema files                  |
| PR safety check (CI)            | `git:origin/main`                | `dir:database/schemas`               | Diff the branch against the base without a database                             |
| Deploy to production            | `database:$PROD_URL`             | `dir:database/schemas`               | Generate a migration targeting the live production database                     |
| Drift detection                 | `database:$PROD_URL`             | `catalog:snapshots/last-deploy.json` | Detect out-of-band changes on the server                                        |
| First migration                 | `empty:`                         | `dir:database/schemas`               | Generate the initial migration without a database or Git baseline               |
| Reconciling existing DB         | `database:$DATABASE_URL`         | `dir:database/schemas`               | Generate a migration from the deployed catalog to your files                    |
| Cross-branch comparison         | `git:origin/main`                | `git:feature/my-branch`              | Preview the migration a merge would produce                                     |
| Analyse a legacy dump           | `dump:legacy-schema.sql`         | `dir:database/schemas`               | Diff a dump file against your current schema                                    |
| Adopt a migration-first project | `migrations:supabase/migrations` | `dir:supabase/schemas`               | Generate the first lineage migration from the configured history                |
| Generate types from history     | `migrations:supabase/migrations` | n/a                                  | Run `supaschema types --from migrations:supabase/migrations` without a database |

<Tip>
  Defaults come from `supaschema.config.json`. `sources.from` owns the source
  before-state, `schemaPaths` owns the desired after-state, and `migrationsDir`
  owns migration-derived source intent plus generated-lineage baseline proof for
  zero-source-flag commands. For generation, the scaffolded `"auto"`
  before-state first resolves `git:INDEX` when the latest generated migration is
  staged without worktree edits and its lineage matches the indexed schema
  fingerprint. It then tries valid `git:HEAD` and blocks if generated migrations
  prove a different baseline. `empty:` is only
  for a first migration with no existing migration corpus. A `migrations:`
  before-state must resolve to `migrationsDir` and replay without errors; keep
  generation targets and verify/drift sources on `dir:`, `git:`, `dump:`,
  `catalog:`, `database:`, or `empty:`.

  ```json theme={null}
  {
    "schemaPaths": ["database/schemas"],
    "sources": {
      "from": "auto"
    }
  }
  ```
</Tip>
