Skip to main content

A fast CLI tool for dbt model lineage analysis

Project description

dlin

Crates.io PyPI

dbt lineage analysis CLI that parses SQL files directly. No dbt compile, no Python, no manifest.json.

Builds a dependency graph from ref() and source() calls in SQL. Designed for AI agents and CI pipelines.

Motivation

When I edited dbt models in VS Code, dbt Power User was my go-to companion for navigating lineage. AI agents have no such companion. I watched them grep through dbt projects to find model dependencies. It works, but they end up calling grep repeatedly and relying on fragile string matching to piece together ref() and source() relationships.

dlin is designed to fill that gap: a CLI tool that lets AI agents understand a dbt project's structure without falling back to grep. It is equally useful for humans, and its stdin/stdout interface makes it easy to combine with jq, git diff, and other CLI tools.

To replace grep, speed and size matter. dlin is a small, self-contained binary with no runtime dependencies. It parses SQL directly, evaluates common Jinja patterns without Python, parallelizes file I/O, and caches aggressively.

The key idea behind dlin is that finding the right models fast is what matters most. AI agents can read SQL and trace column-level relationships on their own; the hard part is knowing which models to look at in the first place. So dlin focuses on model-level lineage and makes that as fast as possible.

Install

Cargo (Rust)

cargo install dlin

pip / uv (Python)

For convenience, dlin is also available as a Python package. The installed binary is native and does not require Python at runtime.

pip install dlin-cli   # or: uv tool install dlin-cli

GitHub Releases

Pre-built binaries for Linux, macOS, and Windows are available on the Releases page. You can also use the installer scripts:

macOS / Linux:

curl --proto '=https' --tlsv1.2 -LsSf https://github.com/eitsupi/dlin/releases/latest/download/dlin-installer.sh | sh

Windows (PowerShell):

powershell -ExecutionPolicy Bypass -c "irm https://github.com/eitsupi/dlin/releases/latest/download/dlin-installer.ps1 | iex"

Quick start

# Full lineage graph
dlin graph -p path/to/dbt/project

# Downstream impact analysis
dlin impact orders

# List models as JSON
dlin list -o json --json-fields unique_id,file_path

# Pipe changed files into lineage
git diff --name-only main | dlin graph -o json

Features

  • No dependencies: single binary, no Python, no manifest.json
  • Recursive upstream / downstream: -u N / -d N to control traversal depth
  • Impact analysis with severity: dlin impact scores downstream nodes and flags exposure reachability
  • Composable: stdin accepts model names or file paths; pipe with jq, dlin list, git diff, etc.
  • Agent-friendly: --error-format json emits structured {"level","what","why","hint"} on stderr; --help is designed for tool discovery

Mermaid diagrams

dlin outputs Mermaid flowcharts that render natively on GitHub, GitLab, Notion, and other Markdown environments.

Simplified graphs with --collapse

Automatically remove intermediate nodes to see just the endpoints (nodes with no predecessors or no successors); everything in between becomes transitive "(via N)" edges:

# Collapse intermediate models — only endpoints remain
dlin graph --collapse -o mermaid

# Focal mode: keep only sources, exposures, and specified focus models
# (ignores BFS window pseudo-endpoints — ideal with -u/-d limits)
dlin graph orders --collapse=focal -u 3 -o mermaid
flowchart LR
    exposure_weekly_report>"weekly_report"]
    model_combined_orders["combined_orders"]
    model_order_summary["order_summary"]
    source_raw_customers(["raw.customers"])
    source_raw_orders(["raw.orders"])
    source_raw_payments(["raw.payments"])

    source_raw_customers ==>|"exposure (via 2)"| exposure_weekly_report
    source_raw_orders ==>|"exposure (via 3)"| exposure_weekly_report
    source_raw_orders -.->|"source (via 1)"| model_combined_orders
    source_raw_orders -.->|"source (via 1)"| model_order_summary
    source_raw_payments ==>|"exposure (via 3)"| exposure_weekly_report
    source_raw_payments -.->|"source (via 1)"| model_order_summary

    classDef model fill:#4A90D9,stroke:#333,color:#fff
    classDef source fill:#27AE60,stroke:#333,color:#fff
    classDef exposure fill:#E74C3C,stroke:#333,color:#fff
    class exposure_weekly_report exposure
    class model_combined_orders model
    class model_order_summary model
    class source_raw_customers source
    class source_raw_orders source
    class source_raw_payments source

Positional focus models are always preserved during collapse, so dlin graph orders --collapse keeps orders even if it would otherwise be intermediate.

Pipe to build focused diagrams

Combine dlin list, jq, and dlin graph to extract exactly the nodes you want:

# Staging models → 1 hop downstream, models only, grouped by directory
dlin list -s 'path:models/staging' -o json | jq -r '.[].label' |
  dlin graph -d 1 --node-type model --group-by directory -o mermaid
