Most of this is what you'd expect from any serious language extension: completions, hover, go-to-definition, diagnostics. Some of it you didn't know you needed until you see it work.
SQL edit & query
Run queries against your warehouse directly from VS Code: ad-hoc SQL, a full model, or a single CTE in isolation using the model::cte_name convention. Jinja compiles first, so {{ ref() }} and macros work exactly as they do in production.
Results land in a grid with per-column statistics: null counts, distinct values, min/max, mean. Select a range of cells and the status bar shows a live sum and average. Export to CSV, JSON, TSV, or Markdown, copy as-is, or open directly in the SQL editor. Excel-style handling without leaving VS Code.
Ninja
The same parser that powers completions, hover, and diagnostics now enforces your SQL style too. Ninja is a built-in linter and formatter: capitalization, aliasing, layout, structural checks, all running on the AST that's already there. No extra parse cost, no external process.
Keyword casing, trailing commas, implicit aliases, indentation, line length, unused CTEs, all configurable per rule with per-line suppression via -- noqa. Reads your existing .sqlfluff config if you have one.
Fixable rules auto-correct on save or on demand. The rest appear as inline diagnostics, exactly where the violation is. And when you want the full picture, a single command runs diagnostics across every model in the workspace, so you can enforce standards project-wide, not just in open files.
Getting started
- 1Install dbt Anvil from the VS Code Extensions panel, or directly from the Marketplace
- 2Open a folder containing
dbt_project.yml
- 3The extension activates and starts indexing automatically. No setup required.*
* This extension is compatible with Visual Studio Code in its stable release configuration. Compatibility with the stable release does not constitute endorsement of the stable release. The stable release is fine. You should still be on VS Code Insiders. Furthermore, it is assumed that the end user is operating GitHub Copilot Chat at the time of installation, or will do so imminently, or is at least thinking about it. The extension does not require Python as a standalone dependency. It does, however, require a functioning dbt Core installation, the absence of which shall be treated as user error. Said installation will be located, interrogated, and put to work automatically. No configuration is necessary. None was ever necessary. WARNING: use of this software has been linked to sudden and irreversible increases in work satisfaction, compulsive model refactoring, and in rare cases a complete loss of tolerance for bad SQL tooling. The author accepts no liability for productivity gains, existential crises triggered by finally understanding your own data lineage, or any civilisation-ending events that may occur as a direct or indirect consequence of installing a VS Code extension. Side effects include: shipping faster, sleeping better, and occasionally explaining column lineage to your manager using actual facts. If symptoms persist, open an issue. This software is provided free of charge to the end user. All applicable fees have been prepaid in full by the author in the form of blood, sweat, tears, and an unreasonable number of late evenings staring at AST node representations of SQL clauses. No further payment is required. No refunds are available. No refunds have ever been available. This has always been free.
Under the hood
This extension is a fair bit more ambitious than a thin wrapper around a language server. Here's what's in it.
No conflicts. dbt Anvil uses your existing Python environment and your existing dbt installation. It auto-detects your setup (venv, uv, poetry, pipenv, conda, system Python) and bridges the VS Code Node.js world to dbt Core over a JSON process boundary, with nothing to configure. All core dbt operations: parse, compile, run, test, build, seed, snapshot, and query, go through this bridge. No bundled runtimes, no parallel installations, no version mismatches. The one thing it cannot help with is a broken dbt setup. That part is on you.
Terminal monitoring. The extension also monitors your terminals. If a dbt command is detected that would conflict with something the extension is doing, or vice versa, it mediates. Running dbt from two places against the same target is a bad idea, and dbt Anvil knows when that's about to happen.
Not blindly executing dbt. It minimises database communication to only what is strictly necessary. The extension runs against its own separate dbt target. When it does something internally, it doesn't touch your schema.
Aggressive caching at every level. dbt is not invoked unless it needs to be. Parsing results, compiled SQL, column metadata, all cached to disk and reused across restarts. All dbt execution is coordinated through priority queues, because not all operations are equally urgent, and the extension takes advantage of that.
Adapter-aware where it counts. Query execution is optimised for Databricks (using the SQL Statement API directly, bypassing dbt show) and DuckDB (local execution). More adapters are on the way.
Built-in compiler, always running. For operations that do not require dbt at all, dbt Anvil uses its own compiler: a native TypeScript SQL and Jinja parser that runs in-process in the extension host — no subprocess, no worker pool, no startup cost. It re-parses the active document on every keystroke (not on save, every keystroke), providing instant diagnostics as you type. A typical model parses in a few milliseconds. The parser is purpose-built for dbt: one pass handles Jinja and SQL together, with exact source positions through templated code, and it keeps working inside conditional blocks instead of giving up at the first {% if %}.
Everything is toggleable. Some of what dbt Anvil does is opinionated, so every feature can be turned off individually from Settings. Changes take effect immediately, no reload required.
dbt Fusion support is planned. When it arrives, the debugger, profiler, and other execution-dependent features will be available there too. The extension doesn't depend on Python being part of your environment; in a Fusion world it may not be. At work we haven't gotten around to Fusion yet - it's a fairly large migration and we've been putting it off.