Creating Dashboards
ancoleman/ai-design-components
Creates comprehensive dashboard and analytics interfaces that combine data visualization, KPI cards, real-time updates, and interactive layouts.
Read before choosing a chart or adding a chart annotation. An agent skill from malloydata/publisher.
$ npx skills add malloydata/publisher --skill malloy-charts -a claude-codeProject install by default; add -g for ~/.claude/skills/.
$ gh skill install malloydata/publisher malloy-charts --agent claude-codeProject scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).
$ git clone --depth 1 https://github.com/malloydata/publisher.git skills-src && mkdir -p .claude/skills && cp -r skills-src/skills/malloy-charts .claude/skills/malloy-charts && rm -rf skills-srcUse ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.
Claude Code skills documentation · loads skills from .claude/skills/
Install the "malloy-charts" agent skill from https://github.com/malloydata/publisher/tree/main/skills/malloy-charts into .claude/skills/malloy-charts/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "malloy-charts", then confirm the skill loads.Claude Code copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$skill-installer install https://github.com/malloydata/publisher/tree/main/skills/malloy-chartsType this inside Codex. $skill-installer <name> installs a curated skill from openai/skills. The installer writes to $CODEX_HOME/skills (default ~/.codex/skills). Restart Codex if the skill does not show up.
$ npx skills add malloydata/publisher --skill malloy-charts -a codexProject install goes to .agents/skills/; add -g for ~/.codex/skills/.
$ gh skill install malloydata/publisher malloy-charts --agent codexProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/malloydata/publisher.git skills-src && mkdir -p .agents/skills && cp -r skills-src/skills/malloy-charts .agents/skills/malloy-charts && rm -rf skills-srcUse ~/.agents/skills/ instead of .agents/skills for a personal install.
Codex skills documentation · loads skills from .agents/skills/
Install the "malloy-charts" agent skill from https://github.com/malloydata/publisher/tree/main/skills/malloy-charts into .agents/skills/malloy-charts/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "malloy-charts", then confirm the skill loads.Codex copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add malloydata/publisher --skill malloy-charts -a cursorProject install goes to .agents/skills/; add -g for ~/.cursor/skills/.
$ gh skill install malloydata/publisher malloy-charts --agent cursorProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/malloydata/publisher.git skills-src && mkdir -p .cursor/skills && cp -r skills-src/skills/malloy-charts .cursor/skills/malloy-charts && rm -rf skills-srcUse ~/.cursor/skills/ instead of .cursor/skills for a personal install.
Cursor skills documentation · loads skills from .cursor/skills/, .agents/skills/, .claude/skills/, .codex/skills/
Install the "malloy-charts" agent skill from https://github.com/malloydata/publisher/tree/main/skills/malloy-charts into .cursor/skills/malloy-charts/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "malloy-charts", then confirm the skill loads.Cursor copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gemini skills install https://github.com/malloydata/publisher.git --path skills/malloy-charts--scope user (default) or --scope workspace; --path is the subfolder of the repo that holds the skill; --consent skips the security confirmation prompt.
$ npx skills add malloydata/publisher --skill malloy-charts -a gemini-cliProject install goes to .agents/skills/; add -g for ~/.gemini/skills/.
$ gh skill install malloydata/publisher malloy-charts --agent gemini-cliProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/malloydata/publisher.git skills-src && mkdir -p .gemini/skills && cp -r skills-src/skills/malloy-charts .gemini/skills/malloy-charts && rm -rf skills-srcUse ~/.gemini/skills/ instead of .gemini/skills for a personal install, then run /skills reload.
Gemini CLI skills documentation · loads skills from .gemini/skills/, .agents/skills/
Install the "malloy-charts" agent skill from https://github.com/malloydata/publisher/tree/main/skills/malloy-charts into .gemini/skills/malloy-charts/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "malloy-charts", then confirm the skill loads.Gemini CLI copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gh skill install malloydata/publisher malloy-chartsInstalls for Copilot at project scope by default; add --scope user for a personal install. Preview a skill first with gh skill preview. Needs GitHub CLI 2.90.0 or later (public preview).
$ npx skills add malloydata/publisher --skill malloy-charts -a github-copilotProject install goes to .agents/skills/; add -g for ~/.copilot/skills/.
$ git clone --depth 1 https://github.com/malloydata/publisher.git skills-src && mkdir -p .github/skills && cp -r skills-src/skills/malloy-charts .github/skills/malloy-charts && rm -rf skills-srcUse ~/.copilot/skills/ instead of .github/skills for a personal install. Commit .github/skills so cloud agent and code review can use it.
GitHub Copilot skills documentation · loads skills from .github/skills/, .claude/skills/, .agents/skills/
Install the "malloy-charts" agent skill from https://github.com/malloydata/publisher/tree/main/skills/malloy-charts into .github/skills/malloy-charts/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "malloy-charts", then confirm the skill loads.GitHub Copilot copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add malloydata/publisher --skill malloy-charts -a opencodeOpenCode documents no install command of its own. Project install goes to .agents/skills/; add -g for ~/.config/opencode/skills/.
$ gh skill install malloydata/publisher malloy-charts --agent opencodeProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/malloydata/publisher.git skills-src && mkdir -p .opencode/skills && cp -r skills-src/skills/malloy-charts .opencode/skills/malloy-charts && rm -rf skills-srcUse ~/.config/opencode/skills/ instead of .opencode/skills for a personal install.
OpenCode skills documentation · loads skills from .opencode/skills/, .claude/skills/, .agents/skills/
Install the "malloy-charts" agent skill from https://github.com/malloydata/publisher/tree/main/skills/malloy-charts into .opencode/skills/malloy-charts/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "malloy-charts", then confirm the skill loads.OpenCode copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
malloy-chartsRead before choosing a chart or adding a chart annotation. An agent skill from malloydata/publisher.
Malloy Charts is an agent skill from malloydata/publisher. Read before choosing a chart or adding a chart annotation. Chart types, tag syntax and scale rules, KPI cards, dashboards, sparklines, and the renderer mistakes that fail silently.
Its SKILL.md is about 4.6k tokens, which your agent loads only when the skill is triggered. It is a single SKILL.md file with no bundled scripts.
It sits in Data & Analytics, covering Data visualization and OKRs and executive reporting. The repository describes itself as: Publisher is the open-source analytics engine for Malloy. It lets you define data models once — and use them everywhere. The licence is MIT.
Read from SKILL.md and the folder at commit c43a052. It shows what the files ask for, not the result of running them.
Pre-approves nothing: there is no allowed-tools line, so your agent's usual permission prompts apply.
From allowed-tools in the SKILL.md frontmatter.
No scripts in the folder and no shell commands in SKILL.md (its code samples are malloy).
From the folder's file list and the shell code blocks in SKILL.md.
Links to these hosts (documentation or services it may open):
docs.malloydata.devFrom URLs in SKILL.md, links to its own repository left out.
Names no API keys, tokens, secrets or passwords.
From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.
Malloy Charts loads about 4.6k tokens when it runs. Until then it costs about 49 tokens; SKILL.md has 1,608 words of instructions outside code blocks.
Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.
The automated check found no risky patterns in SKILL.md.
Automated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); files beside SKILL.md are not scanned.
The full file from malloydata/publisher at commit c43a052, republished under its MIT licence (© malloydata). 1,608 words, ~4,555 tokens.
.claude/skills/malloy-charts/SKILL.md (or your agent's skills folder).<!--
Copyright (c) Credible Data Inc.
SPDX-License-Identifier: MIT
-->
Malloy uses Vega-Lite under the hood.
#tags control visualization. Callsearch_malloy_docswith topic "rendering" for the full tag reference (or see https://docs.malloydata.dev/documentation/visualizations/overview).
This file is about the Malloy renderer's
#tags. It applies when the view itself is rendered - a notebook, a dashboard, an explore result. It does not apply to an app that draws its own charts with a vendored chart library: there the tag vocabulary is irrelevant and the full form vocabulary is available, so the approximations below (a funnel as a bar chart, a treemap as a nested table) are the wrong advice. Design to whichever vocabulary the surface actually uses.
Tool names are written bare here -
get_context,execute_query,search_malloy_docs. The exact prefixed name depends on the host surface; match each against the tools you actually have.
| Data Shape | Default Choice |
|---|---|
| Aggregates only (no group_by) | # big_value |
| 1 time column + 1 measure | # line_chart |
| 1 category + 1 measure | # bar_chart |
| 2 numeric columns | # scatter_chart |
| Geographic (US states) + 1 measure | # shape_map |
| Route data (lat/lon pairs) | # segment_map |
| Multiple perspectives | # dashboard with nest: |
| Nested query to pivot | # pivot |
| Filtered aggregates side-by-side | # flatten |
| Detailed rows | Default table (no annotation) |
| Goal | Renderer |
|---|---|
| Compare categories | # bar_chart (sort by value, limit ~15) |
| Show composition | # bar_chart.stack |
| Trend over time | # line_chart |
| Highlight KPIs | # big_value with # label |
| Correlation | # scatter_chart |
| Compare dimensions | # dashboard (nest chart views) |
| Before/after | # transpose or # pivot |
| Multiple metrics per category | Default table, # flatten, or y=['a','b'] |
Constraints:
y=['a','b'] for multi-measure)# currency not # currency=usd0m. The same measure renders at many granularities, and usd0m turns $500 into $0.0M. Add a scale only in a view, after confirming the value range with a query.# tags on one line do not work.group_by before order_by# bar_chartData shape: group_by = x-axis, aggregate = y-axis, optional 2nd group_by = series.
# bar_chart
view: by_carrier is { group_by: carrier, aggregate: flight_count, order_by: flight_count desc, limit: 10 }
# bar_chart.stack
view: by_region is { group_by: category, region, aggregate: revenue }
# bar_chart { y=['revenue','cost'] }
view: rev_vs_cost is { group_by: category, aggregate: revenue, cost }Key properties: .stack, .size (spark/xs/sm/md/lg/xl/2xl), .x, .x.limit, .y (supports y=['a','b']), .series, .series.limit (default 20), .title, .subtitle, .x.independent, .y.independent
Field role tags: # x, # y, # series on individual fields to assign roles explicitly.
# line_chartData shape: group_by (temporal/numeric) = x-axis, aggregate = y-axis, optional 2nd group_by = series.
# line_chart
view: trend is { group_by: order_month, aggregate: revenue, order_by: order_month }
# line_chart { size=spark }
view: mini_trend is { group_by: order_month, aggregate: revenue, order_by: order_month }Key properties: .zero_baseline, .interpolate (e.g., step), .size, .y (supports y=['a','b']), .series.limit (default 12), .title, .subtitle
# scatter_chartData shape: Fields by position: x, y, color, size (bubble), shape.
# scatter_chart
view: correlation is { group_by: customer_id, aggregate: avg_price, total_quantity }# shape_mapChoropleth. US states only. Fields: state name, value.
# shape_map
view: by_state is { group_by: state, aggregate: revenue }# segment_mapRoute map. US only. Fields: start_lat, start_lon, end_lat, end_lon, color.
# big_valueKPI cards. Aggregates only, no group_by.
# big_value
view: summary is {
aggregate:
# label="Revenue"
# currency
revenue
# label="Orders"
# number=auto
order_count
}Properties: .size, .sparkline=<nested_view_name>, .comparison_field, .comparison_label, .down_is_good
Put # label on every measure. Without it the card shows the raw field name, which is often unclear.
# dashboardCard-based multi-tile layout. Apply to a view whose body is a nested query; the view's own fields lay out automatically:
group_by dimensions -> a row header (repeats once per row; omit for a single block)aggregate measures -> KPI cards, one per measurenest: -> a tile, rendered by the tag above it (# table default, or # bar_chart / # line_chart / # big_value)Two modes. Flex (default): tiles flow and wrap; # break forces a new row. Columns: # dashboard { columns=N } lays tiles into N equal columns, # colspan=n widens a tile (the old # span is gone), # break starts a new row, overflow wraps.
// Flex: measures become KPI cards, the nest becomes a tile
# dashboard
view: overview is {
group_by: category
# currency
aggregate:
avg_retail is retail_price.avg()
sum_retail is retail_price.sum()
nest:
# bar_chart
by_brand is { group_by: brand, aggregate: avg_retail is retail_price.avg(), limit: 10 }
}
// Columns: # colspan widens tiles, # break ends a row
# dashboard { columns=12 }
view: layout is {
group_by: category
# currency
aggregate:
# colspan=4
avg_retail is retail_price.avg()
# colspan=4
sum_retail is retail_price.sum()
# colspan=4
max_retail is retail_price.max()
nest:
# break
# colspan=6
# bar_chart
# subtitle="Top brands"
by_brand_chart is { group_by: brand, aggregate: avg_retail is retail_price.avg(), limit: 8 }
# colspan=6
by_brand_table is { group_by: brand, aggregate: product_count is count(), limit: 8 }
}Tags: # dashboard { columns=N } (columns mode), { gap=PX } (tile spacing, default 16; never a mode), { table.max_height=PX|none } (cap table tiles). On a measure or nest: # colspan=N (columns mode only), # break (both modes), # subtitle="..." (tile), # borderless (drop card chrome), # label="..." (card title).
For rich KPI cards (sparklines, comparison deltas, several metrics on one card) nest a # big_value view instead of relying on the dashboard's own measures:
# dashboard
view: kpis is {
group_by: category
nest:
# big_value
revenue_card is {
aggregate:
# label="Revenue"
# currency
# big_value { sparkline=trend }
total_revenue is retail_price.sum()
# line_chart { size=spark y.independent=true }
# hidden
nest: trend is { group_by: bucket is floor(id / 100)::number, aggregate: total_revenue is retail_price.sum(), order_by: bucket, limit: 20 }
}
}Rules: # dashboard needs a nested-query view (no effect on a scalar). # colspan works only in columns mode and is ignored (warns) in flex. columns is any positive integer; a # colspan over the column count clamps to a full row. Style tiles via the instance theme, or theme the views inside with # theme.* (see Theming below).
# pivotPivot nested results into columns. Max 30 pivot columns.
view: sales is {
group_by: product, aggregate: total
nest: # pivot
by_quarter is { group_by: quarter, aggregate: revenue }
}# transposeSwap rows/columns. Good for period comparisons.
# transpose
view: comparison is {
aggregate:
# label="This Month"
current_revenue
# label="Last Month"
prior_revenue
}# list / # list_detailList renders as comma-separated values. List_detail shows value (detail) pairs.
# flattenCollapse nested record into parent table as columns. Use for side-by-side filtered aggregates:
view: segments is {
group_by: product, aggregate: total_revenue
nest: # flatten
enterprise is { where: segment = 'Enterprise', aggregate: # label="Enterprise" revenue }
nest: # flatten
smb is { where: segment = 'SMB', aggregate: # label="SMB" revenue }
}# tableDefault (implicit). Use explicitly for .size=fill property.
| Tag | Use For | Shorthand |
|---|---|---|
# number | Numeric formatting | =auto (K/M/B), =id (no commas), =1k, =1m |
# percent | Percentages | (none needed) |
# currency | Money | =usd2m (USD, 2 decimals, millions); scale only in views |
# duration | Time durations | =seconds, =minutes, =hours, =days |
# data_volume | Storage sizes | =bytes, =kb, =mb, =gb |
# link | Hyperlinks | .url_template="https://example.com/$$" |
# image | Inline images | .height=40px, .width=100px |
# image and # link are fine in a model file. A document held as text (one with a model-level ## artifact tag, compiled at scope append) is refused if it writes either; define the field in the model file and check that edit at scope file.
Currency codes: usd ($), eur, gbp. Scale: K/M/B/T/Q or auto.
Number suffix styles: word ("42.5 million"), letter ("42.5M"), scientific.
| Tag | Purpose |
|---|---|
# hidden | Hide from output (still usable for sorting/references) |
# label="..." | Override display name |
# description="..." | Tooltip text |
# tooltip | Include nested view in chart tooltip |
# break | Force new dashboard row |
# column { width=sm } | Table column width |
## viz.line_chart.defaults.y.independent=true
## viz.bar_chart.defaults.stackPublisher styles charts and tables from one structured theme. The instance sets it (in publisher.config.json's theme block or the Settings, then Theme editor); a model overrides it per result with # theme.* annotations, or model-wide with ## theme.*. Per-chart annotations use the same nested palette.* / font.* vocabulary as the config, not flat key names, and they win over the instance theme for the keys they set. The forms:
| Annotation | Controls | Modes |
|---|---|---|
# theme.palette.series | Categorical series colors (array) | shared |
# theme.palette.background.{light,dark} | Chart canvas + table background | per-mode |
# theme.palette.tableHeader.{light,dark} | Table header text color | per-mode |
# theme.palette.tableHeaderBackground.{light,dark} | Table header row background | per-mode |
# theme.palette.tableBody.{light,dark} | Table body text color | per-mode |
# theme.palette.tile.{light,dark} | Dashboard tile background | per-mode |
# theme.palette.tileTitle.{light,dark} | Dashboard tile title color | per-mode |
# theme.palette.mapColor.{light,dark} | Choropleth gradient (# shape_map / # segment_map) | per-mode |
# theme.palette.border.{light,dark} | Table gridlines and row rules | per-mode |
# theme.palette.cardBorder.{light,dark} | Dashboard card edge and pinned table header rule | per-mode |
# theme.palette.axis.{light,dark} | Chart axis domain and tick lines | per-mode |
# theme.palette.gridline.{light,dark} | Chart gridlines | per-mode |
# theme.palette.chartText.{light,dark} | Chart axis, legend and title text | per-mode |
# theme.palette.value.{light,dark} | Big-value (KPI) number color | per-mode |
# theme.font.family | Font for all rendered text | shared |
# theme.font.size | Table font size (px) | shared |
The thirteen per-mode palette.* color keys each take a .light and/or .dark variant so dark mode gets its own value. palette.series, font.family, and font.size are single values shared across modes (a .light or .dark on them does nothing). palette.mapColor recolors choropleths only; heatmaps keep their built-in scheme. No annotation sets the default light or dark mode or the user toggle: that lives in the instance theme. Environment-level theming is not applied yet.
// Model-wide defaults (## applies to every view in the model):
## theme.palette.series = ["#14b3cb", "#e47404", "#1474a4"]
## theme.font.family = "Inter, sans-serif"
// Per-view override (# applies to this result only; beats the instance theme):
# theme.palette.background.light = "#fafafa"
# theme.palette.background.dark = "#111111"
# theme.palette.tableHeader.dark = "#94a3b8"
view: revenue_by_month is {
group_by: month
aggregate: revenue
}Precedence, highest to lowest, per key: # theme.* on the view, then ## theme.* model default, then the instance theme, then Publisher's built-in defaults. A per-chart annotation overrides the instance for the keys it sets; unset keys fall through to the instance. (This is the reverse of a bare @malloydata/render embed, where the embedder wins: Publisher reads the annotation itself and layers it on top.)
Quote values that contain spaces or a leading #. The light/dark default (defaultMode) and the toggle lock (allowUserToggle) are instance-only: set them in the config theme block or the editor, not as annotations. Annotation forms that look valid but do nothing, such as a flat # theme.tableHeaderColor, are dropped without an error.
A sparkline needs two things: a # hidden nested view and a .sparkline= property naming it. If it does not show, check that # hidden is on the nested view and that its name matches .sparkline=.
# big_value { sparkline=trend }
view: revenue_kpi is {
aggregate:
# label="Revenue"
# currency
revenue
nest:
# line_chart { size=spark }
# hidden
trend is { group_by: order_date, aggregate: revenue, order_by: order_date }
}# big_value { comparison_field=prior_month comparison_label="vs Last Month" }
view: rev_delta is {
aggregate:
# label="Revenue"
# currency
revenue
# hidden
prior_month
}Use down_is_good=true for metrics where decrease is positive (churn, defects).
view: carriers is {
group_by: carrier, aggregate: flight_count
nest: # line_chart { size=spark }
trend is { group_by: month, aggregate: flight_count, order_by: month }
}# bar_chart { y=['revenue','cost'] }
view: rev_vs_cost is { group_by: quarter, aggregate: revenue, cost }# list_detail
view: explorer is {
group_by: region, aggregate: revenue
nest: # bar_chart
by_category is { group_by: category, aggregate: revenue, order_by: revenue desc, limit: 10 }
}There is no auto-binning function: autobin(...) does not exist and fails with Unknown function 'autobin'. Bin by arithmetic, choosing the width from the column's actual range: query min, max and a few percentiles first, and say in the view's doc where the width came from. A bin width nobody derived is a business decision in disguise.
# bar_chart
view: price_dist is {
group_by: bucket is floor(price / 20) * 20 // 20 is the bin width, from the observed range
aggregate: order_count is count()
order_by: bucket
}| Desired | Malloy Approximation |
|---|---|
| Pie/donut | # bar_chart sorted by value |
| Treemap | Nested table with order_by: desc |
| Heatmap | # pivot with color values |
| Stacked area | # line_chart with series (overlaid lines) |
| Funnel | # bar_chart with ordered stages |
| Gauge/bullet | # big_value with .comparison_field |
nest:A top-level chart tag (e.g., # bar_chart) renders only the outer query; any nest: views are silently hidden from the rendering (still in raw data). To show nests, use # dashboard on the outer query with chart tags on each nest. Otherwise, drop the nest:.
| Mistake | Fix |
|---|---|
| Two aggregates in chart | ONE aggregate, or use y=['a','b'] |
# currency=usd0m on measure | # currency (no scale) on defs; scale only in views |
Several tags on a nest: line | One lone tag on the nest: line works; with several, put each tag on its own line above the nested view |
| Tags on same line | One tag per line |
| Sparkline not showing | Add # hidden to nested view AND reference in .sparkline= |
| Pivot > 30 columns | Filter/limit the nested group_by |
NOTE: The term 'constructor' is a reserved term in Vega-Lite. If the word 'constructor' appears in the query, it will cause the rendering to fail. Never use it in a query and avoid using it as a dimension in a model.
For more patterns, call search_malloy_docs with topics like "bar charts", "line charts", "dashboards", "histograms", "percent of total", "comparing timeframes", or "pivots".
© malloydata, MIT. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file
Just SKILL.md in skills/malloy-charts of malloydata/publisher.
Open the folder on GitHubat commit c43a052
Malloy Charts next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.
| Skill | Stars | Used in | Tokens | Auto-check | Licence | Repo updated |
|---|---|---|---|---|---|---|
| Malloy Charts this skillmalloydata/publisher | 116 | — | ~4.6k | Automated safety check: Pass | MIT | |
| Creating Dashboardsancoleman/ai-design-components | 525 | — | ~3.5k | Automated safety check: Pass | MIT | |
| Dashboard Creatormhattingpete/claude-skills-marketplace | 680 | — | ~489 | Automated safety check: Pass | Apache-2.0 | |
| Dashboardasgeirtj/system_prompts_leaks | 69k | — | ~4.1k | Automated safety check: Pass | CC0-1.0 | |
| Tuftearef-vc/tufte-claude-skill | 307 | — | ~1.3k | Automated safety check: Pass | MIT | |
| Mvizmatsonj/mviz | 227 | — | ~11k | Automated safety check: Pass | None |
ancoleman/ai-design-components
Creates comprehensive dashboard and analytics interfaces that combine data visualization, KPI cards, real-time updates, and interactive layouts.
mhattingpete/claude-skills-marketplace
Create HTML dashboards with KPI metric cards, bar/pie/line charts, progress indicators, and data visualizations.
asgeirtj/system_prompts_leaks
Use this for a dashboard, metrics page, KPI tracker, scorecard, data visualization or recurring report: a page or scroll story of charts, numbers and tables of data, whatever the data and wherever…
aref-vc/tufte-claude-skill
Apply Edward Tufte's principles to any data visualization, chart, dashboard, or infographic.
matsonj/mviz
A chart & report builder for AI. An agent skill from matsonj/mviz.
QwenLM/qwen-code-examples
Build full-stack dashboard applications using React/Next.js + shadcn/ui + Tailwind CSS + Recharts + Express with customizable data sources.
malloydata/publisher
Score one analytical answer against a verified golden, and score which of the entities the golden depends on retrieval delivered to the answerer.
malloydata/publisher
Fix a CRITICAL Trivy finding that is failing CI in this repo (a vulnerability, misconfiguration, or secret from security-scan.yml or image-scan.yml), or add, review, or retire an entry in…
malloydata/publisher
Turn a list of questions into an eval set, whatever shape it arrived in: a JSONL a customer sent, a CSV, a spreadsheet export, a markdown doc, an email thread, or a pull from production logs.
malloydata/publisher
Conduct a local Publisher evaluation loop in five steps: scrape/run, eval, diagnose, improve, checkpoint.
malloydata/publisher
Make the smallest safe Malloy model edit that closes a diagnosed model-owned gap, with a probe receipt for every factual claim.
malloydata/publisher
Decide whether ONE answer matches its golden, and say whether you believe the golden.
Categories
Read before choosing a chart or adding a chart annotation. An agent skill from malloydata/publisher. Malloy Charts is an agent skill from malloydata/publisher. Read before choosing a chart or adding a chart annotation.
Malloy Charts fits situations like: tasks that involve Data visualization; tasks that involve OKRs and executive reporting.
Run `npx skills add malloydata/publisher --skill malloy-charts -a claude-code`. Or copy the skill folder (skills/malloy-charts in malloydata/publisher) into .claude/skills/malloy-charts in your project. Claude Code loads it when a task matches its description.
Run `npx skills add malloydata/publisher --skill malloy-charts -a codex`. Or copy the skill folder (skills/malloy-charts in malloydata/publisher) into .agents/skills/malloy-charts in your project. Codex loads it when a task matches its description.
Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add malloydata/publisher --skill malloy-charts -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/malloy-charts, .gemini/skills/malloy-charts, .github/skills/malloy-charts and .opencode/skills/malloy-charts in your project.
SKILL.md names no scripts, command-line tools or credentials: Malloy Charts is instructions for the agent only.
SKILL.md names 1 domain. As links in the text: docs.malloydata.dev. This is read from the text; nothing was executed.
Our automated static check of SKILL.md found no risky patterns, such as piping downloads into a shell, reading credential files or hidden Unicode. It is not a guarantee. Review the folder before installing.
Malloy Charts is published under the MIT licence (the repository's licence). It allows redistribution, so the full SKILL.md is shown on this page.
About 4.6k tokens (SKILL.md is roughly 18k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full.
Skills that share tags, products or a category with Malloy Charts: Creating Dashboards (ancoleman/ai-design-components, 525 stars), Dashboard Creator (mhattingpete/claude-skills-marketplace, 680 stars), Dashboard (asgeirtj/system_prompts_leaks, 69k stars) and Tufte (aref-vc/tufte-claude-skill, 307 stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.
malloydata (a GitHub organization) maintains it in malloydata/publisher, which has 116 GitHub stars. The repository holds 29 skills in this directory. The repository was last updated on October 10, 2026.
Source: malloydata/publisher on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.