Repository navigation
Releases: dbt-labs/dbt-charts
Releases · dbt-labs/dbt-charts
Release list
dbt-charts-v0.9.1
0.9.1 (2026-10-02)
Fixes
- Hovering a bar, heatmap cell or arc now dims the other marks, and line and area hover markers draw, for charts inside a
cols:row. Before, the hover runtime read its background from a rect that charts transparent over their board never paint, so only the tooltip showed.
dbt-charts v0.9.0
0.9.0 (2026-10-01)
Features
- The
render_boardagent tool (dct mcp,dbt_charts.ai) returns a compact text summary instead of JSON with every row, and no longer takesformat. Setinclude_raw_data: trueto also get the rows.dct rendergains--format text-data. - Amazon Athena support: install
dbt-charts[athena]and point a source at an Athena target withtype: dbt_profile. Closes dbt-labs/dbt-charts#7 - ClickHouse support: install
dbt-charts[clickhouse]and point a source at a ClickHouse target withtype: dbt_profile. The read-only user needsreadonly = 2. Closes dbt-labs/dbt-charts#26 ProjectSession.render_boardacceptscompile_result=to render an already compiled board without compiling it again.- Streamlit support:
st_board(board, project_dir=...)from thedbt-charts[streamlit]extra renders a board with live variable controls. Pass a Snowpark session to runsnowflakequeries through it. dct render --format textshows formatted values: KPI values, chart value ranges, table column labels and formats, plus render warnings.- Date and datepicker controls have a "Today" button.
- Endpoint labels, stacked-bar rails, pie slice labels, and support-table strips derive their label color from each mark color against the chart background, so custom palettes and dark themes get legible labels. Tune it under
chart_rendering.color_variantsindbt_charts.yml. - Every categorical palette offers derived variants via a trailing token:
category.blue.dark,category[2].light,vivid-10.3.pale, or a whole list such asvivid-10.deep. The companion palettes (vivid-10-dark,editorial-10-ghost, ...) and thecategory_dark,category_light,category_ghost, andcategory_inkroles are retired. Boards and themes are migrated on load and bydct migrate, except a nested board's owncharts:block and a KPI background scale palette, which fail to compile with an error naming the new spelling.dct migratedoes not rewrite retired tokens inside a flow-style list. - Bars and bar layers accept
y_start, for floating bars, dumbbells, waterfalls, candlesticks, and gantts. - Board text warns when heading or body text has too little contrast against its row background.
- Stacked area charts accept
style.stack_order;datastacks ay:list in authored order. dct skills introcovers board basics;dct --help,dct skills, anddct initpoint to it.
Fixes
- CJK, kana, and hangul text is measured at full width, so
text:paragraphs wrap instead of clipping. Closes dbt-labs/dbt-charts#6 - A single-series horizontal bar with an attached
support_tablekeeps its value-descending sort. Closes dbt-labs/dbt-charts#8 dct validate --warehouseno longer crashes withAssertionErroron a board that relies on an auto-detected dbt project with nosources:. Closes dbt-labs/dbt-charts#11- Jinja inside a query referenced via
{{ queries.X }}is rendered instead of sent to the warehouse verbatim. Closes dbt-labs/dbt-charts#12 - The color-reuse warning scales with palette size and fires on line, area, and stacked bar charts with endpoint labels. Closes dbt-labs/dbt-charts#14
- Heatmap axes follow query row order by default, and
sort:applies to y as well as x. Closes dbt-labs/dbt-charts#13 multiples:panels follow query row order instead of sorting alphabetically. Closes dbt-labs/dbt-charts#18- A date format on a numeric table column, or a number format on a date column, raises
ERR-TABLE-FORMAT-KIND-MISMATCHinstead ofERR-INTERNAL. Closes dbt-labs/dbt-charts#16 - Date-valued KPIs honor date formats and default to
date_short. Time directives (time_short,%H:%M) show the actual time instead of midnight. Closes dbt-labs/dbt-charts#15 grid.columnsmust be positive and spans and sizes must not be negative;columns: 0crasheddct render. Closes dbt-labs/dbt-charts#17- Grouped bars with a numeric or boolean color field render instead of raising
ERR-CHART-PAINTED-NO-MARKS. Closes dbt-labs/dbt-charts#19 WARN-BAR-BAND-WIDTH-TOO-NARROWfires on horizontal bar charts.- Warehouse connection failures show an actionable message instead of the driver's raw exception text, which moves to a separate
detailfield. - Date and datepicker controls use their own calendar popover and label format, matching daterange, instead of the browser's native date input.
- Time axes with an authored
time_formatno longer overprint tick labels. When no layout fits, labels are dropped andWARN-AXIS-LABEL-COLLISIONfires. - The
cloud-setupskill states its requirements up front: pushing to the default branch and a read-only warehouse credential. dct init skillsreports an unwritable directory instead of aPermissionErrortraceback.dct render --outputcreates missing parent directories.dct cloud statuswarns when the working directory is not tied to a project.dct cloud project connect --git-urlwarns that github.com repositories need the GitHub App flow.- A dual-axis layer with its own
axis_y.labels.formatno longer triggersWARN-LIKELY-CURRENCY-OR-PERCENT-MISSING-FORMATTER. Closes dbt-labs/dbt-charts#30 dct render,dct validate, anddct describeresolve a relative board path from the working directory first.- "No dbt charts project found" errors say to create
dbt_charts.yml; an empty file is enough. ERR-FORMAT-NATIVE-IN-VEGA-SLOTno longer suggests a.1%spec forpercent_numberformats, which painted values 100 times too large.- A
support_tableaggregate:row no longer adds a phantom "undefined NaN" tooltip row. Closes dbt-labs/dbt-charts#29 - A
support_tablerow'ssource:works with column names containing spaces, hyphens, or other special characters. Closes dbt-labs/dbt-charts#32 - When a stacked bar's color maps one-to-one to its x categories, the legend and stack order follow the x order (
sort:or query order) instead of stacked totals. Closes dbt-labs/dbt-charts#28 - Line and area
stroke.widthset at board, theme, ormeta.ymllevel is honored instead of replaced by the density-based default. Closes dbt-labs/dbt-charts#37 - Partial
style.charts.titleoverrides are accepted, and per-family overrides such asstyle.charts.bar.titleapply. Closes dbt-labs/dbt-charts#35 style.title.font.familyapplies to board titles and markdown headings. Closes dbt-labs/dbt-charts#36- Role tokens such as
category[1]work inconditional_formattingrules. Closes dbt-labs/dbt-charts#34 render_dashboardno longer modifies acompile_resultpassed to it, so rendering the same result twice returns the same status without duplicate warnings.- Ctrl-C on
dct serveno longer prints an ASGI traceback, anddct mcp serveno longer hangs on shutdown. - Redshift queries no longer fail with
parameter 'statement_timeout' requires an integer value. Closes dbt-labs/dbt-charts#39 - Nested items in loose Markdown lists in
text:blocks are no longer dropped. Closes dbt-labs/dbt-charts#41 - Tables whose percentage column widths sum to 100% no longer fire a spurious
WARN-TABLE-COLUMNS-OVERFLOW. Closes dbt-labs/dbt-charts#46 - An unknown
dct querysource name raisesERR-SOURCE-NOT-FOUNDinstead of running against an in-memory DuckDB. Closes dbt-labs/dbt-charts#45 - The static column check resolves models ending in
select * from final, so column typos are caught. Closes dbt-labs/dbt-charts#40 - A diverging gradient's
hingeis honored on every chart type. Diverging palettes may have an even number of stops, and the legend labels the hinge. Closes dbt-labs/dbt-charts#48 - Board style values such as fonts and colors can no longer inject script into rendered boards.
dct serveno longer reloads endlessly when the query cache lives inside the project.dct render charts/*.ymlskipsmeta.ymlwith a warning instead of failing.- An empty board file raises
ERR-EMPTY-YAML-DOCUMENTinstead ofERR-INTERNAL. - BigQuery
invalid_granterrors note that a new service account key may still be propagating. chart_focusno longer triggersWARN-UNREFERENCED-CHARTfor every other chart.- The value-label crowding warning measures the text actually painted, fixing missed and false warnings.
- Category axis labels with a d3 number format or
labels.font.caseno longer clip or overlap. %q,%L, and%Qin time formats render correctly.%c,%x,%X,%Z, and%sfail compile with a clear error.- Titles and headings use the body text color in every built-in theme. An authored
style.font.coloralso colors titles unless `style.tit...
dbt-charts v0.8.0
0.8.0 (2026-09-15)
Features
dctcan point at a dbt project outside the board project:--dbt-project-diron the commands that read a dbt project, theDBT_PROJECT_DIRenvironment variable behind it, and adbt_project_dir:key indbt_charts.yml. The flag wins over the config key, which wins over today's default of the board project directory; a named path that does not exist is an error rather than a silent fallback.dct cloud loginopens the approval page in a browser, the waygcloud auth loginandgh auth logindo; the URL is still printed as a fallback.--no-browserprints it without opening anything, and--startnever opens a browser.
Fixes
- A variable's
min,maxorstepmust be a finite number..infor.nanpublished a bound the control read back asNaN, so the board now errors at parse time instead of rendering a control that ignores it. - A board rendered to SVG,
dct render's default format, is a static picture: every interactive rule left the board's embedded stylesheet for the HTML host page. A standalone.svg, or a page embedding one without the host stylesheet, no longer draws hover tooltips or hover emphasis, no longer shows a text cursor or selection highlight on chart text, and no longer lets a table row's link be clicked through its own cell values. All of it still works in--format htmland underdct serve; an embedder that wants it back shipscontrols_stylesheet()alongside the SVG. - Variable controls: a multiselect can be emptied again through its
Allrow, adefault: truecheckbox can be unchecked, the slider commits a drag on both track and thumb, an option menu opens under its own field instead of drifting away from it, and a pressed control draws a focus ring. - A multiselect's option menu stays open while you pick members and reopens after the board re-renders, rather than closing on the first pick.
- List-valued variables are read from and written as repeated URL keys (
?region=west®ion=east);dct servepreviously kept only the last repeat. Existing JSON-encoded links still resolve. - A text variable input draws the value you committed immediately, instead of snapping back to the previous one until the render lands. It also follows its field when the page scrolls or resizes and takes the field's own type size, so it no longer shrinks on a scaled board.
- A number variable input honors authored
min,maxandstep, clamping and snapping on commit and passing them to the native spinner. An empty text or number field draws itsplaceholderas a muted hint rather than in the value color. - Horizontal bar charts with a
support_tablebeside their category labels no longer reserve the table's width twice, recovering the plot width that indentation cost. - The bundled Pygments lexer opens the
queries.<name>: |SQL shorthand only under a top-levelqueries:key, so a nested mapping of that name is no longer highlighted as SQL. - A zero baseline rule is no longer painted when the resolved y domain excludes 0. An all-negative line or area chart, or a bar chart with
zero: falseon data far from zero, drew the rule outside the plot rect, which grew the card to several times its slot height (and stretched every sibling card sharing that row) or, on the independent dual-axis path, rendered the chart blank. dct docs error-referenceanddct docs warning-referencework on an installed wheel. Both reference documents were excluded from the package build, so every PyPI install answered those two topics with "error-reference.md is missing from the installed package." and its warning-side equivalent.- A board-level
style.charts.bar.orientationnow reaches its bar charts. Only an inlinestyle.orientationon the chart was consulted, so the board default was a silent no-op while its siblingbar.stackcascaded normally. dct docslists the three generated references (reference,error-reference,warning-reference) in its topic index, anddct docs allincludes the field reference it already advertised as "unsliced". The reference also documents thedbt_charts.ymlproject-config keys,execution.max_template_output_bytesamong them.dct docs allgrows from roughly 68KB to 310KB, worth knowing before loading it into an agent's context.- Static column attribution no longer gives up on a set operation carrying its own
ORDER BY. AUNIONofref()arms with a sort reportedWARN-DBT-QUERY-COLUMNS-INDETERMINATE, anddct validatestopped checking that query's columns against the dbt models; the sort restates output columns the arms already attributed, so the query is checked like any other. - On a 100%-stacked bar or area chart, an authored percent format is applied to the raw measure value in the hover rows, the printed value labels and the stack total: a count of 20 reads
2000%, its group total of 80 reads8000%. The normalized stack pins its own 0-100% axis, so the format never reaches the axis it was written for. dbt Charts now warns (WARN-NORMALIZE-PERCENT-FORMAT-READS-RAW-VALUE) when the measure is not already a 0..1 share; a chart whose stack groups each sum to about 1 is silent, since there the raw value and the painted share are the same number. - A quantitative axis's ticks below 1 now write out in digits instead of d3's SI sub-unit prefixes, whether the axis has a baked tick ladder or none (a theme leaving
ticks.countunset, ormultiples.scale: independent). A y-axis over 0.29-0.38 reads0.3/0.35, where it used to read300m/350mand be taken for millions. Ticks at or above 1 keep the axis's own k/M compaction, and any axis with an authored literalformat:spec or astyle.formatsalias of its own, or a log scale, is unaffected. - A bar chart's
sort:orders categories by the sort column's own value rather than by that column's total across the category's rows, so a category holding fewer rows than its neighbors no longer sorts out of place. Sorting a stacked bar by its own measure still orders by the stacked total; a grouped bar sorted by its measure now ranks each category by its smallest series, so sort by a pre-summed column when you want the group total. - A
support_tablebelow the plot now clears x labels the chart rotated to fit: the gap is measured from the angle the labels are actually drawn at, rather than assumed to be two lines of horizontal text, so a chart with enough categories to auto-tilt its labels no longer needsstyle.support_table.label_max_linestuned by hand. Two more cases are covered wherever an authoredlabels.anglepins the tilt: a date axis whose points sit further apart than their own grain (ten dates 45 days apart, say) shows Vega's own date labels (September,2024) instead of short1 Janlabels, and an axis settinglabels.font.case: upperorlowerpaints its labels in that casing. In both cases the painted text can differ in width from the text the gap was measured against. - A bar chart with
style.orientation: horizontalnow gets an auto-generated link on itsxcategory, like a vertical bar.xis always the category or time channel for a bar, never the measure, so orientation no longer suppresses the link.
dbt-charts v0.7.1
Scatter charts gain multi-y support, the VS Code extension now auto-updates, and dct playground moves to the hosted app.
dct playgroundnow opens the hosted playground;--with-playgroundremoved:dct playgroundno longer boots a local server — it opens/prints the hosted https://play.dbtcharts.com/ URL instead. Thedct init --with-playgroundflag and theplaygroundpip extra are gone (#8888).- Scatter charts support multi-y (
y: [a, b]): Scatter is now the last cartesian chart type to accepty: [a, b], folding multiple measures into a color series the same way bar, area, and line already do. Tooltips, click interactivity, mirror axis, and related warnings all work with it (#8865). - Editor extension installs now auto-update via the Marketplace/Open VSX:
dct init code|cursor|vscodeinstalls the dbt Charts extension by its published Marketplace/Open VSX ID instead of side-loading a VSIX from an internal bucket, so it now auto-updates through the editor (#8890). - Fixed PDF export failing on deeply nested report boards:
dct render --format pdfno longer fails with an SVG-nesting-depth error on large multi-section report boards; PNG export was never affected. Caused by inert no-op group wrappers counting against PDF's 28-level nesting limit (#8859). - New warning flags unstacked area charts that read as stacked:
dct render/dct validatenow warn when a multi-seriestype: areachart without stacking is visually indistinguishable from a stacked one, since every band fills to zero and the outer edge can be misread as a total (#8852, #8896).
dbt-charts v0.7.0
A correctness pass across chart rendering, sorting, and style cascading, plus a dct serve security fix, three breaking grammar cleanups, and an 11x faster board parser.
Breaking
style.colorandstyle.page.backgroundremoved from the board grammar:style.colornever affected rendering, andstyle.page.backgroundonly ever painted the exported HTML page background, which is now hardcoded white. Boards authoringstyle.pagemigrate automatically; boards authoringstyle.colorfail to compile since there is no safe automatic replacement (#8491).- Shipped skills install under a
dct-prefix and overwrite unconditionally on upgrade:dct init skillsnow writes skills into namespaceddct-*directories so they never collide with a project's own skills, and re-running it after an upgrade always refreshes skill bodies instead of silently skipping existing files. The-f/force flag and the old un-prefixed skill directories are gone; skills retired from a release are now swept automatically (#8850). conditional_formattingremoved from bar, line, area, scatter, pie, map, and other non-table/KPI charts: the key only ever honoredrule.backgroundon these chart types and silently droppedfont,glyph,glyph_color, andtone; it's now removed there entirely, with an automatic migration deleting the key from those boards.tableandkpi, where it fully works, are unaffected (#8490).- Pie/donut chart total format moves from
total.formattostyle.total.value.format: a format string is paint, not authored copy, so it now lives understyle.total.value.formatalongside every other format field (tooltip, bar total label, axis labels); existing boards using the oldtotal.formatkey keep working, auto-migrated in place. Authoringstyle.total.labelas a caption now gets a clear error pointing back tototal.label:instead of a raw extra-field error (#8828).
Features
- Hover emphasis now covers lines, areas, scatter, pie/donut, and heatmaps: hovering a chart now visually ties the tooltip to the data it describes on every chart family: bars, histograms, pie/donut slices, and categorical heatmap cells recede toward the background, while lines, areas, and scatter get a marker dot (or ring) and a neutral drop line to the baseline. Charts whose color encodes a value never recede, since dimming would misrepresent the magnitude; turn the whole feature off with
style.charts.hover_emphasis.visible: false(#8827). - Board renders now cap total template output; oversized boards fail fast instead of exhausting memory: a board render's cumulative Jinja-emitted output is now bounded by a configurable byte ceiling (
execution.max_template_output_bytes, default 50MB), raising a newERR-TEMPLATE-OUTPUT-TOO-LARGEerror instead of letting a small amplifying template, such as nested loops, emit an unbounded amount of text (#8735). - Zero/threshold baseline now renders on scatter charts and every quantitative axis: the bold rule marking zero (or 100% on a percent axis) now fires on any quantitative axis, not just bar/line/area's measure axis, so a scatter plot crossing zero gets a baseline too. The authoring key
grid.zerois renamedgrid.thresholdand gains avisibleswitch to turn off just that rule without hiding the whole axis's gridlines (#8343). - Single-series area charts now render with a solid fill instead of a washed-out translucent one: the translucent overlap fill, meant to signal overlapping series, was applied even when there was nothing to overlap. A single-series area chart now gets the same solid fill and edge treatment as one authored with
style.stack: zero(#8729). dct initstarter board now uses real SQL and a working filter: the scaffoldedguide.ymlboard now queries a sample CSV with real SQL and a filter control that actually re-runs the charts, replacing an inert filter and a detour into unsupported markdown boards. New users see a board that behaves correctly from the first render (#8794).dct initstarter board no longer ships a sample CSV file: the starter board's sample data now lives inline in the YAML asvaluesqueries instead of a scaffolded CSV, sodct initno longer drops a data file into new projects. The region control now drives the board's own explanatory text, since inline rows can't be filtered by a variable (#8808).- Board footers show "made with dbt Charts" as text, not a logo: the SVG wordmark lockup in every board's footer is replaced with live text, "made with dbt Charts", set a weight heavier than the surrounding words and still linked to dbtcharts.com. The change also fixes an emphasis bug in the previous text-based footer: PNG and PDF exports could not resolve the CSS rule that bolded the name (#8755).
Fixes
dct serve's directory listing no longer lets a crafted filename inject template code: a file whose name contained Jinja syntax could have that name evaluated as template source on the next render pass. Filenames are now passed through as plain variable values, so a filename can never be re-tokenized as code (#8730).- Broken chart queries no longer get silently reported as successful: a query failure that wasn't a plain execution error, for example a Jinja template error in SQL or a too-large-template-output error, could lose its error code and be swallowed into an empty chart instead of a recorded failure, making board-artifact generation report success on a board with a genuinely broken chart; this path now surfaces the failure correctly (#8743).
- Charts no longer silently drop every row when dates fall on period ends: a time series reported at month-end, quarter-end, or similar period-end dates (for example
LAST_DAY(month)) with an authoredtime_unitused to render a full axis with zero data points and no warning; rows are now matched to the bucket they fall inside, and two rows landing in the same bucket now raise a clearERR-GAP-FILL-BUCKET-COLLISIONerror instead of one silently overwriting the other (#8739). sort:is respected on layered charts that also usecolor:: a bar chart authoringcolor:,layers:, andsort:together silently rendered its x-axis alphabetically, discarding the sort key, direction, and query row order, so a time series could read as scrambled with no warning. Layered categorical x-axes now keep the intended order. One side effect: a layered scatter chart, which has no sort key of its own, now renders in query row order instead of alphabetical (#8785).sort:now works on area, line, and heatmap charts:sort:was previously silently ignored on area, line, and heatmap charts (only bar and scatter honored it), so a warehouse query returning rows in a different order could reverse a chart's axis with no warning. All five documented chart types now honorsort:(#8796).- Chart x-axis labels no longer misread month-end, quarter-end, and year-end data as daily: time-axis grain detection now looks at the spacing between dates instead of where they fall on the calendar, so month-end, quarter-end, year-end, and fixed-day-of-month series get the correct monthly/quarterly/yearly tick ladder instead of one gridline and label per day (#8815).
- Line, area, and scatter charts no longer draw hundreds of extra gridlines on sparse date data: sparse monthly or quarterly data on a line, area, or scatter chart could be misdetected as daily grain, drawing over 1,000 gridlines that rendered as a solid gray band; these chart types now use the same grain-budget check bar charts already had (#8737).
style.legend.valuesnow actually reorders and filters legend entries on every chart type: the authored legend order was previously overwritten on most chart families, and matching an entry meant guessing a per-family label spelling. Entries now resolve by rendered label or by column/measure name, and an entry that still can't be matched produces a warning instead of silently vanishing from the legend (#8430).- Old boards using dead style keys (
style.color,kpi.style.color, and others) no longer fail to load: four keys retired in earlier grammar versions (board-rootstyle.color,kpi.style.color,style.charts.kpi.color, and heatmap's chart-localstyle.axis_quantitative) are now migrated away automatically instead of raising anextra_forbiddenerror, so old boards that still authored one of them load again (#8848). dct rendernow resolvesenv_var()templating inprofiles.yml: profiles fields that dbt renders via Jinja, such as a Snowflakeprivate_key_pathbuilt fromenv_var(...), no longer reach the file system as a literal template string. Any dbt project relying on templatedprofiles.ymlvalues can now rundct render(#8854).dct query --validateand--describeno longer fail on boards usingref(): both flags previously errored with a raw "Jinja template error: Undefined variable: 'ref' is undefined" on any board query usingref(), even thoughdct query,dct render, anddct validateran fine on the same query. They now resolve refs the same way execution does, and a project with no dbt manifest gets a clearERR-DBT-MANIFEST-MISSINGinstead of the Jinja error (#8776).- Cloud connection tests no longer hang for minutes on an unreachable warehouse: testing a connection to an unreachable warehouse (firewalled, wrong host, black-holed DNS) could previously block a worker for up to 5 minutes; connection tests, including
dct cloud connection test, now time out within about 15 seconds and still surface the driver's real error message when one is available (#8805). dct cloud connection createfor BigQuery no longer hangs indefinitely, and its failure message stops contradicting itself: BigQuery dataset discovery, location lookup, and per-relation readability probes are now time-bounded like the connection test, so a slow or unreachable warehouse fa...
dbt-charts v0.6.0
dbt charts v0.6.0
A broad three-week batch: theme and grammar cleanup (several retired names and fields removed), a wave of dct cloud CLI onboarding fixes, and well over a hundred rendering/authoring bug fixes.
Breaking changes
- MetricFlow support removed:
type: metricflowqueries, the MetricFlow-only chartmodel:sugar, and theVariable.model/dimension/measurefields are no longer supported — boards authoring them will need to migrate to standard SQL/dbt queries. Thedbt-charts[metricflow]install extra is also gone, shrinking the install footprint for everyone who wasn't using it. (#7732). - Four inert grid keys removed:
row_height,default_width,default_height,gap: These keys were accepted bydct validateand documented but silently ignored by rendering. They're now removed from the board schema; usestyle.layout.gridfor spacing and per-itemcol_span/widthfor sizing instead. (#7769). description:renamed tonotes:: Boards, charts, queries, layout/grid/tab items, and variables now authornotes:for non-rendering metadata instead ofdescription:. This is a straight rename with no alias — the field never rendered anything (despite sitting next totitle:/label:/text:), and boards still usingdescription:need to be updated by hand; a schema auto-migration was considered but did not ship in this PR. (#7823).style.font/style.borderon bar, line, area, scatter, histogram, heatmap, pie, and donut now error instead of silently doing nothing: These eight chart types never had a rendering path for chart-levelfont/border— the keys parsed but changed nothing, with no warning. The dead fields are removed for those chart types (with a migration for existing boards), so authoring them now surfaces a clear error instead of being silently ignored. (#7840).- KPI styling:
style.coloris gone,tonesmoves underkpi,alignnow works:charts.kpi.style.color(a bare string, unlike every other chart family) is removed — usestyle.font.colororstyle.value.font.colorinstead. Semantictones(used by both KPI and table conditional glyphs) now lives undercharts.kpi.tonesinstead of being read cross-family. KPI text also gains a realalignoption instead of being hardcoded to left-aligned. Existing boards using the oldkpi.style.colorkey need migration. (#7844). style.charts.table.borderno longer acceptswidth/radius; only markdown rule color remains:widthandradiuson the table'sborderstyle did nothing — the table chart has no outer border to draw. Those fields are removed. The one field that actually did something,color, only ever painted markdown tables and<hr>rules on the board, not the table chart itself; it's been relocated to a board-level markdown style slot so the key name no longer misleads authors into thinking it styles their table chart. (#7858).style.columnsno longer hides unlisted table columns: Naming a column under a table'sstyle.columnsused to silently drop every column not listed there. Styling and visibility are now separate:style.columnsonly styles the columns you name, and a newvisible: falsefield on a column entry is the only way to hide one. Boards that relied on the old show-list behavior will start rendering previously-hidden columns untilvisible: falseis added explicitly. (#7870).dct query --jsonoutput shape changes: noerrorfield, structured diagnostics:ExecuteQueryResult's duplicateerror/errorsfields collapse intoerrors: list[str]only, anddiagnosticson query results is now a list of structured objects instead of raw dicts, serialized with null fields omitted. Scripts parsing the olderrorstring field or dict-shaped diagnostics fromdct query,--validate --json, or the MCP query tools need updating. (#7926).axis_quantitativeremoved from heatmap's style surface: Heatmap's axes are both nominal and its magnitude lives on the color channel, sostyle.axis_quantitativenever had any visual effect when authored on a heatmap — it just parsed and did nothing. Authoring it now raises a parse-time error instead of silently no-op-ing. (#7952).- Chart attachment field renamed:
data_table:is nowsupport_table:: The per-x-tick value strip attached to bar/line/area charts was authored asdata_table:, colliding in name (though not in shape) with the standalonetype: tablechart. It's renamed tosupport_table:to disambiguate the two; boards using the old key needdct migrate. (#7984). currencyandnumberformats now default to compact, not full precision: Authoringnumber_format: currencyused to render full precision (e.g.$400,000,000.00); the compact form ($400M) required the separatecurrency_compactname. That's now flipped: barecurrency/numberare compact by default — matching the engine's own unauthored default — and the old_compactsuffixes are gone. Full precision is now reached viacurrency_full/number_full. Any board authoring the oldcurrency/number/*_compactnames will render differently; update format names when upgrading. (#8102).- Theme set trimmed from seven to five: Removed the unused
plaintheme and the near-duplicatesolidtheme; renamededitorialtoclarity(still the shipped default) andcreamtopaper.stark,vivid, andneonare unchanged. A board authored with an old theme name (theme:orextends:) migrates to its replacement automatically. (#8326). - Category-axis number formats now always raise instead of silently misrendering: A numeric
formatauthored on a category axis (scatter's y as a dot plot, heatmap axes, mirrored axes) used to silently drop the format or paint "$NaN"; it's now a designed error everywhere, matching the existingaxis_xbehavior. Boards that relied on the old silent-drop or NaN rendering now need to fix or remove the format. (#8395).
Features
dctwarns when it's answering from a stale global build: If baredctresolves throughPATHto a globaluv tool install/pip installshim instead of the current checkout's own editable build, it now prints a non-fatal stderr warning naming the mismatch, instead of silently validating against an old, different source tree. (#6998).- Consistent category colors across a board's charts: Charts on the same board that share a categorical column (e.g.
Electronics,North/South) now read color from one board-wide scale instead of each chart independently sorting its own data and assigning palette slots positionally, so a value keeps the same color everywhere on the board. Adds acategory_colorspinning option and a newWARN-CATEGORY-COLOR-PIN-UNSEENwarning when a pinned value never shows up in the data. (#7167). data_tableaccepts bare column names:data_table: [resolution_rate]now works instead of requiringdata_table: [{source: resolution_rate}]for the common case of just listing columns. Also unblocks attaching or detaching a data table strip from Cloud's design panel, which could previously only write simple column lists. (#7661).- Incremental refresh for SQL chart queries: A query or board can now declare
incremental: <watermark-column>so warm renders refresh only the new tail of a query instead of rescanning the full history — the executor computes a watermark from cached rows and appends what's new. A nested scope can opt out withincremental: false; a bareincremental: trueis rejected at parse time since there's no column to key on. (#7671). - New
dct examplescommand:dct examples <name>surfaces complete, validated board YAML from the playground gallery — multi-chart layout, query wiring, and variables working together — as a third knowledge surface alongsidedct skillsanddct docs. (#7680). - New hard limits on
files:sources protect against runaway disk usage: File sources (files:insources:) had no cap on per-relation materialized size or on the number of tables in a namespace. Newexecution.file_source_max_tables(default 500) andexecution.file_source_max_bytes(default 5GB) config keys enforce hard errors (ERR-FILE-SOURCE-TOO-MANY-TABLES, ERR-FILE-SOURCE-TOO-LARGE) before a large or wide file source is read. (#7794). - Bar and histogram marks gain a
fill_opacityfield:style.marks.bar.fill_opacityis now accepted (histogram charts share bar marks, so they get it too), matching the opacity field already available on area, point, rule, rect, and circle marks. Useful for keeping bin/bar boundaries visible when bars sit close together. (#7833). - KPI cards can now center- or right-align their text: KPI values were hardcoded to left-aligned text. A new
alignfield on KPI styling acceptsleft | center | right, matching the alignment already available on table columns. (#7873). dct validate --warehousenow checks Postgres, Redshift, and Snowflake: Warehouse-level query validation previously worked only for DuckDB and BigQuery; every other adapter reportedunchecked. Postgres, Redshift, and Snowflake now get real validity checks viaEXPLAIN. Also addsdct init ci, which scaffolds a GitHub Actions workflow that runsdct validate chartson pull requests. (#7879).- New
dct impactcommand finds boards affected by a column change:dct impact COLUMN [--table] [--json]answers "which boards break if this column changes" by building a reverse index from warehouse columns to the boards and queries that reference them, using compiled board SQL and no warehouse connection. Unparseable SQL,SELECT *, and boards that fail to compile are reported as indeterminate rather than silently omitted. (#7893). dct validatecatches renamed dbt columns before you run dbt: A new check derives each dbt model's output columns statically from the compiled SQL intarget/manifest.json(a baredbt parse, no build or ...