Skip to content
Use this GitHub action with your project
Add this Action to an existing workflow or create a new one
View on Marketplace

Repository files navigation

dbt Doctor - static analysis and health checks for dbt projects

version downloads

See CHANGELOG.md for release history.

Note

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 - see the monorepo LICENSE. 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

Static analysis and health checks for dbt projects.

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.yml at the project root (or use rootDir in config for monorepos).
  • SQLFluff (recommended): pip install sqlfluff sqlfluff-templater-dbt - omit if you set skipSqlfluff: true or use customRulesOnly (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. See action.yml for full descriptions.

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, or none. Applies to diagnostics that pass the ciFailure surface (see configuration).
  • --diff <base> - only files changed vs main / master or your branch name; good for regression-only gates.
  • --staged - only staged files (pre-commit). Do not combine with --diff.

Annotations (--annotations) and PR comments (github-token) are display-only for exit code purposes unless paired with --fail-on.

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. See presets.

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

CLI overrides: --preset enterprise, --score-mode files, --fail-on warning.

  • ignore.rules - silence those rules everywhere.
  • ignore.files - silence all rules on matching paths (use sparingly).
  • ignore.overrides - silence listed rules only on matched files.
  • ignore.tags - silence every rule with a given tag (e.g. design-style hints if you use them).
  • rootDir - if config lives above the dbt project, point here (path relative to the config file).
  • skipSqlfluff / customRulesOnly - run only built-in dbt-doctor rules (no Python).
  • adoptExistingSqlfluffConfig - pick up .sqlfluff / pyproject.toml when present (default true).
  • offline - skip the remote score API and share link; score still uses the local formula.
  • surfaces - tune cli, prComment, score, and ciFailure independently (include/exclude by tag, category, or plugin/rule id).
  • rules / categories - severity overrides (error / warn / off) for rule ids and rule categories.

Rule catalog: Rules reference (generated from packages/dbt-doctor-rules/src/rules/).

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') }}

YAML / Jinja can use # or -- style comments depending on context. Use dbt-doctor --explain path/to/file.sql:42 (or --why) to see why a rule fired or why a suppression did not apply.

Respect for other tools: .gitignore is honored. Optional --no-respect-inline-disables neutralizes eslint-disable / oxlint-disable markers for audit-style runs (dbt-doctor’s own inline directives are controlled separately).

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.

Scores can shift when new rules ship - pin dbt-doctor in CI if you need stable numbers.

Diff and staged modes

  • --diff [base] - changed files vs branch (or "diff": true / "diff": "develop" in config).
  • --staged - index-only; for pre-commit hooks.
  • --full - forces a full scan.

Interactive runs may prompt to scan only changes; CI and --json skip that prompt.

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.

diagnose accepts options such as lint, offline, includePaths, respectInlineDisables. See packages/dbt-doctor/src/api.ts.

Monorepo & contributing

This package is part of the dbt-doctor monorepo. To hack on the CLI locally:

git clone https://github.com/northgraindata/dbt-doctor.git
cd dbt-doctor
pnpm install
pnpm build
node packages/dbt-doctor/bin/dbt-doctor.js /path/to/your/dbt-project

Issues: github.com/northgraindata/dbt-doctor/issues

Who made dbt Doctor?

dbt Doctor is built and maintained by Northgrain Data, a data engineering agency for modern dbt and Snowflake teams. We design, build, test, and improve reliable data systems - and publish open-source tools based on what works in production.

Northgrain Data - the data engineering partner for modern dbt and Snowflake teams

License

This package is MIT - LICENSE. Upstream credit: dbt-doctor is a clone of Million / React Doctor (see the note at the top of this README).

About

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.

Topics

Resources

Stars

22 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages