# Schema commands

Two commands about the warehouse layer beneath the ontology: pull a local snapshot to work from, or push a DDL file so Cassis detects what changed.

## schema pull

Downloads the project’s full source schema, as last introspected from the warehouse or uploaded as DDL, into `cassis/.schema.json`.

```bash
# In a checkout with cassis/project.yml, the project id is read from it
cassis schema pull

# Or name the project and checkout explicitly
cassis schema pull /path/to/checkout --project 019f0000-0000-7000-8000-000000000000
```

This is the bulk counterpart to the MCP server’s [`get_source_schema`](/reference/mcp/source-schema/) tool: instead of paging through 20 tables per call, an agent on a modeling pass greps one local file.

- **Observed state, not truth** The snapshot is stamped with `pulled_at`. The warehouse stays authoritative and the file is a local cache. Re-run to refresh.

- **Never committed** The command maintains a `.gitignore` entry for it in the ontology directory.

- **Exit codes** 0 on success, 2 on a usage error including a checkout it cannot write to, 3 on a transport or API error.

## schema push

Uploads a DDL file to detect source-schema changes on a DDL-only project, the same effect as the web app’s “Update from DDL” button. Cassis diffs the DDL against the ontology, and added, dropped, and changed objects appear in the [Data source review queue](/curate/data-source-changes/) for approval. Read that queue from the terminal with [`cassis source-changes list`](/reference/cli/source-changes/).

**A DDL file speaks only for the schemas it contains.** A partial export — Snowflake’s per-schema `GET_DDL`, one schema out of many — adds and updates the schemas it covers and leaves the others as they were, instead of marking every table in them as removed. Pass `--complete` when the file **is** the project’s complete source schema, so schemas absent from it are treated as dropped. That was the behavior of every upload before, and it now takes `--complete` to get.

This scoping lives in Cassis, not in the CLI, so it applies to every upload from every client whatever its version, including older CLIs that cannot pass the flag. If a pipeline of yours relied on leaving a schema out of the file to signal that it was dropped, upgrade to cassis-cli 1.6.0 or newer and pass `--complete`, or those drops stop being detected.

```bash
# Upload and wait for the detection run to complete
cassis schema push schema.sql --project ...

# The file is the whole source schema: schemas missing from it were dropped
cassis schema push schema.sql --project ... --complete

# Machine-readable output
cassis schema push schema.sql --project ... --json
```

- **Scope of the file** Without `--complete`, only the schemas present in the file are compared, and the stored schema keeps carrying the rest. With `--complete`, a schema the file does not mention is a dropped schema.

- **DDL-only projects** Connected projects sync their schema from the warehouse directly, so this command does not apply to them.

- **Waiting** The command always waits for the detection run and exits 0 only when the run completed — the DDL parsed and the schema was applied. `--poll-interval` (5 seconds) and `--timeout` (10 minutes) control the polling; the run keeps going server-side if the CLI hits the timeout (exit 3).

- **What success prints** The number of changes the run queued for review, or that there were none.

- **Suspected partial export** When the file drops most of the tracked tables in a schema it does cover, Cassis flags it and the command prints a note. Removals of modeled tables wait for review rather than applying, so re-pushing a complete export undoes an unintended drop.

- **Parse errors** A DDL statement the parser cannot read fails the run: exit 1 with the parser’s message. Nothing is applied.

- **Conflict** Exit 1 when the project will not take the push: a detection run is already in flight, or the project is warehouse-connected rather than DDL-only. Wait for the run to finish or cancel it in the web app; a connected project refreshes with a warehouse sync instead.

- **Superseding** Re-uploading a corrected DDL supersedes the previous one.

Neither command changes the ontology. `schema pull` writes a local snapshot; `schema push` queues changes for a human to approve. Modeling a newly appeared table is still an edit in the repository or the app.
