dbt-plan

Static analysis tool that warns about risky DDL changes before dbt run. Like terraform plan for dbt.

pip install dbt-plan

Get started in 2 minutes

1Install
One package, one dependency (sqlglot). No warehouse connection needed.
pip install dbt-plan
2Run
One command handles everything: compile baseline, compile current, check.
dbt-plan run
3Add to CI
Generate a GitHub Actions workflow that blocks destructive PRs.
dbt-plan ci-setup

What you'll see

$ dbt-plan check dbt-plan -- 3 model(s) changed DESTRUCTIVE int_unified (incremental, sync_all_columns) DROP COLUMN data__device ADD COLUMN data__device__uuid Downstream: fct_events, dim_device (2 model(s)) >> BROKEN_REF fct_events: references dropped column(s): data__device WARNING fct_strict (incremental, fail) BUILD FAILURE SAFE dim_device (table) CREATE OR REPLACE TABLE dbt-plan: 3 checked, 1 safe, 1 warning, 1 destructive, 1 cascade risk(s)

What it checks

Column changes
Detects ADD/DROP from compiled SQL diffs. Flags sync_all_columns drops as DESTRUCTIVE.
Cascade analysis
Finds downstream models that reference dropped columns or will fail from schema changes.
Config changes
Detects materialization or on_schema_change policy changes between snapshots.
CI-ready
Exit codes (0/1/2), JSON output, GitHub markdown. One-line summary for grep.
Multi-dialect
Snowflake, BigQuery, Postgres, Redshift, DuckDB, and more via --dialect.
Zero runtime deps
Only sqlglot. No warehouse connection. Analyzes files on disk, nothing else.
Safe by design
Parse failures, SELECT *, and ambiguous columns always warn. False safe is never OK.
200+ tests
92% coverage. Every materialization, every edge case, every output format tested.

CI integration

1Generate workflow
One command creates .github/workflows/dbt-plan.yml with snapshot, check, and merge gate.
dbt-plan ci-setup
2Push and done
Every PR that touches models/ will be checked. Destructive changes block merge (exit 1).
git add .github/workflows/dbt-plan.yml
git push

All commands

CommandWhat it does
dbt-plan runOne command: compile baseline, compile current, check. Handles git stash automatically.
dbt-plan checkAnalyze compiled SQL changes and warn about risks. Supports --format text/github/json, --select.
dbt-plan snapshotSave current compiled SQL + manifest as baseline for later comparison.
dbt-plan ci-setupGenerate GitHub Actions workflow that runs dbt-plan on every PR.
dbt-plan initGenerate .dbt-plan.yml config + add .dbt-plan/ to .gitignore.
dbt-plan statsAnalyze project: materialization distribution, SELECT * usage, cascade risks.

Configuration

Create .dbt-plan.yml in your project root, or use environment variables.
# .dbt-plan.yml

# Skip known-safe models
ignore_models: [scratch_model, staging_temp]

# SQL dialect (default: snowflake)
dialect: bigquery

# Custom compile command (for uv, poetry, etc.)
compile_command: uv run dbt compile

# Exit code for warnings (default: 2, set 0 to pass CI)
warning_exit_code: 0
All settings also work as environment variables (for CI):
DBT_PLAN_DIALECT=bigquery
DBT_PLAN_COMPILE_COMMAND="uv run dbt compile"
DBT_PLAN_IGNORE_MODELS="scratch_model,staging_temp"
DBT_PLAN_FORMAT=json
DBT_PLAN_WARNING_EXIT_CODE=0
Priority: CLI flags > environment variables > .dbt-plan.yml > defaults

Design philosophy

PrincipleMeaning
False safe = neverIf we can't determine safety, we warn. Never silently pass.
False warning = OKOver-warning is fine. Use ignore_models to suppress.
No runtime depsOnly sqlglot. No warehouse connection needed.
CI-firstExit codes, structured output, one-line summary.