Skip to content

CLI Reference

sqb build

Compile, plan, and execute the selected build lifecycle.

Compiles, plans, and executes the selected build lifecycle, running the full selected scope. Use --no-tests and --no-audits to skip validation for fast iteration.

sqb build [SELECTOR ...] [flags]

Positional SELECTOR arguments work like --select, and both forms can be combined.

These options apply to every sqb command. --project-dir, --no-color, and --debug go before or after the command name, as in sqb --debug build or sqb build --debug. Under sqb dbt, put --project-dir before dbt: after it, --project-dir is passed to dbt as dbt’s own option. --version works only directly after sqb, as in sqb --version:

Option Description
--project-dir <path> Run against the project in <path> instead of the current directory
--no-color Print without colour
--debug Print detailed progress, the SQL each step runs, and internal diagnostics to stderr; implies --verbose
--version, -V Print the SQLBuild version
Flag Description
--target Build against a configured target instead of the active/default target
--no-tests Skip SQL unit tests
--no-audits Skip audits
--no-python Skip read-side Python tasks and assets (loader-side Python still runs for selected sources)
--no-sql-analysis Disable compile-time SQL analysis (--no-sql-validation is an alias)
--no-cache Bypass the reusable compile-analysis cache for this invocation
--full-refresh Drop and rebuild selected models unless a model sets full_refresh false; full_refresh true forces a model even without this flag
--changed Build only the selected models and seeds whose definition or inputs changed since they last succeeded; see Building only what changed
--defer-to Resolve unselected model references against another target
--defer-sources-to Read managed source data from another target
--fail-fast Stop on first failure and skip remaining nodes
--concurrency Number of worker connections (default: 1)
--test-timeout <duration> Time limit for each unit test the build runs, such as 30s, or disabled; see Time limits
--verbose, -v Show lifecycle SQL inline after each model
--start-cursor Override the start cursor, typed from the selected incremental models’ cursor type; fails with S303 if the selection mixes timestamp and integer cursors. With no cursor model selected, an integer value is read as an integer cursor and anything else as an ISO timestamp
--end-cursor Override the end cursor, typed the same way as --start-cursor
--start-cursor-ts Override start cursor for timestamp incremental models (ISO format)
--end-cursor-ts Override end cursor for timestamp incremental models (ISO format)
--start-cursor-int Override start cursor for integer incremental models
--end-cursor-int Override end cursor for integer incremental models
--load Explicitly load managed sources before building
--no-load Run no source loaders; selected managed sources are still audited
--reload Reload managed sources (passes is_reload=True to loaders)
--selection-diagnostics Warn when a selected model will build on changed upstream models that are not selected; see Selection and staleness
--manifest Generate target/manifest.json with plan-aware project metadata
SELECTOR ... Positional selectors, the same as --select
--select, -s Select specific models, or unit tests by name (test:<name>); selecting only unit tests runs them without building models
--exclude Exclude specific models
--warehouse <name> Snowflake warehouse for this invocation; overrides the target’s build warehouse group and the connection warehouse

Use --no-tests and --no-audits to skip validation when you only want to materialize models:

sqb build --no-tests --no-audits

This replaces the former sqb run command. The full lifecycle (tests + audits) is always the default; skip flags opt out of specific phases when you need speed.

--changed skips each selected model or seed that would read exactly what it read the last time it built successfully:

sqb build --changed
Changed: 2 of 3 selected models and seeds run; 1 unchanged are skipped.

Add --verbose to print why each one runs, such as input raw_orders changed.

A selected model or seed runs when any of these is true:

Reason Example
It has no successful build on record A new model
Its last build did not finish The build was killed or failed after the model started writing
Its relation is missing, or --full-refresh or a cursor override applies sqb build --changed --full-refresh
Its definition changed Edited SQL, config, hooks, contract or a function it calls
A source it reads has a different freshness value New rows raise MAX(loaded_at)
An upstream model or seed was rebuilt since, or runs in this build stg_orders ran, so customer_orders runs
An upstream model or seed needs to run, even when it is not selected sqb build customer_orders --changed runs customer_orders on every build until a changed stg_orders is built
What it reads can’t be listed SQL that reads relations not declared as sources or models, or a Python task or asset upstream

A model that runs under --changed plans exactly as in a plain build: its replay_on_change policy still decides how much history an incremental model reprocesses. A model that runs only because an upstream was rebuilt takes its normal incremental step.

In a scheduled job, set settings={'changed': True}. Skipped models count as successful nodes of the run.

