You don't write dashctl.
Claude Code, Cursor, and Codex do. They emit a YAML spec;
dashctl compiles it to one self-contained HTML file —
themeable, reproducible, with live BigQuery and DuckDB.
You ship it.
Open live demo →
Each one is a single self-contained HTML file produced by
dashctl build
from a YAML spec — view-source friendly, no backend.
Same prompt, same data, byte-identical dashboard. The spec lives in git, diffs are readable, regressions are obvious. Re-run the build a year later and get the same artifact — no GUI state to lose.
Drop your brand colors, font, and density into one
theme:
block. Every dashboard your agent emits adopts it. Light, dark, or
your design system — no per-chart restyling.
CSV, JSON, Parquet, DuckDB-WASM in the browser, and live BigQuery via a local proxy (ADC — no OAuth dance). Snapshot for instant load or query live; same spec, your call.
No human writes the format. You chat; the agent ships.
"Build a sales dashboard from BigQuery — last 90 days, top regions, revenue per channel."
Claude Code / Cursor / Codex emits dashboard.yaml
against a published, schema-validated spec.
One command turns the spec into a single self-contained HTML file — typically < 1 MB, fully offline-capable.
Open it, attach it to email, drop it on S3, embed it in a portal. Live BigQuery still queries from the static file.
Yes, there is a format. Your agent writes it fluently — you don't have to look at it unless you're curious. A small, stable, schema-validated YAML keeps the agent's output predictable.
# dashboard.yaml — what the agent writes title: Sales theme: light sources: orders: type: csv url: ./orders.csv panels: - row: - type: kpi title: Total revenue source: orders query: SELECT SUM(amount) AS [value] FROM orders format: currency - type: line title: Revenue over time source: orders query: SELECT date, SUM(amount) AS revenue FROM orders GROUP BY date x: date y: revenue
# in your agent / terminal > "Build a sales dashboard from > ./orders.csv with revenue, top > customers, region breakdown." # the agent emits dashboard.yaml, then: $ dashctl validate dashboard.yaml [validate] ok — 4 panels, 1 source $ dashctl build dashboard.yaml -o dash.html [build] wrote dash.html (842 KB) # one file. open it, email it, # drop it on S3.
npm install -g dashctl
dashctl init my-dashboard
dashboard.yaml + tiny CSV in the repo — a one-shot reference the agent can learn the format from. You can delete it after../orders.csv — revenue, top customers, region split." The agent writes the spec, runs dashctl build, hands you the HTML. That's the loop.