flowchart LR
    subgraph models_marts["models/marts"]
        model_combined_orders["combined_orders"]
        model_customers["customers"]
        model_order_summary["order_summary"]
        model_orders["orders"]
    end
    subgraph models_staging["models/staging"]
        model_stg_customers["stg_customers"]
        model_stg_online_orders["stg_online_orders"]
        model_stg_orders["stg_orders"]
        model_stg_payments["stg_payments"]
        model_stg_retail_orders["stg_retail_orders"]
    end

    model_orders -->|ref| model_customers
    model_stg_customers -->|ref| model_customers
    model_stg_online_orders -->|ref| model_combined_orders
    model_stg_orders -->|ref| model_order_summary
    model_stg_orders -->|ref| model_orders
    model_stg_payments -->|ref| model_order_summary
    model_stg_payments -->|ref| model_orders
    model_stg_retail_orders -->|ref| model_combined_orders

    classDef model fill:#4A90D9,stroke:#333,color:#fff
    class model_combined_orders model
    class model_customers model
    class model_order_summary model
    class model_orders model
    class model_stg_customers model
    class model_stg_online_orders model
    class model_stg_orders model
    class model_stg_payments model
    class model_stg_retail_orders model

Column names in nodes with --show-columns

Add --show-columns to include column names inside Mermaid node labels — useful for understanding what each model produces at a glance:

dlin graph orders -u 1 -d 0 --show-columns --node-type model,source -o mermaid
flowchart LR
    model_orders["orders<br/>---<br/>order_id, customer_id, order_date, status, total_amount, payment_method"]
    model_stg_orders["stg_orders<br/>---<br/>order_id, customer_id, order_date, status"]
    model_stg_payments["stg_payments<br/>---<br/>payment_id, order_id, amount, payment_method"]

    model_stg_orders -->|ref| model_orders
    model_stg_payments -->|ref| model_orders

    classDef model fill:#4A90D9,stroke:#333,color:#fff
    class model_orders model
    class model_stg_orders model
    class model_stg_payments model

Combines well with --collapse to show rich detail on fewer endpoint nodes.

Other graph options

dlin graph orders -u 2 -d 1                            # focus on specific model
dlin graph -o mermaid --collapse --show-columns        # columns in collapsed nodes
dlin graph orders --collapse=focal -u 3 -o mermaid    # focal: sources + exposures + orders
dlin graph -o mermaid --group-by directory             # group by directory
dlin graph -o mermaid --direction tb                   # top-to-bottom layout
dlin graph --node-type source,exposure                 # filter by node type
dlin graph -o dot | dot -Tsvg > out.svg                # Graphviz rendering

Output formats: ASCII (default), JSON, Mermaid, Graphviz DOT, Plain, SVG, HTML.

Key subcommands

list

dlin list                                                   # all models and sources
dlin list orders -o json --json-fields unique_id,file_path  # specific model as JSON
dlin list --node-type source                                # sources only

impact

$ dlin impact orders
Impact Analysis: orders
==================================================
Overall Severity: CRITICAL

Summary:
  Affected models:    1
  Affected tests:     1
  Affected exposures: 1

Impacted Nodes:
  [critical] weekly_report (exposure, distance: 1)
  [high    ] customers (model, distance: 1) [models/marts/customers.sql]
  [low     ] assert_orders_positive_amount (test, distance: 1)

Filtering

dlin graph -s tag:finance,path:marts  # selector expressions (union)
dlin graph --node-type model,source   # filter by node type

Data sources

dlin aims to work without dbt compile. By default it parses SQL files directly, but it can also leverage a pre-compiled manifest.json for additional accuracy when one is available.

SQL parsing (default): extracts ref() and source() from SQL via regex + Jinja template evaluation. No Python or dbt needed.

Manifest mode (--source manifest): reads a pre-compiled manifest.json for full accuracy with complex Jinja logic.

Limitations of SQL parse mode

  • var() resolves from dbt_project.yml only (--vars CLI overrides not supported)
  • Runtime context (target.type, env_var()) is not evaluated
  • Conditional Jinja branches use default values; non-default paths may be missed

When these limitations matter, use --source manifest.

Credits

Hard fork of dbt-lineage-viewer by Simon Muller (MIT license). The original focused on TUI-based exploration; dlin removes the TUI and targets non-interactive use: scripting, CI, and AI agents.

License

MIT

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

dlin_cli-0.1.1a1.tar.gz (703.7 kB view details)

Uploaded Source

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

dlin_cli-0.1.1a1-py3-none-win_amd64.whl (2.4 MB view details)

Uploaded Python 3Windows x86-64

dlin_cli-0.1.1a1-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (2.5 MB view details)

Uploaded Python 3manylinux: glibc 2.17+ x86-64

dlin_cli-0.1.1a1-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (2.3 MB view details)

Uploaded Python 3manylinux: glibc 2.17+ ARM64

