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

# Using SQLBuild with dbt

> Opt into change-aware builds for your existing dbt project. No SQLBuild models and no migration.

Point SQLBuild at your existing dbt project and, when you want it, stop rebuilding what hasn't changed. No SQLBuild models, no migration, no edits to your dbt files.

<Frame>
  <img src="https://mintcdn.com/mimo-9eaac99f/2YYv9q2ul_AgU1zd/dbt-reuse.gif?s=910fda4d0a9431bc5c207aa99a0ca893" alt="Pointing SQLBuild at a dbt project: with --changes-only, the first build runs the edited models and the second build skips everything because all planned dbt models are current" width="1100" height="694" data-path="dbt-reuse.gif" />
</Frame>

**Change-aware builds (opt-in).** By default `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](/concepts/dbt-compatibility/change-aware-builds).

It also adds standalone operations that work against a production-shaped git ref: [`sqb dbt clone`](/concepts/dbt-compatibility/clone) to populate a target from production, and [`sqb dbt diff`](/concepts/dbt-compatibility/diff) to compare a build against a production baseline.

<Note>
  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.
</Note>

## Start with your existing dbt project

From inside your dbt project, run a `sqb dbt` command. Selection works exactly like dbt: scope to whatever you would normally build with `--select`, or omit it to plan the whole project.

```bash theme={null}
sqb dbt plan --select path:models/marts
```

The first time you do this, SQLBuild bootstraps itself. If there is no `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.

```
my-workspace/
  analytics/                  # your existing dbt project, untouched
    dbt_project.yml
    models/
    target/
      manifest.json
  sqlbuild_project/           # created by SQLBuild
    sqlbuild_project.toml     # points at the dbt project, no models of its own
    dbt/
      macros/
        generate_schema_name.sql  # schema override used by clone/diff
```

The generated `sqlbuild_project.toml` looks like this:

```toml theme={null}
name = "analytics"
adapter = "snowflake"
default_target = "dev"

[dbt]
project_dir = "../analytics"
profiles_dir = "/Users/you/.dbt"
target_path = "../analytics/target"
target = "dev"

[dbt.production_ref]
git_ref = "main"
generate_schema_name_override = "dbt/macros/generate_schema_name.sql"

[targets.dev]
schema = "analytics"

[targets.dev.connection]
source = "dbt_profile"
profile = "analytics"
target = "dev"
```

