A smoother dbt workflow, without leaving VS Code — and without your SQL ever leaving your machine.
What is dbt Forge?
dbt Forge is a VS Code extension for data engineers working on dbt projects (built and tested against dbt-fabric / Microsoft Fabric, but not tied to it). It fills the gaps left by existing dbt tooling — column-level autocomplete, an interactive lineage graph, and one-click build shortcuts — while keeping everything 100% local.
Nothing is sent anywhere. No account, no API key, no third-party backend. dbt Forge only reads the files your own dbt already produces (manifest.json, catalog.json, compiled SQL) and runs dbt through your own project's Python environment.
Features
| Feature | Description | |
|---|---|---|
| 🔗 | ref()/source() autocomplete | Suggests model, seed, snapshot and source names as you type inside {{ ref('... / {{ source('...', '... |
| ⚡ | Snippet expansion | Type ref or source in plain SQL to expand into the full {{ ref("") }} tag, cursor ready to autocomplete |
| 🧭 | Go to Definition | Ctrl+click a ref()/source()/macro call to jump straight to the file it resolves to — a model's or macro's .sql, a seed's .csv |
| 🔍 | Find All References | Shift+F12 (or right-click) on a model, source, or macro to list every call site across the project |
| 💬 | Hover documentation | Hover a ref()/source()/macro call to see its description (and a macro's argument signature) straight from the manifest |
| ⚠️ | Broken ref()/source() diagnostics | Warns in the Problems panel (and inline) when a ref()/source() call doesn't resolve against the manifest — e.g. a typo or a renamed/deleted model |
| 🔤 | Column autocomplete | Suggests column names after alias., resolved from catalog.json (requires dbt docs generate — see below) and from same-file CTEs |
| 🌳 | Parents / Children / Tests panel | Sidebar view of the current model's direct dependencies and dependents, from the manifest's dependency graph |
| 🕸️ | Interactive lineage graph | Click-to-expand upstream/downstream graph (React Flow) — starts at the current model, seed or snapshot, no giant unreadable diagram dumped on you. Each node shows its materialization and wears the node_color your project declares |
| 👁️ | Compiled SQL preview | Read-only, side-by-side preview of the compiled SQL dbt actually runs |
| 📊 | Data preview | Ctrl+Enter on a model to run dbt show and read the rows in a Data Preview tab in the bottom panel — works on models that were never materialized, and on ephemeral ones |
| 🧩 | Per-CTE preview | A preview button on every CTE, to inspect an intermediate step without commenting out the rest of the query |
| 🚀 | Build / Test shortcuts | CodeLens and sidebar buttons for Build Upstream, Build Downstream, Test, and Build Project — run through your project's own venv |
| 🔀 | Environment switching | Status bar picker over the profiles in your profiles.yml — every dbt command dbt Forge runs then carries that --profile/--target, so a dev branch can point at a different Fabric workspace than main |
| 📄 | Compile This File | Compiles only the open model (dbt compile --select path:<file>) — the fast way to get a just-created model into the manifest, without a full-project compile |
| 🏷️ | Tags panel | Every tag declared in the project, expandable to its resources, with one-click Build / Build Upstream / Build Downstream / Test per tag |
Getting Started
Prerequisites
- VS Code 1.85+
- A dbt project (
dbt_project.yml) with its own Python virtual environment (dbt-core + your adapter installed inside it) manifest.jsongenerated at least once (dbt compileordbt build) for autocomplete/lineage/panels to have datacatalog.jsongenerated (dbt docs generate, or the Generate Docs button) for column autocomplete on already-built models
Installation
From the VS Code Marketplace — open the Extensions view (Ctrl+Shift+X), search for dbt Forge, and click Install. Or, from a terminal:
code --install-extension evolve-data.dbtforge
The extension is also on the Marketplace page, and activates on its own as soon as the folder you open contains a dbt_project.yml.
(a release download, or your own build)
code --install-extension dbtforge-0.11.0.vsix
From source(to hack on the extension)
git clone https://github.com/Y0hannH/dbtforge
cd dbtforge
npm install
npm run compile
Then press F5 in VS Code to launch an Extension Development Host with dbt Forge loaded, and open your dbt project in that window. npm test runs the unit suite; npx vsce package produces an installable .vsix.
First Run
- Open your dbt project folder (containing
dbt_project.yml, or nested inside a larger workspace) - Set
dbtForge.pythonPathto your project's venv Python (e.g.C:/path/to/project/.venv/Scripts/python.exe) - Run
dbt compile(ordbt build) at least once somanifest.jsonexists - Run dbt Forge: Generate Docs (the 📖 button in the panel's title bar) so
catalog.jsonexists — column autocomplete needs it - Open a model
.sqlfile — autocomplete, CodeLens, and the Parents/Children/Tests panel activate automatically
Column autocomplete: what it needs
Column suggestions come from two independent paths, which explains why they sometimes appear and sometimes don't:
| You type | Where the columns come from | Requires |
|---|---|---|
my_cte. |
The CTE's own SELECT list, parsed from the open file |
Nothing — works offline, on an unbuilt model |
m. where m aliases a model/source |
catalog.json |
dbt docs generate, and the model must have been built |
Two things trip people up:
catalog.jsonis only written bydbt docs generate. Neitherdbt compile, nordbt run, nordbt buildproduces or refreshes it. A model can be perfectly compiled and still have no column suggestions. Use the Generate Docs button, then re-run it whenever columns change.- The alias is mandatory.
from {{ ref('orders') }} ogives youo.;from {{ ref('orders') }}with no alias gives you nothing to type before the dot.
Also note that the alias must sit right after a single-argument ref()/source() call — ref('package', 'model'), ref('model', version=2), and calls split across lines aren't detected yet.
If nothing is suggested, dbt Forge stays silent rather than guessing. Check those conditions in order.
Architecture
| Layer | Stack |
|---|---|
| Extension Host | TypeScript + VS Code Extension API |
| Lineage Webview | React + React Flow + dagre (auto-layout), bundled locally — no CDN |
| Data Source | Reads manifest.json / catalog.json / target/compiled/*.sql directly, with a file watcher to stay in sync. profiles.yml is read (never written) to list the environments you can switch between |
| dbt Execution | Runs the dbt executable from your configured venv (Scripts//bin/) in the integrated terminal — except data preview, which spawns dbt show directly so it can read the rows back |
Commands
| Command | Description |
|---|---|
dbtForge.generateDocs |
dbt docs generate — writes catalog.json, which column autocomplete reads |
dbtForge.refreshIndex |
Re-read manifest.json / catalog.json from disk (does not run dbt) |
dbtForge.compileFile |
dbt compile --select path:<file> for the open file — works even if it isn't in the manifest yet |
dbtForge.parseProject |
dbt parse — regenerates manifest.json without compiling SQL or hitting the warehouse |
dbtForge.compileProject |
dbt compile for the whole project |
dbtForge.buildModel |
dbt build --select model for the open model, without upstream or downstream |
dbtForge.buildUpstream |
dbt build --select +model for the open model |
dbtForge.buildDownstream |
dbt build --select model+ for the open model |
dbtForge.testModel |
dbt test --select model for the open model |
dbtForge.buildProject |
dbt build for the whole project |
dbtForge.buildFolder |
dbt build --select path:<folder> for all models in a right-clicked folder |
dbtForge.buildFolderUpstream |
dbt build --select +path:<folder> — folder's models + upstream parents |
dbtForge.buildFolderDownstream |
dbt build --select path:<folder>+ — folder's models + downstream children |
dbtForge.buildTag |
dbt build --select tag:<tag> — every resource carrying the tag |
dbtForge.buildTagUpstream |
dbt build --select +tag:<tag> — the tag's resources + upstream parents |
dbtForge.buildTagDownstream |
dbt build --select tag:<tag>+ — the tag's resources + downstream children |
dbtForge.testTag |
dbt test --select tag:<tag> |
dbtForge.refreshTags |
Re-read the tag list from the loaded manifest |
dbtForge.previewCompiledSql |
Open the compiled SQL for the open model, read-only |
dbtForge.previewData |
dbt show for the open model — rows land in the Data Preview panel (Ctrl+Enter / Cmd+Enter) |
dbtForge.previewCte |
dbt show for one CTE of the open model — invoked from the CodeLens on the CTE itself |
dbtForge.rerunPreview |
Re-run the last data preview |
dbtForge.showLineage |
Open the interactive lineage graph for the open model, seed or snapshot |
dbtForge.selectProfile |
Switch the profile/target dbt Forge runs dbt with (also on the status bar) |
Configuration
| Setting | Default | Description |
|---|---|---|
dbtForge.pythonPath |
"" |
Path to the Python executable inside your dbt project's venv. Empty falls back to dbt on PATH |
dbtForge.projectDir |
"" |
Path to the dbt project root. Auto-detected (including nested inside a larger workspace) if left empty |
dbtForge.manifestPath |
target/manifest.json |
Path to manifest.json, relative to the project root |
dbtForge.catalogPath |
target/catalog.json |
Path to catalog.json, relative to the project root |
dbtForge.compiledDir |
target/compiled |
Path to the compiled models directory, relative to the project root |
dbtForge.profilesDir |
"" |
Directory holding profiles.yml, for the environment picker. Empty looks where dbt does: DBT_PROFILES_DIR, the project root, then ~/.dbt. When set, it is also passed as --profiles-dir |
dbtForge.previewRowLimit |
100 |
Rows a data preview asks dbt for (dbt show --limit). -1 fetches every row |
Local Data & Privacy
dbt Forge does not collect any data and has no network calls of its own:
- Reads
manifest.json,catalog.json, and compiled SQL directly from your project'starget/folder - Reads
profiles.ymlto list the profiles and targets you can switch between. It is only ever read, never modified, and nothing from it — credentials included — leaves your machine or is written to your settings; switching environments only changes the--profile/--targetflags on the command line - Your environment choice is stored in VS Code's workspace state, not in a committed
.vscode/settings.json - Runs
dbtthrough your own configured Python environment, in your own integrated terminal - Data preview queries your warehouse — it runs
dbt showthrough your own venv and your own profile, so rows travel between your warehouse and your machine exactly as they would if you randbt showyourself. The extension stores no credentials and opens no connection of its own, but a preview is not an offline operation: it costs a query against whichever target you are pointed at - No telemetry, no backend, no external service — everything happens on your machine
Roadmap
✅ Core (v1)
ref()/source() autocomplete, Go to Definition, column autocomplete (aliases + CTEs), Parents/Children/Tests panel, build/test shortcuts, compiled SQL preview, interactive lineage graph.
✅ v0.4
Find All References and Go to Definition for macros, in addition to models/sources.
✅ v0.5
Environment switching: pick a profile/target from the status bar, and every dbt command runs against it.
✅ v0.6
Generate Docs command, so the catalog.json column autocomplete depends on can be produced from the editor.
✅ v0.7
Hover documentation for models/sources/macros, and Problems-panel diagnostics for broken ref()/source() calls.
✅ v0.8
Single-file compile (dbt compile --select path:<file>) and dbt parse so a just-created model gets indexed without a full-project run, an actionable welcome view on the relatives panel, and immediate panel/CodeLens refresh on manifest reload.
✅ v0.9
Tags panel: build or test every resource carrying a tag, straight from the sidebar.
✅ v0.10
Data preview: dbt show for the open model or any of its CTEs, rendered in a Data Preview tab in the bottom panel.
✅ v0.11
ref() resolving to seeds and snapshots (not models only), lineage that opens on a seed, node boxes sized from their own name, and lineage nodes showing their materialization and node_color.
🔲 Next
- Configurable lineage depth / filtering for very large projects
- Multi-project workspace polish (multiple dbt projects in one workspace)
Non-goals
dbt Forge stays small on purpose. One question decides what goes in:
Does the feature need to know your dbt project?
If it has to read manifest.json, catalog.json or your dependency graph to be useful, it belongs here — nobody else can do it as well. If it works the same on any SQL file, it is somebody else's extension, and pulling it in would only make this one heavier at doing what it is actually for.
So these are deliberately out of scope, not "not yet":
| Not in scope | Use instead |
|---|---|
| Jinja / SQL syntax highlighting | Better Jinja — mature, and it covers .sql, .yml and .md |
| SQL formatting and linting | sqlfmt, SQLFluff, or your editor's own formatter |
| A warehouse browser or general SQL client | A warehouse-specific extension. Data preview here goes through dbt show and nothing else — dbt Forge opens no connection of its own |
| dbt Cloud, remote execution, AI assistance | Not planned in any form. Everything runs locally through your own venv, and nothing leaves your machine (see Local Data & Privacy) |
A request that falls on the wrong side of that line is not a bad idea — it is usually a good idea for a different extension. Where the underlying need does touch the project (say, resolving a doc() to the block that defines it, rather than colouring the {% docs %} tag), that is the version worth opening an issue for.
Contributing
The project is under active development.
- Fork → branch → PR
- Open an issue to discuss a feature before coding
- Follow the existing naming conventions
License
MIT © 2026 Evolve — Yohann
Built with ♥ by Evolve