{"id":48033361,"url":"https://github.com/eitsupi/dlin","last_synced_at":"2026-04-04T13:56:34.010Z","repository":{"id":343255257,"uuid":"1173509602","full_name":"eitsupi/dlin","owner":"eitsupi","description":"dbt lineage analysis CLI that parses SQL files directly, written in Rust. No dbt compile, no manifest.json. Designed for AI agents and CI pipelines.","archived":false,"fork":false,"pushed_at":"2026-03-26T15:22:59.000Z","size":1399,"stargazers_count":2,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-03-26T17:43:18.474Z","etag":null,"topics":["cli","dbt","dbt-core","rust"],"latest_commit_sha":null,"homepage":"","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/eitsupi.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-03-05T12:54:21.000Z","updated_at":"2026-03-26T15:23:09.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/eitsupi/dlin","commit_stats":null,"previous_names":["eitsupi/dlin"],"tags_count":3,"template":false,"template_full_name":null,"purl":"pkg:github/eitsupi/dlin","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/eitsupi%2Fdlin","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/eitsupi%2Fdlin/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/eitsupi%2Fdlin/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/eitsupi%2Fdlin/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/eitsupi","download_url":"https://codeload.github.com/eitsupi/dlin/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/eitsupi%2Fdlin/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31402276,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-04T10:20:44.708Z","status":"ssl_error","status_checked_at":"2026-04-04T10:20:06.846Z","response_time":60,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["cli","dbt","dbt-core","rust"],"created_at":"2026-04-04T13:56:33.918Z","updated_at":"2026-04-04T13:56:33.992Z","avatar_url":"https://github.com/eitsupi.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"# dlin\n\n[![Crates.io](https://img.shields.io/crates/v/dlin)](https://crates.io/crates/dlin)\n[![PyPI](https://img.shields.io/pypi/v/dlin-cli)](https://pypi.org/project/dlin-cli/)\n[![Ask DeepWiki](https://deepwiki.com/badge.svg)](https://deepwiki.com/eitsupi/dlin)\n\ndbt lineage analysis CLI that parses SQL files directly. No `dbt compile`, no Python, no `manifest.json`.\n\nBuilds a dependency graph from `ref()` and `source()` calls in SQL. Designed for AI agents and CI pipelines.\n\n## Motivation\n\nWhen I edited dbt models in VS Code, [dbt Power User](https://marketplace.visualstudio.com/items?itemName=innoverio.vscode-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.\n\ndlin 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.\n\nTo 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.\n\nThe 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.\n\n## Install\n\n### Cargo (Rust)\n\n```sh\ncargo install dlin\n```\n\n### pip / uv (Python)\n\nFor convenience, dlin is also available as a Python package. The installed binary is native and does not require Python at runtime.\n\n```sh\npip install dlin-cli   # or: uv tool install dlin-cli\n```\n\n### GitHub Releases\n\nPre-built binaries for Linux, macOS, and Windows are available on the [Releases](https://github.com/eitsupi/dlin/releases) page. You can also use the installer scripts:\n\nmacOS / Linux:\n\n```sh\ncurl --proto '=https' --tlsv1.2 -LsSf https://github.com/eitsupi/dlin/releases/latest/download/dlin-installer.sh | sh\n```\n\nWindows (PowerShell):\n\n```powershell\npowershell -ExecutionPolicy Bypass -c \"irm https://github.com/eitsupi/dlin/releases/latest/download/dlin-installer.ps1 | iex\"\n```\n\n## Quick start\n\n```sh\n# Full lineage graph\ndlin graph -p path/to/dbt/project\n\n# Downstream impact analysis\ndlin impact orders\n\n# List models as JSON\ndlin list -o json --json-fields unique_id,file_path\n\n# Pipe changed files into lineage\ngit diff --name-only main | dlin graph -o json\n```\n\n## AI agent integration\n\nNo MCP server or tool configuration needed.\nJust install dlin and add the following to your `AGENTS.md`, `CLAUDE.md`, or system prompt:\n\n````md\n## dbt project structure analysis\n\nUse `dlin` to explore dbt model dependencies.\nDo NOT grep/cat/find through SQL files.\n\n```bash\ndlin summary                                           # Project overview (start here)\ndlin graph \u003cmodel\u003e -u 2 -d 1 -q                        # Upstream/downstream lineage\ndlin impact \u003cmodel\u003e                                    # Downstream impact with severity\ndlin list -o json --json-fields unique_id,sql_content  # Read SQL content\ngit diff --name-only main | dlin graph -q              # Lineage of changed files\n```\n\nFor full option reference: `dlin --help`, `dlin graph --help`, etc.\n````\n\nThe key line is **\"Do NOT grep/cat/find through SQL files\"** — without it, agents default to familiar tools. `dlin --help` is designed for tool discovery, so the prompt can stay minimal.\n\n## Features\n\n- **No dependencies**: single binary, no Python, no `manifest.json`\n- **Recursive upstream / downstream**: `-u N` / `-d N` to control traversal depth\n- **Impact analysis with severity**: `dlin impact` scores downstream nodes and flags exposure reachability\n- **Composable**: stdin accepts model names or file paths; pipe with `jq`, `dlin list`, `git diff`, etc.\n- **Agent-friendly**: `--error-format json` emits structured `{\"level\",\"what\",\"why\",\"hint\"}` on stderr; `--help` is designed for tool discovery\n\n## Mermaid diagrams\n\ndlin outputs Mermaid flowcharts that render natively on GitHub, GitLab, Notion, and other Markdown environments.\n\n### Simplified graphs with `--collapse`\n\nAutomatically remove intermediate nodes to see just the endpoints (nodes with no predecessors or no successors); everything in between becomes transitive \"(via N)\" edges:\n\n```sh\n# Collapse intermediate models — only endpoints remain\ndlin graph --collapse -o mermaid\n\n# Focal mode: keep only sources, exposures, and specified focus models\n# (ignores BFS window pseudo-endpoints — ideal with -u/-d limits)\ndlin graph orders --collapse=focal -u 3 -o mermaid\n```\n\n```mermaid\nflowchart LR\n    exposure_weekly_report\u003e\"weekly_report\"]\n    model_combined_orders[\"combined_orders\"]\n    model_order_summary[\"order_summary\"]\n    source_raw_customers([\"raw.customers\"])\n    source_raw_orders([\"raw.orders\"])\n    source_raw_payments([\"raw.payments\"])\n\n    source_raw_customers ==\u003e|\"exposure (via 2)\"| exposure_weekly_report\n    source_raw_orders ==\u003e|\"exposure (via 3)\"| exposure_weekly_report\n    source_raw_orders -.-\u003e|\"source (via 1)\"| model_combined_orders\n    source_raw_orders -.-\u003e|\"source (via 1)\"| model_order_summary\n    source_raw_payments ==\u003e|\"exposure (via 3)\"| exposure_weekly_report\n    source_raw_payments -.-\u003e|\"source (via 1)\"| model_order_summary\n\n    classDef model fill:#4A90D9,stroke:#333,color:#fff\n    classDef source fill:#27AE60,stroke:#333,color:#fff\n    classDef exposure fill:#E74C3C,stroke:#333,color:#fff\n    class exposure_weekly_report exposure\n    class model_combined_orders model\n    class model_order_summary model\n    class source_raw_customers source\n    class source_raw_orders source\n    class source_raw_payments source\n```\n\nPositional focus models are always preserved during collapse, so `dlin graph orders --collapse` keeps `orders` even if it would otherwise be intermediate.\n\n### Pipe to build focused diagrams\n\nCombine `dlin list`, `jq`, and `dlin graph` to extract exactly the nodes you want:\n\n```sh\n# Staging models → 1 hop downstream, models only, grouped by directory\ndlin list -s 'path:models/staging' -o json | jq -r '.[].label' |\n  dlin graph -d 1 --node-type model --group-by directory -o mermaid\n```\n\n```mermaid\nflowchart LR\n    subgraph models_marts[\"models/marts\"]\n        model_combined_orders[\"combined_orders\"]\n        model_customers[\"customers\"]\n        model_order_summary[\"order_summary\"]\n        model_orders[\"orders\"]\n    end\n    subgraph models_staging[\"models/staging\"]\n        model_stg_customers[\"stg_customers\"]\n        model_stg_online_orders[\"stg_online_orders\"]\n        model_stg_orders[\"stg_orders\"]\n        model_stg_payments[\"stg_payments\"]\n        model_stg_retail_orders[\"stg_retail_orders\"]\n    end\n\n    model_orders --\u003e|ref| model_customers\n    model_stg_customers --\u003e|ref| model_customers\n    model_stg_online_orders --\u003e|ref| model_combined_orders\n    model_stg_orders --\u003e|ref| model_order_summary\n    model_stg_orders --\u003e|ref| model_orders\n    model_stg_payments --\u003e|ref| model_order_summary\n    model_stg_payments --\u003e|ref| model_orders\n    model_stg_retail_orders --\u003e|ref| model_combined_orders\n\n    classDef model fill:#4A90D9,stroke:#333,color:#fff\n    class model_combined_orders model\n    class model_customers model\n    class model_order_summary model\n    class model_orders model\n    class model_stg_customers model\n    class model_stg_online_orders model\n    class model_stg_orders model\n    class model_stg_payments model\n    class model_stg_retail_orders model\n```\n\n### Column names in nodes with `--show-columns`\n\nAdd `--show-columns` to include column names inside Mermaid node labels — useful for understanding what each model produces at a glance:\n\n```sh\ndlin graph orders -u 1 -d 0 --show-columns --node-type model,source -o mermaid\n```\n\n```mermaid\nflowchart LR\n    model_orders[\"orders\u003cbr/\u003e---\u003cbr/\u003eorder_id, customer_id, order_date, status, total_amount, payment_method\"]\n    model_stg_orders[\"stg_orders\u003cbr/\u003e---\u003cbr/\u003eorder_id, customer_id, order_date, status\"]\n    model_stg_payments[\"stg_payments\u003cbr/\u003e---\u003cbr/\u003epayment_id, order_id, amount, payment_method\"]\n\n    model_stg_orders --\u003e|ref| model_orders\n    model_stg_payments --\u003e|ref| model_orders\n\n    classDef model fill:#4A90D9,stroke:#333,color:#fff\n    class model_orders model\n    class model_stg_orders model\n    class model_stg_payments model\n```\n\nCombines well with `--collapse` to show rich detail on fewer endpoint nodes.\n\n### Other graph options\n\n```sh\ndlin graph orders -u 2 -d 1                            # focus on specific model\ndlin graph -o mermaid --collapse --show-columns        # columns in collapsed nodes\ndlin graph orders --collapse=focal -u 3 -o mermaid    # focal: sources + exposures + orders\ndlin graph -o mermaid --group-by directory             # group by directory\ndlin graph -o mermaid --direction tb                   # top-to-bottom layout\ndlin graph --node-type source,exposure                 # filter by node type\ndlin graph -o dot | dot -Tsvg \u003e out.svg                # Graphviz rendering\n```\n\nOutput formats: ASCII (default), JSON, Mermaid, Graphviz DOT, Plain, SVG, HTML.\n\n## Key subcommands\n\n### `list`\n\n```sh\ndlin list                                                   # all models and sources\ndlin list orders -o json --json-fields unique_id,file_path  # specific model as JSON\ndlin list --node-type source                                # sources only\n```\n\n### `impact`\n\n```sh\n$ dlin impact orders\nImpact Analysis: orders\n==================================================\nOverall Severity: CRITICAL\n\nSummary:\n  Affected models:    1\n  Affected tests:     1\n  Affected exposures: 1\n\nImpacted Nodes:\n  [critical] weekly_report (exposure, distance: 1)\n  [high    ] customers (model, distance: 1) [models/marts/customers.sql]\n  [low     ] assert_orders_positive_amount (test, distance: 1)\n```\n\n## Filtering\n\n```sh\ndlin graph -s tag:finance,path:marts  # selector expressions (union)\ndlin graph --node-type model,source   # filter by node type\n```\n\n## Data sources\n\ndlin 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.\n\n**SQL parsing (default)**: extracts `ref()` and `source()` from SQL via regex + Jinja template evaluation. No Python or dbt needed.\n\n**Manifest mode** (`--source manifest`): reads a pre-compiled `manifest.json` for full accuracy with complex Jinja logic.\n\n### Limitations of SQL parse mode\n\n- `var()` resolves from `dbt_project.yml` only (`--vars` CLI overrides not supported)\n- Runtime context (`target.type`, `env_var()`) is not evaluated\n- Conditional Jinja branches use default values; non-default paths may be missed\n\nWhen these limitations matter, use `--source manifest`.\n\n## Credits\n\nHard fork of [dbt-lineage-viewer](https://github.com/sipemu/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.\n\n## License\n\nMIT\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Feitsupi%2Fdlin","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Feitsupi%2Fdlin","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Feitsupi%2Fdlin/lists"}