dlin_cli-0.1.1a1-py3-none-macosx_11_0_arm64.whl (2.3 MB view details)

Uploaded Python 3macOS 11.0+ ARM64

dlin_cli-0.1.1a1-py3-none-macosx_10_12_x86_64.whl (2.4 MB view details)

Uploaded Python 3macOS 10.12+ x86-64

File details

Details for the file dlin_cli-0.1.1a1.tar.gz.

File metadata

  • Download URL: dlin_cli-0.1.1a1.tar.gz
  • Upload date:
  • Size: 703.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.11.2 {"installer":{"name":"uv","version":"0.11.2","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for dlin_cli-0.1.1a1.tar.gz
Algorithm Hash digest
SHA256 339cfca5309e975f7d65abf4089d1f62080cc5acb8f7f59e4b50d49e630adfd4
MD5 efabad92674f14c0c57a9a48ed254eeb
BLAKE2b-256 3231ba42853e5b87678a645438e293237e7314aa971f0cca07bcdcc11f1c9be2

See more details on using hashes here.

File details

Details for the file dlin_cli-0.1.1a1-py3-none-win_amd64.whl.

File metadata

  • Download URL: dlin_cli-0.1.1a1-py3-none-win_amd64.whl
  • Upload date:
  • Size: 2.4 MB
  • Tags: Python 3, Windows x86-64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.11.2 {"installer":{"name":"uv","version":"0.11.2","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for dlin_cli-0.1.1a1-py3-none-win_amd64.whl
Algorithm Hash digest
SHA256 1407c4f086a24ee0429145451215b1f999d58276606e3fb40c394c4c756dca1d
MD5 deeb7cc2e26a5f9e628980cadda10207
BLAKE2b-256 7b0b122669311e9be1e1d0f65d81219df0fe115b5adc54b08368e88340657a32

See more details on using hashes here.

File details

Details for the file dlin_cli-0.1.1a1-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

  • Download URL: dlin_cli-0.1.1a1-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
  • Upload date:
  • Size: 2.5 MB
  • Tags: Python 3, manylinux: glibc 2.17+ x86-64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.11.2 {"installer":{"name":"uv","version":"0.11.2","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for dlin_cli-0.1.1a1-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 67018eacbe6648f9c996e1df7bf23ff81b5be80241d56990704e95fd7f2b06f7
MD5 ef69d1842b39347fbcaff2ee2a822822
BLAKE2b-256 572771cd7c854b83b878f65fa677061ea22bb566872044d40597b0f67030d15a

See more details on using hashes here.

File details

Details for the file dlin_cli-0.1.1a1-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.

File metadata

  • Download URL: dlin_cli-0.1.1a1-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
  • Upload date:
  • Size: 2.3 MB
  • Tags: Python 3, manylinux: glibc 2.17+ ARM64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.11.2 {"installer":{"name":"uv","version":"0.11.2","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for dlin_cli-0.1.1a1-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 3a8f72b3d62c778c10cdbee9d56c8bbd2fab71d2ec17d57a5a3c2c92a85dc00f
MD5 85bc07d848b18db3a6871db099e55e2e
BLAKE2b-256 c8017e4afa36772800b1b1085a7202ca199baf8256088f05fc8619ffd7781c01

See more details on using hashes here.

File details

Details for the file dlin_cli-0.1.1a1-py3-none-macosx_11_0_arm64.whl.

File metadata

  • Download URL: dlin_cli-0.1.1a1-py3-none-macosx_11_0_arm64.whl
  • Upload date:
  • Size: 2.3 MB
  • Tags: Python 3, macOS 11.0+ ARM64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.11.2 {"installer":{"name":"uv","version":"0.11.2","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for dlin_cli-0.1.1a1-py3-none-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 36cb82e700aa68b240ad900152b66ab3369bca95603e1af0f6f515ec60c14021
MD5 44a4fce3de3397987541d89961fdbb23
BLAKE2b-256 29e527d2e5fcd0997bb003d161ddee2867ecf9d845959ebc1444c0bb3464b6e9

See more details on using hashes here.

File details

Details for the file dlin_cli-0.1.1a1-py3-none-macosx_10_12_x86_64.whl.

File metadata

  • Download URL: dlin_cli-0.1.1a1-py3-none-macosx_10_12_x86_64.whl
  • Upload date:
  • Size: 2.4 MB
  • Tags: Python 3, macOS 10.12+ x86-64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.11.2 {"installer":{"name":"uv","version":"0.11.2","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for dlin_cli-0.1.1a1-py3-none-macosx_10_12_x86_64.whl
Algorithm Hash digest
SHA256 b0b7da1c24de5d76f7b09dadbc5ab9d604e07b395877ba898f903b10b3f0218d
MD5 f383529ebc79b3459184a7f68bfd7263
BLAKE2b-256 461080cac98f3adcc423e98536b81d4ef8abc1d008df8905f9e9e1d2950aba9e

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page