dbt Charts Puts the Dashboard in the Pull Request, and Keeps the Language Behind a Mirror
dbt Labs open-sourced a YAML dashboard language written for coding agents; the useful part is what fails the build, and the catch is who owns the grammar
A dashboard is the one artifact in a data stack that almost never goes through code review. Models do. Tests do. Even the warehouse schema does, in the form of migrations. But the chart on top, the thing the executive actually looks at, lives in a BI tool's database, edited by clicking, versioned by nobody. dbt Labs open-sourced dbt Charts on September 14 with a pitch aimed squarely at that gap, and the pitch is not "prettier charts." It is that the front end of everything is becoming a chat agent, and agents are "fluent in code, SQL, and Git, and clumsy in someone else's UI," so charts have to move to where agents work.
The repo at dbt-labs/dbt-charts is Apache 2.0, the CLI is dct, and the whole language is a handful of top-level keys: variables, queries, charts, and a layout of rows and cols. A board is one YAML file. That file renders to SVG, HTML, PNG, PDF, or the terminal, and it fails a pull request when the model underneath it changes.
That last sentence is the product. The rest of this piece is about why it is the product, what it costs, and the ownership detail that the announcement does not dwell on.
What breaks the build
Dave Fowler's launch post says the quiet part directly: agents "can be quite blind, and they do best with a tight feedback loop." A pile of HTML, CSS, JavaScript, and a chart library is a bad loop. Nothing tells the agent the bars are too thin or the table overflows. dbt Charts has a validator with named warnings, and the docs list them. WARN-BAR-BAND-WIDTH-TOO-NARROW comes with the measurement (182 bands across 640 pixels) and a fix (roll up to a coarser grain). WARN-TABLE-COLUMNS-OVERFLOW says the table needs 980 pixels and has 640. An agent can act on that. A human squinting at a Streamlit app cannot.
The CI guide is more interesting than the launch post, because it describes three tiers of what can fail and is honest about what each tier cannot see.
Tier one is structural. dct init ci writes a GitHub Actions workflow that runs dct validate on any pull request touching charts/. It catches malformed YAML, unknown fields, and a chart pointing at a query that does not exist. It needs no credentials and no dbt.
Tier two is where the dbt integration earns its name. Add dbt parse before the validate step, and dct validate reads target/manifest.json. Now a board that references {{ ref('orders') }} fails if you renamed the model. More than that: the validator derives each model's output columns statically from its SQL, so renaming customer_id to user_id in models/orders.sql fails every board that selects customer_id from that model, with ERR-DBT-MODEL-COLUMN-MISSING, on the same pull request, before dbt run has rebuilt anything. The docs point out why that timing matters: warehouse-level validation would still pass at that moment, because the old table is still there.
The drift check is honest about its own blind spots, which I respect more than the feature itself. A model with SELECT * or a macro in projection position gets WARN-DBT-MODEL-COLUMNS-UNRESOLVED rather than a silent pass. A board query the validator cannot analyze gets WARN-DBT-QUERY-COLUMNS-INDETERMINATE. Neither fails the build by default. dct validate --strict makes them fail, and the docs say what that costs: a project that ships SELECT * queries will need to make its columns explicit to go green.
Tier three adds --warehouse and uses the cheapest per-adapter check available (DuckDB DESCRIBE, BigQuery dry-run, EXPLAIN on Postgres, Redshift, and Snowflake) without running queries at full cost. Adapters with no safe primitive are reported as unchecked, not as passing. Most teams, the docs say, stop at tier two.
There is also a reverse index. dct impact customer_id --table orders lists every board whose compiled SQL reads that column, resolved through CTEs and aliases, with no warehouse connection. That is the "what will I break" question, answered before the rename instead of after.
Put those together and you have something I have not seen a BI tool offer: the dashboard is a first-class citizen of the same pull request as the model, and the gate that protects it is deterministic. An agent that edits a model and forgets the board gets told. An agent that edits a board against a column that no longer exists gets told. The telling happens in CI, in text, which is the only place an agent can read it.
Why this is the pattern that survives model churn
Every few weeks a new model makes last month's prompt engineering obsolete. What does not go obsolete is a target format that is small, declarative, validated, and diff-able. If the agent's job is "produce a YAML file that passes dct validate," then the model can change, the prompt can change, and the review process stays the same, because the review is a schema and a test, not a vibe.
dbt itself is the precedent. It won because SQL in files with ref() and tests beat SQL in a BI tool's saved-query box. dbt Charts is the same bet one layer up. Fowler frames it as the second unbundling of BI, quoting Tristan Handy: the modern data stack pulled ingestion, transformation, and compute out of the BI bundle between 2015 and 2022, and charts are the biggest piece left. Whether or not you buy the history, the mechanism is the same one that worked before.
The mirror
Now the part I would not have noticed from the announcement.
The README of dbt-labs/dbt-charts says the GitHub repo is a read-only mirror of dbt Labs' private upstream. Pull requests are closed unmerged. Issues are accepted. The LICENSE file is Apache 2.0, and the copyright line reads "Copyright 2026 Fivetran, Inc.," not dbt Labs. The footer of the docs site links Fivetran's privacy policy and terms. The star count on the morning after launch was in the low hundreds, which is the number you get when the code arrives on GitHub as a finished artifact rather than a project people have been watching.
None of that is hidden, and none of it is wrong. Apache 2.0 is Apache 2.0; you can fork, vendor, and ship. But there is a difference between a language whose grammar you can read and a language whose grammar you can shape, and dbt Charts is currently the first kind. The post says the grammar is still changing and that boards "migrate as they parse," so what you write today will keep rendering. It also says, in the same paragraph, that the team is asking for feedback via issues and Slack. That is the channel. It is not a pull request.
For an individual analyst this does not matter. For a team deciding whether the dashboard layer of its data platform should be a language it does not control, developed in private, with a copyright line that names Fivetran rather than the dbt Labs that made ref() a household word, it matters some. The hosted product, dbtCharts.com, launched in public beta the same day, and the docs already have a "dbt Charts Cloud" section with access control, warehouse privileges, and a Claude and ChatGPT connector. The open language and the closed platform shipped together, on purpose.
I do not think that is a reason to skip it. I think it is a reason to treat the YAML as a rendering target you can regenerate, not a source of truth you are married to. Keep the SQL in dbt models, where you own it. Let the board file be thin.
Put this into practice
Start without a warehouse. uv tool install dbt-charts then dct init writes a dbt_charts.yml anchor and a charts/guide.yml starter board that renders with no database. dct serve previews it in a browser. Ten minutes, and you know whether the YAML shape suits you.
If you have a dbt project, run dct init in its root instead. dct serve finds the root from dbt_project.yml, and query sources come from your profiles.yml. Write one board with one ref(). Then run dbt parse && dct validate locally. The docs say it is sub-second without --warehouse, which makes it a pre-commit hook candidate.
Then scaffold the gate: dct init ci, commit the workflow, and open a pull request that breaks the board on purpose. The CI guide's line on this is worth keeping: "A gate you have never seen fail is a gate you can't trust." One operational catch from the same page: because the workflow filters on charts/**, it does not start at all on a pull request that touches no boards, so if you make it a required status check, unrelated PRs pin at "Expected, waiting for status." Leave it optional or drop the path filter.
If you want the agent version, hand your coding agent the launch post's sentence verbatim and give it a small, real question about a dbt model you already have. Watch two things: whether the board it produces passes dct validate on the first try, and whether the visualization warnings change what it does on the second.
And before adopting it for anything shared, read the README's mirror paragraph and the LICENSE copyright line yourself. Decide in advance how you would leave.
Where it falls short
It is pre-1.0 and says so. The grammar is changing, and while the migration promise is that old boards keep rendering, a language with over 1,100 config options that is still moving will produce diffs you did not author.
The column-drift check depends on static analysis of model SQL. SELECT *, macros in projection position, seeds, and snapshots all fall into the unresolved bucket. If your project leans on those, tier two warns instead of fails, and --strict will make you rewrite queries you were happy with.
Warehouse validation needs credentials on the CI runner, which is exactly the thing most teams do not want in a pull-request workflow. The docs suggest running it on a schedule or on merge instead. That means the failure class only a live warehouse reveals, a table dropped outside dbt, lands after the merge.
Semantic layer support is planned, not shipped; the post points at issue #1. Until then, a metric the project defines in the semantic layer has to be restated as SQL in the board, which is precisely the duplication dbt exists to remove.
The contribution model is issues only. If you find a bug in the validator, you can report it. You cannot fix it upstream.
And I have not run this at scale. The CI claims above are from the documentation, quoted rather than reproduced, and the sub-second validation figure is theirs, not mine.
What to decide
The question dbt Charts asks is not whether agents should make dashboards. They already do, badly, in whatever framework was in the training data. The question is whether the dashboard should be a file that a deterministic check can reject on the same pull request as the model it reads. I think the answer is obviously yes, and I think dbt Charts is the first serious attempt at that answer from a company with the distribution to make it stick.
Whether the language should be one you cannot contribute to is a separate question, and it is yours. Read the mirror paragraph. Then write one board and break it on purpose.
Sources: dbt Charts launch post "Charts built for Chat" by Dave Fowler, September 14, 2026; dbt-labs/dbt-charts README and LICENSE on GitHub (cache-busted raw fetch, September 15); dbt Charts documentation, Quick Guide and "Validating Boards in CI," docs.dbtcharts.com, read September 15, 2026.
Medium metadata
- Title: dbt Charts Puts the Dashboard in the Pull Request, and Keeps the Language Behind a Mirror
- Subtitle: dbt Labs open-sourced a YAML dashboard language written for coding agents; the useful part is what fails the build, and the catch is who owns the grammar
- Tags: dbt, Data Engineering, AI Agents, Open Source, Analytics
- Canonical: fervorai.dev (import to Medium after publish)