
sqb dbt build runs your full selection, exactly like dbt. Add --changes-only and SQLBuild fingerprints your dbt models in the warehouse and prunes the ones that have not changed, so a second build skips everything already current and a single edit rebuilds only that model and whatever depends on it. This works on a plain dbt project with no SQLBuild models. See Change-aware builds.
It also adds standalone operations that work against a production-shaped git ref: sqb dbt clone to populate a target from production, and sqb dbt diff to compare a build against a production baseline.
SQLBuild reads your dbt manifest and drives the
dbt CLI as a subprocess. It never edits, patches, or moves files in your dbt project, and it does not reimplement Jinja, profiles, or dbt’s selection language. Your dbt project runs exactly as it does today.Start with your existing dbt project
From inside your dbt project, run asqb dbt command. Selection works exactly like dbt: scope to whatever you would normally build with --select, or omit it to plan the whole project.
sqlbuild_project.toml, it reads your dbt_project.yml and profile and creates a minimal twin project in a sqlbuild_project/ directory next to your dbt project. It reuses your dbt profile for the warehouse connection, so there are no separate credentials to configure.
sqlbuild_project.toml looks like this:
source = "dbt_profile" tells SQLBuild to connect using your dbt profile, so it talks to the same warehouse dbt does.
The [dbt.production_ref] block configures where your production-shaped relations live, and is used by sqb dbt clone and sqb dbt diff. It is not used by ordinary sqb dbt build, whose change-aware pruning comes from warehouse fingerprints alone. See Configuration for the field reference and the schema-name override.
Run sqb dbt build --select path:models/marts once to build your selected dbt models with state recorded, then plan again with --changes-only. Once everything in the selection is current, the dbt side reports nothing to do:
sqb dbt build --changes-only skips the dbt run entirely because nothing changed. Change one model and only that model, plus whatever depends on it, rebuilds.
How it works
- SQLBuild runs
dbt compileto produce amanifest.jsonwith model metadata - SQLBuild reads the manifest to understand dbt model names and their qualified warehouse tables
- SQLBuild resolves your
--select/--excludeagainst dbt by runningdbt ls, so dbt-native selectors likestate:modifiedandpackage:are evaluated by dbt itself, not reimplemented - SQLBuild plans which dbt models actually need to run, using warehouse-stored fingerprints and source freshness
sqb dbt plan/run/build/testorchestrates the run: dbt builds the full selection by default, and with--changes-onlybuilds only the models that changed, pruning everything that is current- (Optional) any SQLBuild models you have added run last, against the dbt outputs
dbt CLI directly: dbt compile for the manifest, dbt ls for selection, and dbt build/dbt run for execution.
Flags
sqb dbt plan/run/build/test declare the common flags directly. Anything declared goes before a -- separator; any other raw dbt flag goes after it and is forwarded verbatim. A flag placed on the wrong side errors rather than silently reaching dbt.
--changes-only
By default sqb dbt build runs every selected model, exactly like dbt. --changes-only turns on change-aware pruning for the current run: any model whose fingerprint and relation are unchanged is dropped from the dbt command, so dbt only rebuilds what actually changed. It is the dbt-interop equivalent of native sqb build --changes-only. Pruning is driven by the warehouse fingerprints SQLBuild records on every build, so a build without the flag still keeps state current; the next --changes-only run picks up exactly where it left off. It is distinct from --full-refresh: --changes-only decides whether a model runs, while --full-refresh decides how (a full rebuild rather than an incremental run).
--vars
--vars accepts the same JSON object dbt accepts, and SQLBuild passes it to both the underlying dbt invocation and its own variable resolution. That means a value referenced as @@my_var in SQLBuild model SQL (see Interpolation) and as {{ var('my_var') }} in a dbt model both resolve to the value you passed. CLI vars take precedence over project and local config vars. You do not need to declare vars twice.
Forwarding other dbt flags
For any native dbt flag SQLBuild does not declare, put it after-- and it is passed straight to the dbt invocation untouched:
Configuration
The auto-generated project above is editable, and you can writesqlbuild_project.toml by hand. The [dbt] block (shown in the generated project above) accepts:
Paths can be absolute or relative to the SQLBuild project root.
The production ref block
sqb dbt clone and sqb dbt diff need to know your production-shaped relations. They find them by compiling your dbt project at a configured git ref in an isolated checkout (your working tree is never touched) and reading the relation names from the resulting manifest. The block accepts:
The schema-name override macro
SQLBuild compiles the production ref with your configured target and deliberately knows nothing about your environments. If that target resolves to your dev schemas, the manifest points at dev tables, not the production ones. The override fixes this: you provide agenerate_schema_name macro that resolves to your production schema layout with no environment branching, and SQLBuild injects it into the isolated checkout only, never your real dbt project.
Take your project’s existing generate_schema_name, keep only what it does in production, and delete the dev/CI branching. Auto-init writes a default that works for dbt’s stock unsuffixed layout:
generate_schema_name (so it shadows your project’s own) and live under dbt/macros/ in your SQLBuild project.
Prerequisites
- dbt must be installed and available on
PATHasdbt - Both projects must target the same warehouse and schema/database context
dbt install; it does not bundle or install dbt. If your dbt is not reachable as a bare dbt on PATH (for example, you run it via uv, poetry, or a wrapper), set the DBT_EXECUTABLE environment variable to the executable SQLBuild should call.
SQLBuild runs dbt compile automatically as part of sqb dbt plan/run/build/test to produce the manifest. You do not need to compile the dbt project manually.
Debugging
sqb dbt debug runs both projects’ diagnostics: dbt debug (verifying the dbt project config and warehouse connection) followed by sqb debug (verifying the SQLBuild project config and connection).
On this topic
- Selection - how
--selectand--excluderoute work across both graphs. - Change-aware builds - fingerprinting, cascade propagation, source freshness, and pruning unchanged dbt models.
- Column lineage - trace a column through dbt and SQLBuild models, plus model-level lineage.
- Testing - unit tests against dbt models, with mocks and model chaining.
- Scenarios - end-to-end scenario tests with warehouse capture and local replay.
- Diff - compare a dbt build against a production baseline.
- Clone - copy or zero-copy clone production relations into a target.
- Adding SQLBuild models - optionally write SQLBuild models, tests, audits, and scenarios downstream of dbt.