Every build, with or without --changed, records what each model and seed read in _sqlbuild_consumption in its target schema, so the build needs permission to create and insert into that table. sqb janitor keeps the newest direct_state_history_versions builds of each relation.

Limitations:

  • A source is compared only through its freshness value. A change that doesn’t move it, such as an update that keeps the old loaded_at, isn’t seen. A source without freshness configuration counts as changed on every build.
  • SQL that depends on the time, such as current_date, or on random values never counts as changed. Build those models without --changed.
  • Two builds of one model less than 5 seconds apart can’t be ordered, so its downstream models run on the next --changed build.
  1. Managed sources are loaded (unless --no-load, which audits their existing data instead)
  2. Selected seeds are loaded
  3. Source audits run before their dependent models (unless --no-audits); with --no-load, or for a source selected by name, a source no model reads is audited at the end
  4. SQL unit tests run before their target model (unless --no-tests)
  5. Models are materialized in DAG topological order
  6. Error-severity audits run against the staging table before promotion to the target (unless --no-audits)

A resource with an attached audit also waits for every other model, seed, or table function that audit reads, so the audit can gate the resource like its other audits. See Audits that read other resources.

Execution sqb build (concurrency: 1)
1/17 source raw__customers OK 0.05s rows=5
2/17 source raw__orders OK 0.03s rows=10
3/17 seed waffle_types OK 0.03s
7/17 view stg_orders OK 0.04s
test test_stg_orders PASS
expect expected stg_orders PASS
expect assertion order_ids_are_not_null PASS
audit not_null (order_id) PASS
audit unique (order_id) PASS
audit not_null (customer_id) PASS
audit relationships (waffle_type_id) PASS
audit accepted_values (status) PASS
13/17 table hourly_order_activity (delete_insert) OK 0.24s
5 batches (1d) range 2026-03-31T09:00:00 → 2026-04-04T14:00:00 8 rows
audit (d) orders_placed_is_non_negative PASS 5/5
audit (d) not_null (activity_hour) PASS 5/5
audit (f) orders_placed_is_non_negative PASS
audit (f) not_null (activity_hour) PASS
✓ Completed successfully PASS=99 WARN=0 FAIL=0 INSUFFICIENT=0 SKIP=0 TOTAL=99 (2.13s)

Each resource prints one row when it finishes, followed by its tests and audits. Rows for individual warehouse statements and for steps inside a resource, such as Create staging relation, Promote relation, loader callable, or audit evaluation, appear only with sqb --debug build. Without --debug, a statement that is still running after 30 seconds prints a RUNNING row every 30 seconds, with its elapsed time and, when the warehouse reports one, its query ID. A failed statement or step still prints its FAIL row.

Use --defer-to to resolve unselected model references against another target. This lets you build a subset of models in dev while referencing production tables for everything else:

sqb build fact_orders --defer-to prod

No manifest.json is required. --defer-to selects only the namespace used for unselected references. SQLBuild resolves those relations through the active target’s sole physical connection and never opens the deferred target’s connection. The deferred namespace must be visible and readable through the active connection; deferral is not a cross-account, cross-server, or cross-file transfer mechanism.

When a model fails:

  • Downstream models are automatically blocked and skipped
  • Staging/delta tables are retained for inspection
  • Failure details show the model name, failed phase, and error message

A model that exceeds its max_duration fails with C417. The failure states the elapsed time, the limit and where it was set, whether cancelling its running statement was confirmed, and the query IDs SQLBuild saw; downstream models are skipped as for any other failure. Its row shows TIMEOUT. In the summary line, timed-out models and unit tests are counted under TIMEOUT= and excluded from FAIL= (PASS=1 WARN=0 FAIL=0 TIMEOUT=1 INSUFFICIENT=0 SKIP=1 TOTAL=3). In --json output, summary.failure_count still includes them, and summary.timeout_count reports how many of those failures were timeouts. A timeout is a failure for the exit code: the build exits non-zero and its JSON status is failed.

After a successful build, SQLBuild writes version identities to _sqlbuild_fingerprints in the target schema. These are used on subsequent runs to detect changes and skip unchanged work. A build writes a row only for a resource whose identity differs from its latest row, so a build that changes no definitions writes none. In a project with model migration history, every build writes a row for each resource it builds. See Planning and Change Detection for details.

Build writes executed lifecycle SQL to target/run/models/. These files contain the actual SQL that was executed, including resolved cursor bounds and runtime substitutions.