“An embrasure is an opening in a fortified wall, built to see and respond without giving up protection.”
Catch unexpected data changes before a dbt PR is reviewed.
Embrasure is open-source, local dbt PR validation for Snowflake, Databricks, and BigQuery:
- Builds changed models and critical downstream paths in temporary schemas, then cleans them up.
- Runs dbt tests and compares schema, row counts, null rates, cardinality, ranges, and primary keys with production.
- Shows affected downstream models and columns.
- Connects directly to your warehouse, with no Embrasure account or data sent to Embrasure.
- Includes a
verifyskill that runs the agent check-and-fix loop.
embrasure auth login uses Snowflake OAuth. Databricks uses a token supplied through the configured environment variable. BigQuery uses Google Application Default Credentials. The warehouse identity needs production read access and permission to create and remove temporary schemas or datasets.
From your existing Snowflake dbt Core project directory, create or activate its Python environment:
python3 -m venv .venv
source .venv/bin/activate
python -m pip install "dbt-core>=1.5,<2""dbt-snowflake>=1.5,<2""sqlglot>=30,<31"Then install Embrasure on macOS or Linux with Homebrew:
brew install embrasureai/tap/embrasure
embrasure init
embrasure auth login
embrasure doctor
embrasure check --dry-run
embrasure checkBy default, check compares your branch with origin/main.
If dbt is managed by your project
Embrasure uses the dbt Core and Snowflake adapter versions already installed by your project. Activate the project's normal environment, or set dbt.command in embrasure-check.yml to the wrapper your project uses.
Install the Databricks dbt adapter instead of dbt-snowflake:
python -m pip install "dbt-core>=1.5,<2""dbt-databricks>=1.5,<2""sqlglot>=30,<31"Use a version 2 configuration with a typed provider block:
version: 2dbt:
project_dir: .profile: analyticsaccounts:
- name: primaryprovider:
type: databrickshost: https://your-workspace.cloud.databricks.comhttp_path: /sql/1.0/warehouses/your-warehouse-idcatalog: analyticsproduction_schema: prodauth:
type: tokentoken_env: DATABRICKS_TOKENThe integration uses a Databricks SQL warehouse and Unity Catalog. Set DATABRICKS_TOKEN, then run embrasure doctor and embrasure check. Incremental baselines currently require managed Delta tables and use Unity Catalog shallow clones; doctor verifies that a suitable table and grants are available.
Install the BigQuery dbt adapter:
python -m pip install "dbt-core>=1.5,<2""dbt-bigquery>=1.5,<2""sqlglot>=30,<31"For local development, create Google Application Default Credentials, then initialize Embrasure from the dbt project root:
gcloud auth application-default login
embrasure init
embrasure doctor
embrasure check --dry-run
embrasure checkinit detects an active BigQuery dbt profile and writes the version 2 provider configuration. The equivalent manual configuration is:
version: 2dbt:
project_dir: .profile: analyticsaccounts:
- name: primaryprovider:
type: bigqueryproject: analytics-prodlocation: USproduction_schema: prodmaximum_bytes_billed: 10737418240auth:
type: application_defaultApplication Default Credentials also support GOOGLE_APPLICATION_CREDENTIALS and an attached Google Cloud service account. maximum_bytes_billed applies the same per-query cap to dbt builds and Embrasure comparison queries. Incremental baselines use BigQuery table clones; clone mode seeds candidates with table copies. The source and temporary datasets must be in the same location, and table-clone restrictions still apply.
If you do not use Homebrew, use the installer:
curl -fsSL https://raw.githubusercontent.com/EmbrasureAI/embrasure-cli/main/install.sh | shThe installer writes to /usr/local/bin when writable, otherwise ~/.local/bin. Set EMBRASURE_INSTALL_DIR to choose another directory.
Installing on Windows (Windows 11 or Windows Server 2022+)
Download the PowerShell installer from GitHub Releases, inspect it, then run it:
$installer=Join-Path$env:TEMP'embrasure-install.ps1'Invoke-WebRequest https://github.com/EmbrasureAI/embrasure-cli/releases/latest/download/install.ps1 -OutFile $installerGet-Content$installerUnblock-File$installer&$installerThe installer verifies the release checksum, installs Embrasure under %LOCALAPPDATA%\Programs\Embrasure, and adds its bin directory to your user PATH. It does not need administrator access. Open a new terminal when it finishes.
Unblock-File removes the internet-zone marker after you inspect the script. It does not change PowerShell's execution policy or verify the publisher. If your organization blocks the script, use the portable ZIP from the same release.
Installer options:
- Pin a release:
& $installer -Version 0.5.4 - Run without prompts:
& $installer -Quiet - Uninstall:
& $installer -Uninstall
Uninstalling removes Embrasure and its PATH entry, but keeps your configuration, credentials, reports, and logs.
Scoop users can install from Embrasure's official bucket:
scoop bucket add embrasure https://github.com/EmbrasureAI/scoop-bucket
scoop install embrasure/embrasureWinGet manifests are generated with each release. After the first WinGet listing is accepted:
winget install --id EmbrasureAI.Embrasure --exactUse Embrasure from an existing Snowflake, Databricks, or BigQuery dbt project whose unchanged production models are already materialized. Embrasure uses those existing relations as the comparison baseline.
For Snowflake and BigQuery, init reads the active dbt profile and asks only for missing values. Databricks uses the version 2 configuration shown above. Use --config <path> before or after any subcommand to choose another config file.
Continue only when embrasure doctor reports READY. Embrasure generates a temporary dbt profile for its own runs; it does not modify your existing profile or production models.
If dbt is installed in .venv, run source .venv/bin/activate in each new shell before using Embrasure.
Example result:
✓ Safe to continue
The change passed across every selected dbt model.
Scope
5 affected models
2 selected for validation
Evidence
2 / 2 models built · 2 compared with production
151,615,312 candidate rows evaluated
Schema, row counts, nulls, cardinality, and distributions checked
1 primary key checked
0 findings · 3 unvalidated models
Temporary warehouse schema removed
Lineage impact
fct_orders
└─ finance_daily
├─ executive_revenue
├─ regional_margin
└─ revenue_forecast_input
Completed in 2m11s
In an interactive terminal, check shows live progress while it runs. Redirected output, CI, and --json stay plain.
The default validates changed models and every path to a critical model. Critical targets are tagged critical, configured with critical: true, or used directly by a dbt exposure. Use --downstream all for every downstream model or --downstream none for changed models only. Impact is always computed from the full changed set.
Intersect the changed set with one or more explicit models:
embrasure check --select orders --select order_items
embrasure check --select orders --downstream noneAn unknown, ambiguous, unchanged, or out-of-scope selection fails instead of returning a misleading pass.
Preview the plan without creating schemas or querying warehouse data:
embrasure check --dry-run
embrasure check --dry-run --jsonDry runs use local dbt parsing but do not resolve credentials, create warehouse schemas, or query warehouse data.
JSON output is versioned and stably ordered. Progress goes to stderr, so stdout contains one JSON document.
embrasure check --json
embrasure check --json --markdown embrasure-check.md
embrasure check --json --report-version 1Published contracts: v1, v2, v3, and v4. V4 adds column lineage and bounded warehouse execution links and is the default; older versions remain available with --report-version.
| Exit code | Meaning |
|---|---|
0 | The check passed |
1 | The data or code needs a fix |
2 | A requested check could not be completed |
3 | Setup, execution, or cleanup failed |
Agent loop:
Run `embrasure check --base origin/main --json`.
Exit 1: fix every finding and rerun.
Exit 2: resolve or explain every coverage gap.
Exit 3: fix the setup or execution failure.
Request review only after exit 0.
For a faster first pass on large tables, add --mode quick. Quick mode estimates cardinality and skips percentiles. Deep mode is the default. Primary-key integrity stays exact in both modes.
Query-diff checks compare any two read-only query results exactly. production_sql defaults to sql, and each dbt ref() is rendered against the candidate or production-state manifest. Checks with no refs, or definitions changed since --base, run even when no model changed.
checks:
- type: query_diffname: paid order totalssql: | select customer_id, sum(amount) as paid_amount from {{ ref('orders') }} where status = 'paid' group by customer_idprimary_key: [customer_id]With a primary key, Embrasure reports added, removed, and changed rows plus per-column mismatch counts. Null or duplicate keys block the value join. Without a key, grouped rows and their multiplicities preserve duplicate-only differences. Query examples are bounded by the configured sample, column, and value limits.
Only persisted dbt models are supported in ref(). Query checks accept one SELECT, WITH, or VALUES expression; other Jinja and multi-statement SQL are rejected. Removed checks are reported as incomplete coverage instead of silently passing.
The composite action installs Embrasure. Install dbt with your project's normal locked setup; this example uses requirements.txt. Keep the check in a visible run step so exit codes and secrets remain explicit.
In embrasure-check.yml, configure the account to read the CI secret:
auth:
type: programmatic_access_tokentoken_env: SNOWFLAKE_PROGRAMMATIC_ACCESS_TOKENjobs:
embrasure:
runs-on: ubuntu-24.04permissions:
contents: readsteps:
- uses: actions/checkout@v4with:
fetch-depth: 0
- uses: actions/setup-python@v6with:
python-version: "3.12"
- run: python3 -m pip install -r requirements.txt
- uses: EmbrasureAI/embrasure-cli@v1
- run: embrasure check --base origin/main --jsonenv:
SNOWFLAKE_PROGRAMMATIC_ACCESS_TOKEN: ${{ secrets.SNOWFLAKE_PROGRAMMATIC_ACCESS_TOKEN }}fetch-depth: 0 is required because selection compares the working tree with the base revision.
List managed temporary schemas older than six hours:
embrasure clean
embrasure clean --older-than 24 --yesclean searches only configured account databases and verifies the prefix and ownership marker before removal.
Check for or install an update:
embrasure update --check
embrasure updateGenerate shell completion scripts:
embrasure completion bash
embrasure completion zsh
embrasure completion fish
embrasure completion powershellYour generate_schema_name macro must preserve the complete target schema. Make custom schemas children of target.schema; do not replace it.
Every existing incremental model needs a stable baseline copy, including in full-refresh mode. Snowflake supports tables that can be zero-copy cloned; Databricks currently supports managed Delta tables that can be shallow cloned; BigQuery supports base tables, table clones, and table snapshots accepted by CREATE TABLE CLONE. Use another materialization or exclude an unsupported relation from this validation path.
The validation role needs SELECT on the production source and CREATE TABLE in the target schema. Run embrasure doctor. If the relation should not use clone mode, rerun with --incremental-mode full-refresh.
Use --config <path> before or after any subcommand to choose another config file.
See the example configuration and enterprise setup guide for service credentials, multiple accounts, model policies, filters, thresholds, concurrency, external changes, cross-account dependencies, Metabase, and grants.
Every temporary schema has a unique name and ownership marker. Query results are materialized in a dedicated run-owned schema so they cannot collide with dbt model aliases. Embrasure checks ownership before removal and treats cleanup failures as execution failures. Use a dedicated identity that can read and clone only the production tables under test and create temporary schemas in the required databases or catalogs. SQL validation is not a side-effect sandbox, so the identity must not be able to call unsafe procedures, functions, or external integrations.
Security and data flow documents network connections, local files, returned data, credentials, cleanup, updates, and release verification.
- Databricks support requires a Unity Catalog SQL warehouse and environment-supplied token authentication.
- Native Windows support requires 64-bit Windows 11 or Windows Server 2022+. Windows 10, Windows on Arm, and machine-wide installation are not supported.
- Column lineage covers compiled dbt SQL that SQLGlot can resolve. Wildcards without an input schema and dynamic SQL are reported as unresolved.
- Dashboard column lineage is not inferred from model lineage.
- Metabase matching covers native SQL cards that reference fully qualified production relations. Unsupported or inaccessible metadata becomes a coverage gap.
Rust 1.88 or newer is required when building from source.
cargo fmt --check
cargo clippy --all-targets --all-features -- -D warnings
cargo test --lockedThe opt-in Snowflake suite uses EMBRASURE_RUN_SNOWFLAKE_TESTS=1 and the EMBRASURE_TEST_SNOWFLAKE_* account, user, role, database, warehouse, and token variables. It covers exact keyed passes and changes, duplicate-only unkeyed differences, incremental cloning, cleanup, and 100,000 synthetic rows.
Contributions are welcome under the Apache 2.0 license.