agent/skills/kuva/SKILL.md
Creates scientific plots from tabular data via the command line. Use when generating charts from CSV/TSV files, piping structured data to visualizations, or producing SVG/PNG/PDF figures without a GUI.
npx skillsauth add knoopx/pi kuvaInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
27 chart types from stdin, CSV, or TSV. Output format is inferred from -o extension: .png, .svg, or .pdf.
Every generated plot MUST be shown to the user. Never generate a plot and silently save it.
Save plots to /tmp by default. Never write plots to the current working directory unless the user explicitly requests it.
kuva ... -o /tmp/plot.pngread /tmp/plot.png to show the userWhen rendering several plots:
kuva ... -o /tmp/plot1.png, then kuva ... -o /tmp/plot2.png, etc.)read tool (e.g., read /tmp/plot1.png followed by read /tmp/plot2.png)Always prefer DuckDB pipe over file input. Kuva reads CSV directly via positional argument, but DuckDB gives you ignore_errors=true for messy data, CAST/aggregations on the fly, and no intermediate files. When piping, do NOT pass a file argument to kuva (it will read the file instead of stdin).
duckdb :memory: -csv << 'EOF' 2>/dev/null | kuva bar --label-col Vendor --value-col cnt \
--theme dark --color "#fad000" --background "#191033" \
--title 'Vendor Counts' -o plot.png
SELECT Vendor, COUNT(*) AS cnt FROM read_csv('data.csv', header=true, ignore_errors=true) GROUP BY Vendor ORDER BY cnt DESC;
EOF
CAST failures. Filter non-numeric rows: WHERE col != '' AND col NOT LIKE '%—%'."Payment Method".<< 'EOF' ... EOF) with duckdb for complex queries — -c struggles with quoting.kuva strip only.2>/dev/null so kuva receives clean CSV on stdin.| Chart | Command | Required Args | Notes |
| ------------ | ---------------- | ---------------------------- | ----------------------------------------------------------------------------------- |
| Bar chart | kuva bar | --label-col, --value-col | Use --count-by to count occurrences, or --agg sum/mean/median with --color-by |
| Pie chart | kuva pie | --label-col, --value-col | Pre-aggregated data only (no --agg); use --palette and --legend |
| Histogram | kuva histogram | (first column is data) | Use --bins N, --value-col to pick a specific column |
| Line chart | kuva line | --x, --y | Expects numeric x-axis; use --fill for area fill, --color-by for multi-series |
| Scatter plot | kuva scatter | --x, --y | Use --trend for regression line |
| Box plot | kuva box | --group-col, --value-col | Use --overlay-points or --overlay-swarm |
| Violin plot | kuva violin | --group-col, --value-col | Density visualization grouped by column |
| Strip plot | kuva strip | --group-col, --value-col | Individual data points per group; file input only (no pipe); no --color-by |
| Density | kuva density | --value | KDE curve; use --filled for area fill, --color-by to group |
Parameter naming varies by chart type: bar/box/violin/strip use --label-col or --group-col; histogram uses --value-col; density/line/scatter use --value, --x, --y. Check --help for the specific chart.
Single-color charts: --color "#hex" sets all bars/elements to one color. Works on bar, histogram, box, violin, strip.
Strip plot caveat: Does NOT support --color-by — use --color for a single fill, or switch to kuva violin / kuva box with --color-by if per-group coloring is needed.
duckdb :memory: -csv << 'EOF' 2>/dev/null | kuva bar --label-col x --value-col y --color "#fad000" \
--theme dark --background "#191033" -o plot.png
SELECT x, CAST(y AS DOUBLE) AS y FROM read_csv('data.csv', header=true, ignore_errors=true);
EOF
Multi-series charts: --color-by column + --palette name. Palette cycles per series. Not all chart types support --color-by — check --help.
Available palettes: category10, wong, okabe-ito, pastel, bold, tol-bright, tol-muted, tol-light, ibm
Pie charts: use --palette (it overrides --color). No per-slice color control via CLI.
Custom background: --background "#191033" overrides the theme's canvas color.
No custom themes via CLI. Only 4 built-in: light, dark, solarized, minimal. Use these defaults:
| kuva flag | Your palette value | Usage |
| -------------- | ------------------------- | -------------------------------- |
| --background | #191033 (base00) | Canvas background for all charts |
| --color | #fad000 (base0A/yellow) | Default bar/histogram fill color |
| --theme | dark | Dark theme as base |
Example: kuva bar --label-col x --value-col y --theme dark --color "#fad000" --background "#191033" -o plot.png
All chart types accept:
--theme light|dark|solarized|minimal--palette category10|wong|okabe-ito|pastel|bold|tol-bright|tol-muted|tol-light|ibm--cvd-palette deuteranopia|protanopia|tritanopia (overrides --palette)--background <CSS> — canvas background color--x-label, --y-label, --ticks N, --no-grid, --log-x/y--interactive (SVG only), --width, --height, --scale, --titleBar chart extras: --bar-width, --agg sum|mean|median|min|max, --count-by column
--color-by overrides --color; --count-by ignores --value-col--palette overrides --color on pie charts and multi-series charts--terminal is incompatible with -o file output--x "my column"SUM, GROUP BY, etc.)year*12+month)duckdb :memory: -csv << 'EOF' 2>/dev/null | kuva bar --label-col Vendor --value-col cnt \
--theme dark --color "#fad000" --background "#191033" \
--title 'Transactions by Vendor' \
-o payment.png
SELECT Vendor, COUNT(*) AS cnt FROM read_csv('data.csv', header=true, ignore_errors=true) GROUP BY Vendor ORDER BY cnt DESC;
EOF
duckdb :memory: -csv << 'EOF' 2>/dev/null | kuva pie --label-col Vendor --value-col total \
--theme dark --palette okabe-ito --background "#191033" \
--title 'Top Spending Vendors' --legend \
-o pie.png
SELECT Vendor, SUM(CAST(Amount AS DOUBLE)) AS total FROM read_csv('data.csv', header=true, ignore_errors=true) GROUP BY Vendor ORDER BY total DESC LIMIT 10;
EOF
duckdb :memory: -csv << 'EOF' 2>/dev/null | kuva histogram --value-col Amount --bins 30 \
--theme dark --color "#fad000" --background "#191033" \
--title 'Amount Distribution' --x-label 'Amount (€)' \
-o histogram.png
SELECT CAST(Amount AS DOUBLE) AS Amount FROM read_csv('data.csv', header=true, ignore_errors=true);
EOF
duckdb :memory: -csv << 'EOF' 2>/dev/null | kuva box --group-col Vendor --value-col Amount \
--theme dark --overlay-points --background "#191033" \
--title 'Spending Distribution' --x-label 'Vendor' --y-label 'Amount (€)' \
-o boxplot.png
SELECT Vendor, CAST(Amount AS DOUBLE) AS Amount FROM read_csv('data.csv', header=true, ignore_errors=true);
EOF
duckdb :memory: -csv << 'EOF' 2>/dev/null | kuva density --value Amount \
--theme dark --filled --background "#191033" \
--title 'Purchase Amount Density' --x-label 'Amount (€)' \
-o density.png
SELECT CAST(Amount AS DOUBLE) AS Amount FROM read_csv('data.csv', header=true, ignore_errors=true);
EOF
Convert dates to month numbers (year*12+month) in DuckDB since kuva's line chart expects numeric x:
duckdb :memory: -csv << 'EOF' 2>/dev/null | kuva line --x month_num --y total \
--theme dark --color "#fad000" --background "#191033" \
--fill --title 'Monthly Spending' --x-label 'Month' --y-label 'Total (€)' \
-o line.png
SELECT (STRFTIME(CAST(DATE_TRUNC('month', CAST(Date AS DATE)) AS DATE), '%Y')::INT * 12 + STRFTIME(CAST(DATE_TRUNC('month', CAST(Date AS DATE)) AS DATE), '%m')::INT) AS month_num, SUM(CAST(Amount AS DOUBLE)) AS total FROM read_csv('data.csv', header=true, ignore_errors=true) GROUP BY month_num ORDER BY month_num;
EOF
duckdb :memory: -csv << 'EOF' 2>/dev/null | kuva violin --group-col Tags --value-col Amount \
--theme dark --palette okabe-ito --background "#191033" \
--title 'Spending by Category' --x-label 'Tag' --y-label 'Amount (€)' \
-o violin.png
SELECT Tags, CAST(Amount AS DOUBLE) AS Amount FROM read_csv('data.csv', header=true, ignore_errors=true);
EOF
File input only (no pipe support); single color via --color (no --color-by).
kuva strip --group-col Vendor --value-col Amount \
--theme dark --color "#fad000" --background "#191033" \
--title 'Individual Purchases' --x-label 'Vendor' --y-label 'Amount (€)' \
-o strip.png data.csv
Basic charts (scatter, line, bar, histogram, pie), distributions (box, violin, strip, density, ridgeline), matrices and flows (heatmap, sankey, chord, upset), bioinformatics (volcano, manhattan, forest, candlestick). Check kuva <chart> --help for chart-specific options.
tools
Inform the user what is happening — skip passive lookups
development
Renders markdown to self-contained HTML with a custom dark stylesheet and opens in browser. Use when previewing markdown documents, generating styled HTML from README or report files.
testing
Programmatic hunk selection for Jujutsu — split, commit, or squash specific hunks without interactive prompts. Use when making partial commits or selective squashes.
content-media
Manage version control with Jujutsu (jj) — no staging area, immediate changes, smart rebasing. Use when navigating history, squashing, or pushing to Git remotes.