QUICKSTART
1. INSTALL DVT
pip install dvt-core
Or with uv:
uv add dvt-core
Requires Python 3.9+ on macOS (x86_64, arm64) or Linux (x86_64).
2. LOG IN
DVT requires authentication. Run dvt login to open your browser and sign in with your getdvt.net account:
dvt login
This opens a browser window for authentication. Once complete, your credentials are stored at ~/.dvt/credentials.json and all CLI commands are unlocked.
Check your auth status anytime with dvt status.
3. CREATE YOUR PROJECT
dvt init my_project cd my_project
This scaffolds a new DVT project with the standard dbt directory structure: models, seeds, tests, snapshots, and macros.
4. CONFIGURE CONNECTIONS
Before anything else, define your database connections in ~/.dvt/profiles.yml. This is where DVT learns about your databases. See the profiles.yml guide for full details.
# ~/.dvt/profiles.yml
my_project:
target: pg_dev # default target
outputs:
# Default target — all pushdown models run here
pg_dev:
type: postgres
host: localhost
port: 5432
user: analyst
password: "{{ env_var('PG_PASSWORD') }}"
dbname: analytics
schema: public
threads: 4
# External connection — MySQL operational database
mysql_ops:
type: mysql
host: mysql.internal.com
port: 3306
user: readonly
password: "{{ env_var('MYSQL_PASSWORD') }}"
schema: operations
# External connection — Snowflake warehouse
sf_warehouse:
type: snowflake
account: xy12345.us-east-1
user: DVT_USER
password: "{{ env_var('SF_PASSWORD') }}"
database: PROD_DB
schema: RAW
warehouse: COMPUTE_WH5. BOOTSTRAP YOUR ENVIRONMENT
Run dvt sync to automatically install all required database drivers, DuckDB extensions, cloud SDKs, and the Sling binary based on your profiles.yml:
dvt sync
Then verify all connections are reachable:
dvt debug
6. DEFINE SOURCES
Create a sources.yml file in your models directory to map external databases to source references. See the sources.yml guide for full details.
# models/staging/sources.yml
version: 2
sources:
- name: crm
connection: mysql_ops # external — points to profiles.yml
tables:
- name: customers
- name: orders
- name: warehouse
connection: sf_warehouse # external — points to profiles.yml
tables:
- name: invoices
- name: analytics
# NO connection — lives on the default target (pg_dev)
schema: public
tables:
- name: seed_categories7. WRITE MODELS
Create SQL models that reference your sources. DVT automatically detects which execution path to use based on where each source lives.
Pushdown model — all sources on the default target, runs as native PostgreSQL:
-- models/staging/stg_categories.sql
-- All sources on default target → adapter pushdown
-- SQL dialect: PostgreSQL
{{ config(materialized='table') }}
SELECT id, name, parent_id
FROM {{ source('analytics', 'seed_categories') }}Extraction model — cross-engine sources, runs in DuckDB:
-- models/marts/cross_engine_report.sql
-- Sources on different engines → extraction via Sling + DuckDB
-- SQL dialect: DuckDB (Postgres-like)
{{ config(materialized='table') }}
SELECT
c.customer_name,
c.email,
o.order_date,
o.total_amount
FROM {{ source('crm', 'customers') }} c -- MySQL
JOIN {{ source('warehouse', 'invoices') }} o -- Snowflake
ON c.customer_id = o.customer_id
WHERE o.order_date >= '2024-01-01'8. LOAD SEEDS, RUN, TEST
# Load CSV seed data (Sling-based, 10-100x faster than dbt) dvt seed # Run all models dvt run # Run tests dvt test # Or do everything in DAG order dvt build
9. GENERATE DOCUMENTATION
dvt docs generate dvt docs serve
Opens the DVT data catalog — a futuristic dark-themed UI with engine-colored lineage graphs, column metadata from all engines, and cross-engine source documentation.
PROJECT STRUCTURE
my_project/ ├── dbt_project.yml # Project configuration ├── models/ │ ├── staging/ # Source-aligned models + sources.yml │ ├── intermediate/ # Business logic │ └── marts/ # Final tables/views ├── seeds/ # CSV files ├── tests/ # Custom tests ├── snapshots/ # SCD2 snapshots ├── macros/ # Reusable SQL └── target/ # Build artifacts (gitignored)