Pretty terminal lineage tree for dbt selectors. Run a selector, get a readable tree of the resulting DAG right in your terminal — no docs server, no browser.
dbt-tree "my_model+"dbt-tree forwards the selector verbatim to dbt ls, so every dbt selector
works exactly as it does in dbt itself: model+, +model, +model+,
2+model+3, tag:nightly+, path:models/marts, set unions, and so on.
- A working dbt-core install that you can run as
dbt(any virtualenv tool is fine —venv,virtualenv,conda,poetry,uv, …). The only requirement is that thedbtexecutable is reachable (active venv, onPATH, or via$DBT_TREE_DBT/--dbt-executable). - Python 3.10+.
dbt ls is parse-only, so no warehouse connection is needed to draw the tree.
Install into the same environment as your dbt so they share a PATH:
pip install dbt-tree
# or, latest from source:
pip install "git+https://github.com/KarthikRajashekaran/dbt-tree.git"dbt itself is not a Python dependency — dbt-tree shells out to your
existing dbt rather than pinning a version.
Resolution order:
--dbt-executable$DBT_TREE_DBT- the active virtualenv (
$VIRTUAL_ENV/bin/dbt) — so once you activate your dbt venv, dbt-tree uses the same dbt as your shell dbtonPATH
dbt-tree prefers dbt-core and will skip a dbt Fusion binary when a core
install is available (Fusion's stricter parsing and different ls surface aren't
supported yet).
# 1. Activate the environment where your dbt-core lives (any venv tool works):
source /path/to/your/dbt-venv/bin/activate # or: conda activate <env>, poetry shell, ...
# 2. Confirm dbt-core is runnable (should NOT say "dbt-fusion"):
dbt --version
# 3. Install dbt-tree into that same environment:
pip install dbt-tree
# 4. From inside your dbt project, draw lineage:
cd /path/to/your/dbt_project
dbt-tree "my_model+" # downstream
dbt-tree "+my_model" # upstream
dbt-tree "+my_model+" # both directionsNo warehouse connection is needed (dbt ls only parses the project). If you'd
rather not activate anything, point dbt-tree straight at dbt instead:
dbt-tree "my_model+" --dbt-executable /path/to/dbt-core/bin/dbt \
--project-dir /path/to/your/dbt_project --target dev# Downstream lineage
dbt-tree "my_model+"
# Upstream lineage
dbt-tree "+my_model"
# Scope / dbt passthrough
dbt-tree "tag:nightly+" --target prod --project-dir dbt/my_projectExample output:
my_model (view) *
└── stg_orders (table)
└── int_orders_joined (table)
├── fct_orders (table)
│ ├── mart_revenue (table)
│ └── ...
└── fct_order_items (table)
The originally-selected model is marked with *. Nodes are colored by resource
type; the suffix shows materialization (table/view) or resource type
(source/seed/snapshot).
The tree is rooted so the focal model is always at the top:
model+(downstream) — root is the model, children are its descendants.+model(upstream) — root is the model, children are its ancestors (up to sources/seeds).+model+(both) — two sections:▲ ancestorsthen▼ descendants.
- Runs
dbt --quiet ls --output json --output-keys ... --select <selector>. - Keeps models, sources, seeds, and snapshots (tests off unless
--include-tests). - Builds child adjacency within the selected set, finds roots, and expands a
duplicated tree (Unix
treestyle) with cycle and node-count guards. - Renders a
richtree (duplicating shared subtrees,tree-command style).
| flag | default | meaning |
|---|---|---|
--target |
— | dbt target |
--project-dir |
— | dbt project directory |
--profiles-dir |
— | dbt profiles directory |
--dbt-executable |
dbt |
path to dbt |
--include-tests |
off | include data/unit tests as nodes |
--max-depth |
0 |
limit depth (0 = unlimited) |
--max-nodes |
5000 |
safety cap on rendered nodes |
--no-color |
off | disable color in plain output |
Unknown flags are forwarded to dbt ls as an escape hatch.
- Single project. Lineage covers whatever
dbt lsresolves in the active project; it does not stitch across sibling projects in a monorepo. - Selector parsing is dbt's, so behavior matches your installed dbt version.
pip install -e ".[dev]"
pytest
ruff check .Apache-2.0