dbt doctor (GitHub Repo)
dbt-doctor is a new open-source CLI tool for identifying maintainability issues, documentation gaps, and schema drift in dbt projects.
Decoder
- dbt: Data Build Tool, an open-source command-line tool that enables data analysts and engineers to transform data in their warehouses using select statements.
- DAG: Directed Acyclic Graph, the structure dbt uses to model dependencies between tables and transformations.
- Schema drift: The unintentional evolution of database schemas, where source data changes (e.g., new columns) in ways that break downstream transformations.
Original article
dbt-doctor
Static analysis and health checks for dbt projects.
dbt-doctor is a clone of React Doctor by Million. React Doctor is published under the MIT License; this project clones and adapts its ideas (CLI, scoring, agent tooling) for dbt and remains MIT as well. Thank you to the React Doctor maintainers for the original work.
Static analysis and health checks for dbt projects.
Find missing docs, missing tests, schema drift risks, stale models, DAG maintainability issues, and CI quality gate failures.
dbt-doctor scans your dbt project and finds maintainability issues before they become production debt:
- missing model documentation
- missing dbt tests
- weak docs/test coverage
- schema drift risks
- stale models
- source freshness gaps
- naming convention issues
- oversized DAG areas
- governance and ownership gaps
Use it locally, in pre-commit, or as a CI quality gate for analytics engineering teams.
Requirements
- Node.js 22+
- dbt layout: a
dbt_project.ymlat the project root (or userootDirin config for monorepos). - SQLFluff (recommended):
pip install sqlfluff sqlfluff-templater-dbt- omit if you setskipSqlfluff: trueor usecustomRulesOnly(custom rules only).
Quick start
From your dbt project root:
npx dbt-doctor@latest
You get a score (75+ Great, 50–74 Needs work, under 50 Critical) and grouped findings. The score counts unique rules that fired (each plugin/rule once), not every occurrence.
Install for coding agents
Install the dbt-doctor skill into detected agents (Cursor, Claude Code, Codex, and others):
npx dbt-doctor@latest install
Use --yes to skip prompts. Same behavior as the website’s curl installer, which delegates to this command.
GitHub Actions
A composite action lives in this repo. Example workflow:
name: dbt Doctor
on:
pull_request:
push:
branches: [main]
permissions:
contents: read
pull-requests: write # for sticky PR comments
jobs:
dbt-doctor:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
with:
fetch-depth: 0 # required when using diff
- uses: northgraindata/dbt-doctor@main
with:
diff: main
github-token: ${{ secrets.GITHUB_TOKEN }}
Notable inputs: directory, verbose, project, diff, github-token, fail-on (error / warning / none), offline, annotations, setup-sqlfluff (default installs SQLFluff + dbt templater), node-version.
With github-token on pull_request, findings are posted as a sticky PR comment. The action exposes a score output (0–100) for follow-up steps (e.g. score floor checks).
Bare CLI in CI (no marketplace action):
- run: npx dbt-doctor@latest --fail-on warning
Remember to install SQLFluff in that job unless you rely on skipSqlfluff / customRulesOnly.
PR blocking and exit codes
--fail-on <level>-error(default),warning, ornone. Applies to diagnostics that pass theciFailuresurface (see configuration).--diff <base>- only files changed vsmain/masteror your branch name; good for regression-only gates.--staged- only staged files (pre-commit). Do not combine with--diff.
Configuration
Add a .dbt-doctor props file at the project root (KEY=value, # comments - like .env). CLI flags override config.
Presets (default | strict | enterprise) control which rule tags run and default CI strictness. Omit preset to run all 122 rules.
Example .dbt-doctor:
# Full catalog + governance (all 122 rules including native SQL style)
preset=enterprise
score_mode=files
fail_on=warning
# Silence noisy rules on legacy paths
ignore.rules=dbt-doctor/no-select-star
ignore.files=models/legacy/**
skip_sqlfluff=false
offline=false
Inline suppressions (SQL / YAML)
Use dbt-doctor-disable-next-line on the line above the finding. SQL:
-- dbt-doctor-disable-next-line dbt-doctor/no-select-star
select * from {{ ref('stg_orders') }}
CLI reference
Usage: dbt-doctor [directory] [options]
Options:
-v, --version display the version number
--lint / --no-lint enable or skip linting
--verbose show every rule and per-file details
--score output only the score
--json structured JSON report on stdout
--json-compact with --json, minimal whitespace
-y, --yes skip prompts; scan all workspace packages
--full full scan (overrides diff in config / CLI)
--project <name> workspace package(s), comma-separated
--diff [base] only files changed vs base branch
--staged only git-staged files
--offline skip score API and share URL (local score)
--fail-on <level> error | warning | none
--annotations GitHub Actions annotation format
--pr-comment tune output for sticky PR comments
--explain <file:line> why a rule fired or suppression missed
--why <file:line> alias for --explain
-h, --help display help
Commands:
install|setup install agent skills (--yes, --dry-run, -c cwd)
Scoring
Formula (same locally and on the default API):
score = round(100 − (unique error rules × 1.5) − (unique warning rules × 0.75))
Labels: Great ≥ 75, Needs work ≥ 50, Critical < 50.
Node.js API
import { diagnose, toJsonReport, summarizeDiagnostics } from "dbt-doctor/api";
const result = await diagnose("./path/to/dbt-project", { offline: false });
console.log(result.score); // { score, label } | null in edge cases
console.log(result.diagnostics);
console.log(result.project); // ProjectInfo: adapter, model paths, etc.
Who made dbt Doctor?
dbt Doctor is built and maintained by Northgrain Data, a data engineering agency for modern dbt and Snowflake teams.
Fresh dev news, AI-digested daily. Never miss a trend at devoured.fyi