`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`](/concepts/dbt-compatibility/clone) and [`sqb dbt diff`](/concepts/dbt-compatibility/diff). It is not used by ordinary `sqb dbt build`, whose change-aware pruning comes from warehouse fingerprints alone. See [Configuration](#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:

```
Plan ready (0 selected resources)

dbt (3 selected resources)
  selected by dbt selector: 3 from dbt selector
  planned models: 0 run, 3 current, 0 blocked
  planned non-model dbt work: 0
  skipped: all planned dbt models are current

  Model plan
    First run (0)
    Current (3)
      model.analytics.dim_customers   no change
      model.analytics.fct_orders      no change
      model.analytics.dim_products    no change
    Blocked (0)
```

The next `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

1. SQLBuild runs `dbt compile` to produce a `manifest.json` with model metadata
2. SQLBuild reads the manifest to understand dbt model names and their qualified warehouse tables
3. SQLBuild resolves your `--select`/`--exclude` against dbt by running `dbt ls`, so dbt-native selectors like `state:modified` and `package:` are evaluated by dbt itself, not reimplemented
4. SQLBuild plans which dbt models actually need to run, using warehouse-stored fingerprints and source freshness
5. `sqb dbt plan/run/build/test` orchestrates the run: dbt builds the full selection by default, and with `--changes-only` builds only the models that changed, pruning everything that is current
6. (Optional) any SQLBuild models you have added run last, against the dbt outputs

Each step calls the `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.

```bash theme={null}
sqb dbt build --select path:models/marts --full-refresh
```

Declared flags are routed to the right place automatically:

| Flag                                                                            | Routed to                                        | Notes                                                                                                        |
| ------------------------------------------------------------------------------- | ------------------------------------------------ | ------------------------------------------------------------------------------------------------------------ |
| `--select` / `--exclude`                                                        | dbt                                              | dbt resolves selection (see [Selection](/concepts/dbt-compatibility/selection)).                             |
| `--vars`                                                                        | dbt **and** SQLBuild                             | The same vars feed dbt's compile and SQLBuild's own variable resolution, so both sides see identical values. |
| `--full-refresh`                                                                | dbt **and** SQLBuild                             | Forces a full rebuild of selected models and tells SQLBuild's planner not to skip them.                      |
| `--threads`                                                                     | dbt (`--threads`) and SQLBuild (`--concurrency`) |                                                                                                              |
| `--target` / `--project-dir` / `--profiles-dir` / `--profile` / `--target-path` | dbt                                              | Standard dbt locators.                                                                                       |
| `--changes-only`                                                                | SQLBuild                                         | Prunes models whose fingerprint and relation are unchanged from the dbt run. See below.                      |

#### `--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](/concepts/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.

```bash theme={null}
sqb dbt build --select path:models/marts --vars '{"my_var": 1}'
```

#### 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:

```bash theme={null}
sqb dbt build -- --log-level debug
```

## Configuration

The auto-generated project above is editable, and you can write `sqlbuild_project.toml` by hand. The `[dbt]` block (shown in the generated project above) accepts:

| Field              | Description                                                                                                                                                                                       |
| ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `project_dir`      | Path to the dbt project root (where `dbt_project.yml` lives)                                                                                                                                      |
| `profiles_dir`     | Path to the directory containing `profiles.yml`                                                                                                                                                   |
| `target_path`      | Path to dbt's `target/` directory (where `manifest.json` is written)                                                                                                                              |
| `target`           | dbt target name override (optional)                                                                                                                                                               |
| `replay_on_change` | Project-wide policy for rerunning changed dbt models: `forward_only` (default) or `full` (optional). See [Change-aware builds](/concepts/dbt-compatibility/change-aware-builds#replay-on-change). |
| `production_ref`   | Where your production-shaped relations live, used by [`sqb dbt clone`](/concepts/dbt-compatibility/clone) and [`sqb dbt diff`](/concepts/dbt-compatibility/diff). Written by auto-init.           |

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:

| Field                           | Description                                                                                                                                                                                                                 |
| ------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `git_ref`                       | The production-shaped git branch or tag to compile (`main` by default).                                                                                                                                                     |
| `generate_schema_name_override` | Path (relative to the SQLBuild project root) to a `generate_schema_name` macro injected into the isolated compile so it resolves production schema names. Auto-init generates one at `dbt/macros/generate_schema_name.sql`. |

#### 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 a `generate_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:

```sql theme={null}
{% macro generate_schema_name(custom_schema_name, node) -%}
    {%- if custom_schema_name is none -%}
        {{ target.schema }}
    {%- else -%}
        {{ custom_schema_name | trim }}
    {%- endif -%}
{%- endmacro %}
```

The macro must be named `generate_schema_name` (so it shadows your project's own) and live under `dbt/macros/` in your SQLBuild project.

<Warning>
  The override must produce production's schema names regardless of which target SQLBuild compiles with. The example above uses `target.schema` as the base, which only resolves to production when your configured target's schema is the production one. If your production base schema is a fixed value that differs from the active target, write that literal value instead of `target.schema`.
</Warning>

## Prerequisites

* dbt must be installed and available on `PATH` as `dbt`
* Both projects must target the same warehouse and schema/database context

SQLBuild uses your own `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).

```bash theme={null}
sqb dbt debug
```

## On this topic

* [Selection](/concepts/dbt-compatibility/selection) - how `--select` and `--exclude` route work across both graphs.
* [Change-aware builds](/concepts/dbt-compatibility/change-aware-builds) - fingerprinting, cascade propagation, source freshness, and pruning unchanged dbt models.
* [Column lineage](/concepts/dbt-compatibility/column-lineage) - trace a column through dbt and SQLBuild models, plus model-level lineage.
* [Testing](/concepts/dbt-compatibility/testing) - unit tests against dbt models, with mocks and model chaining.
* [Scenarios](/concepts/dbt-compatibility/scenarios) - end-to-end scenario tests with warehouse capture and local replay.
* [Diff](/concepts/dbt-compatibility/diff) - compare a dbt build against a production baseline.
* [Clone](/concepts/dbt-compatibility/clone) - copy or zero-copy clone production relations into a target.
* [Adding SQLBuild models](/concepts/dbt-compatibility/adding-sqlbuild-models) - optionally write SQLBuild models, tests, audits, and scenarios downstream of dbt.
