dbt Skill for Claude
Comprehensive dbt guidance: project structure, modeling, testing, CI/CD, production patterns. Targets Snowflake and BigQuery. Beginner-friendly with progressive scaling.
When to Use
Activate when: creating/modifying dbt models, choosing materializations, structuring layers, setting up tests, implementing CI/CD, configuring sources/freshness, writing Jinja macros, reviewing dbt projects, making analytics engineering decisions.
Skip when: basic SQL syntax, warehouse admin, raw pipeline config (Fivetran/Airbyte), BI tool config.
Core Principles
- DRY via ref()/source() -- never hardcode table names
- Single Source of Truth -- each concept defined once; staging = entry point, marts = consumer interface
- Idempotent Transformations --
dbt run twice produces identical results
- Test Everything -- every model has at minimum PK uniqueness and not-null tests
- Progressive Complexity -- start with views/tables, add complexity when volume demands it
Project Structure
dbt_project/
├── dbt_project.yml
├── packages.yml
├── profiles.yml # local only, not committed
├── models/
│ ├── staging/ # 1:1 with source tables
│ │ └── <source>/
│ │ ├── _<source>__models.yml
│ │ ├── _<source>__sources.yml
│ │ └── stg_<source>__<entity>.sql
│ ├── intermediate/ # business logic, joins, pivots
│ │ └── <domain>/
│ └── marts/ # business-facing tables
│ └── <domain>/
│ ├── _<domain>__models.yml
│ ├── fct_<entity>.sql
│ └── dim_<entity>.sql
├── macros/
├── tests/
│ └── generic/
├── seeds/
├── snapshots/
└── analyses/
Layer Decision Matrix
| Layer |
Materialization |
Purpose |
Naming |
Tests |
| Staging |
view |
Clean/rename raw data, 1:1 with source |
stg_<source>__<entity> |
not_null, unique on PK |
| Intermediate |
ephemeral |
Business logic, joins, pivots |
int_<entity>_<verb>ed |
Tested via downstream |
| Marts |
table/incremental |
Business-facing facts and dimensions |
fct_<entity>, dim_<entity> |
Full coverage |
Materialization Decision Matrix
| Situation |
Materialization |
Why |
| Staging models |
view |
Always fresh, minimal storage |
| Intermediate logic |
ephemeral |
Zero cost, inlined as CTE |
| Marts < 100M rows |
table |
Simple, fast reads |
| Marts > 100M rows |
incremental |
Process only new/changed data |
| SCD Type 2 |
snapshot |
Track historical changes |
ref() and source() Rules
source() only in staging -- staging is the sole gateway to raw data
ref() everywhere else
- Never skip layers -- marts must not ref() staging directly
- Never hardcode schema names
SQL Style
- Leading commas, lowercase keywords, CTEs over subqueries
- Explicit columns in marts (no
select *), final CTE named final
- 4-space indentation, one column per line
Source Configuration
Define sources in _<source>__sources.yml with loaded_at_field and freshness thresholds. Configure warn_after and error_after per table.
| Concept |
Snowflake |
BigQuery |
| Top-level container |
Database |
Project |
| Schema grouping |
Schema |
Dataset |
Warehouse Quick Reference
| Config |
Snowflake |
BigQuery |
| Profile type |
snowflake |
bigquery |
| Auth |
User/password or key-pair |
OAuth or service account |
| Schema gen |
database.schema.model |
project.dataset.model |
| Incremental default |
merge |
merge |
| Partitioning |
Automatic micro-partitions |
partition_by required for large tables |
| Clustering |
cluster_by (automatic) |
cluster_by (manual) |
| Cost model |
Credits (compute time) |
Bytes scanned / Slots |
Common Commands
| Command |
Purpose |
dbt build |
Run + test in DAG order (recommended) |
dbt build --select +model |
Build model and all ancestors |
dbt build --select model+ |
Build model and all descendants |
dbt build --select tag:finance |
All models tagged finance |
dbt build --select state:modified+ |
Modified + descendants (Slim CI) |
dbt source freshness |
Check source freshness |
dbt deps |
Install packages |
dbt docs generate && dbt docs serve |
Documentation site |
Gotchas
ref() only in staging-and-above, source() only in staging — using source() in marts bypasses the staging contract and breaks lineage
- Incremental models without
unique_key silently duplicate rows on re-runs — always set unique_key for merge strategy
ephemeral models can't be tested directly or selected with dbt test --select — test via downstream consumers
dbt run doesn't run tests — always use dbt build to get run + test in DAG order
--full-refresh on a large incremental model can blow warehouse credits — scope with --select first
- Jinja whitespace control:
{%- -%} vs {% %} — trailing whitespace breaks compile output silently
packages.yml version ranges (>=1.0,<2.0) can pull breaking changes — pin exact versions in production
-- WRONG: source() in marts (skips staging layer)
SELECT * FROM {{ source('stripe', 'payments') }}
-- RIGHT: ref staging model
SELECT * FROM {{ ref('stg_stripe__payments') }}
-- WRONG: incremental without unique_key (duplicates on re-run)
{{ config(materialized='incremental') }}
-- RIGHT: always specify unique_key
{{ config(materialized='incremental', unique_key='payment_id') }}
Reference Files
Load on demand when detailed guidance is needed:
| Reference |
Topics |
| Testing & Quality |
Schema/generic/singular/unit tests, dbt-expectations, layer strategy |
| CI/CD & Deployment |
Slim CI, GitHub Actions, dbt Cloud, environments, blue/green, SQLFluff |
| Jinja, Macros & Packages |
Jinja fundamentals, custom macros, packages, debugging |
| Incremental & Performance |
Microbatch, merge, delete+insert, insert_overwrite, warehouse tuning |
| Data Quality & Observability |
Source freshness, Elementary, anomaly detection, alerting, incidents |
| Semantic Layer & Governance |
MetricFlow, contracts, versions, access controls, dbt Mesh |
License
Apache License 2.0. See LICENSE file for full terms.
Copyright 2026 Daniel Song
1---2name: dbt-skill3description: Use when working with dbt (data build tool) - creating models, writing tests, CI/CD pipelines, materializations, sources, staging/intermediate/marts layers, Snowflake/BigQuery warehouse configuration, incremental strategies, Jinja macros, data quality, semantic layer, or making analytics engineering decisions4license: Apache-2.05metadata:6 author: Daniel Song7 version: 1.0.08---910# dbt Skill for Claude1112Comprehensive dbt guidance: project structure, modeling, testing, CI/CD, production patterns. Targets Snowflake and BigQuery. Beginner-friendly with progressive scaling.1314## When to Use1516Activate when: creating/modifying dbt models, choosing materializations, structuring layers, setting up tests, implementing CI/CD, configuring sources/freshness, writing Jinja macros, reviewing dbt projects, making analytics engineering decisions.1718Skip when: basic SQL syntax, warehouse admin, raw pipeline config (Fivetran/Airbyte), BI tool config.1920## Core Principles21221. **DRY via ref()/source()** -- never hardcode table names232. **Single Source of Truth** -- each concept defined once; staging = entry point, marts = consumer interface243. **Idempotent Transformations** -- `dbt run` twice produces identical results254. **Test Everything** -- every model has at minimum PK uniqueness and not-null tests265. **Progressive Complexity** -- start with views/tables, add complexity when volume demands it2728## Project Structure2930```31dbt_project/32├── dbt_project.yml33├── packages.yml34├── profiles.yml # local only, not committed35├── models/36│ ├── staging/ # 1:1 with source tables37│ │ └── <source>/38│ │ ├── _<source>__models.yml39│ │ ├── _<source>__sources.yml40│ │ └── stg_<source>__<entity>.sql41│ ├── intermediate/ # business logic, joins, pivots42│ │ └── <domain>/43│ └── marts/ # business-facing tables44│ └── <domain>/45│ ├── _<domain>__models.yml46│ ├── fct_<entity>.sql47│ └── dim_<entity>.sql48├── macros/49├── tests/50│ └── generic/51├── seeds/52├── snapshots/53└── analyses/54```5556## Layer Decision Matrix5758| Layer | Materialization | Purpose | Naming | Tests |59|-------|----------------|---------|--------|-------|60| Staging | `view` | Clean/rename raw data, 1:1 with source | `stg_<source>__<entity>` | not_null, unique on PK |61| Intermediate | `ephemeral` | Business logic, joins, pivots | `int_<entity>_<verb>ed` | Tested via downstream |62| Marts | `table`/`incremental` | Business-facing facts and dimensions | `fct_<entity>`, `dim_<entity>` | Full coverage |6364## Materialization Decision Matrix6566| Situation | Materialization | Why |67|-----------|----------------|-----|68| Staging models | `view` | Always fresh, minimal storage |69| Intermediate logic | `ephemeral` | Zero cost, inlined as CTE |70| Marts < 100M rows | `table` | Simple, fast reads |71| Marts > 100M rows | `incremental` | Process only new/changed data |72| SCD Type 2 | `snapshot` | Track historical changes |7374## ref() and source() Rules75761. `source()` only in staging -- staging is the sole gateway to raw data772. `ref()` everywhere else783. Never skip layers -- marts must not ref() staging directly794. Never hardcode schema names8081## SQL Style8283- Leading commas, lowercase keywords, CTEs over subqueries84- Explicit columns in marts (no `select *`), final CTE named `final`85- 4-space indentation, one column per line8687## Source Configuration8889Define sources in `_<source>__sources.yml` with `loaded_at_field` and freshness thresholds. Configure `warn_after` and `error_after` per table.9091| Concept | Snowflake | BigQuery |92|---------|-----------|----------|93| Top-level container | Database | Project |94| Schema grouping | Schema | Dataset |9596## Warehouse Quick Reference9798| Config | Snowflake | BigQuery |99|--------|-----------|----------|100| Profile type | `snowflake` | `bigquery` |101| Auth | User/password or key-pair | OAuth or service account |102| Schema gen | `database.schema.model` | `project.dataset.model` |103| Incremental default | `merge` | `merge` |104| Partitioning | Automatic micro-partitions | `partition_by` required for large tables |105| Clustering | `cluster_by` (automatic) | `cluster_by` (manual) |106| Cost model | Credits (compute time) | Bytes scanned / Slots |107108## Common Commands109110| Command | Purpose |111|---------|---------|112| `dbt build` | Run + test in DAG order (recommended) |113| `dbt build --select +model` | Build model and all ancestors |114| `dbt build --select model+` | Build model and all descendants |115| `dbt build --select tag:finance` | All models tagged `finance` |116| `dbt build --select state:modified+` | Modified + descendants (Slim CI) |117| `dbt source freshness` | Check source freshness |118| `dbt deps` | Install packages |119| `dbt docs generate && dbt docs serve` | Documentation site |120121## Gotchas122123- `ref()` only in staging-and-above, `source()` only in staging — using `source()` in marts bypasses the staging contract and breaks lineage124- Incremental models without `unique_key` silently duplicate rows on re-runs — always set `unique_key` for merge strategy125- `ephemeral` models can't be tested directly or selected with `dbt test --select` — test via downstream consumers126- `dbt run` doesn't run tests — always use `dbt build` to get run + test in DAG order127- `--full-refresh` on a large incremental model can blow warehouse credits — scope with `--select` first128- Jinja whitespace control: `{%- -%}` vs `{% %}` — trailing whitespace breaks `compile` output silently129- `packages.yml` version ranges (`>=1.0,<2.0`) can pull breaking changes — pin exact versions in production130131```sql132-- WRONG: source() in marts (skips staging layer)133SELECT * FROM {{ source('stripe', 'payments') }}134-- RIGHT: ref staging model135SELECT * FROM {{ ref('stg_stripe__payments') }}136137-- WRONG: incremental without unique_key (duplicates on re-run)138{{ config(materialized='incremental') }}139-- RIGHT: always specify unique_key140{{ config(materialized='incremental', unique_key='payment_id') }}141```142143## Reference Files144145Load on demand when detailed guidance is needed:146147| Reference | Topics |148|-----------|--------|149| [Testing & Quality](references/testing-quality.md) | Schema/generic/singular/unit tests, dbt-expectations, layer strategy |150| [CI/CD & Deployment](references/ci-cd-deployment.md) | Slim CI, GitHub Actions, dbt Cloud, environments, blue/green, SQLFluff |151| [Jinja, Macros & Packages](references/jinja-macros-packages.md) | Jinja fundamentals, custom macros, packages, debugging |152| [Incremental & Performance](references/incremental-performance.md) | Microbatch, merge, delete+insert, insert_overwrite, warehouse tuning |153| [Data Quality & Observability](references/data-quality-observability.md) | Source freshness, Elementary, anomaly detection, alerting, incidents |154| [Semantic Layer & Governance](references/semantic-layer-governance.md) | MetricFlow, contracts, versions, access controls, dbt Mesh |155156## License157158Apache License 2.0. See LICENSE file for full terms.159160**Copyright 2026 Daniel Song**