Requirements
- Target platform
- OpenClaw
- Install method
- Manual import
- Extraction
- Extract archive
- Prerequisites
- OpenClaw
- Primary doc
- SKILL.md
Generate publication-quality chart images from data. Supports line, bar, area, point, candlestick, pie/donut, heatmap, multi-series, and stacked charts. Use...
Generate publication-quality chart images from data. Supports line, bar, area, point, candlestick, pie/donut, heatmap, multi-series, and stacked charts. Use...
Hand the extracted package to your coding agent with a concrete install brief instead of figuring it out manually.
I downloaded a skill package from Yavira. Read SKILL.md from the extracted folder and install it by following the included instructions. Then review README.md for any prerequisites, environment setup, or post-install checks. Tell me what you changed and call out any manual steps you could not complete.
I downloaded an updated skill package from Yavira. Read SKILL.md from the extracted folder, compare it with my current installation, and upgrade it while preserving any custom configuration unless the package docs explicitly say otherwise. Then review README.md for any prerequisites, environment setup, or post-install checks. Summarize what changed and any follow-up checks I should run.
Generate PNG chart images from data using Vega-Lite. Perfect for headless server environments.
Built for Fly.io / VPS / Docker deployments: ✅ No native compilation - Uses Sharp with prebuilt binaries (unlike canvas which requires build tools) ✅ No Puppeteer/browser - Pure Node.js, no Chrome download, no headless browser overhead ✅ Lightweight - ~15MB total dependencies vs 400MB+ for Puppeteer-based solutions ✅ Fast cold starts - No browser spinup delay, generates charts in <500ms ✅ Works offline - No external API calls (unlike QuickChart.io)
cd /data/clawd/skills/chart-image/scripts && npm install
node /data/clawd/skills/chart-image/scripts/chart.mjs \ --type line \ --data '[{"x":"10:00","y":25},{"x":"10:30","y":27},{"x":"11:00","y":31}]' \ --title "Price Over Time" \ --output chart.png
node chart.mjs --type line --data '[{"x":"A","y":10},{"x":"B","y":15}]' --output line.png
node chart.mjs --type bar --data '[{"x":"A","y":10},{"x":"B","y":15}]' --output bar.png
node chart.mjs --type area --data '[{"x":"A","y":10},{"x":"B","y":15}]' --output area.png
# Pie node chart.mjs --type pie --data '[{"category":"A","value":30},{"category":"B","value":70}]' \ --category-field category --y-field value --output pie.png # Donut (with hole) node chart.mjs --type donut --data '[{"category":"A","value":30},{"category":"B","value":70}]' \ --category-field category --y-field value --output donut.png
node chart.mjs --type candlestick \ --data '[{"x":"Mon","open":100,"high":110,"low":95,"close":105}]' \ --open-field open --high-field high --low-field low --close-field close \ --title "Stock Price" --output candle.png
node chart.mjs --type heatmap \ --data '[{"x":"Mon","y":"Week1","value":5},{"x":"Tue","y":"Week1","value":8}]' \ --color-value-field value --color-scheme viridis \ --title "Activity Heatmap" --output heatmap.png
Compare multiple trends on one chart: node chart.mjs --type line --series-field "market" \ --data '[{"x":"Jan","y":10,"market":"A"},{"x":"Jan","y":15,"market":"B"}]' \ --title "Comparison" --output multi.png
node chart.mjs --type bar --stacked --color-field "category" \ --data '[{"x":"Mon","y":10,"category":"Work"},{"x":"Mon","y":5,"category":"Personal"}]' \ --title "Hours by Category" --output stacked.png
Price line with volume bars: node chart.mjs --type line --volume-field volume \ --data '[{"x":"10:00","y":100,"volume":5000},{"x":"11:00","y":105,"volume":3000}]' \ --title "Price + Volume" --output volume.png
node chart.mjs --sparkline --data '[{"x":"1","y":10},{"x":"2","y":15}]' --output spark.png Sparklines are 80x20 by default, transparent, no axes.
OptionDescriptionDefault--typeChart type: line, bar, area, point, pie, donut, candlestick, heatmapline--dataJSON array of data points---outputOutput file pathchart.png--titleChart title---widthWidth in pixels600--heightHeight in pixels300
OptionDescriptionDefault--x-fieldField name for X axisx--y-fieldField name for Y axisy--x-titleX axis labelfield name--y-titleY axis labelfield name--x-typeX axis type: ordinal, temporal, quantitativeordinal--y-domainY scale as "min,max"auto
OptionDescriptionDefault--colorLine/bar color#e63946--darkDark mode themefalse--svgOutput SVG instead of PNGfalse--color-schemeVega color scheme (category10, viridis, etc.)-
OptionDescriptionDefault--show-changeShow +/-% change annotation at last pointfalse--focus-changeZoom Y-axis to 2x data rangefalse--focus-recent NShow only last N data pointsall--show-valuesLabel min/max peak pointsfalse
OptionDescriptionDefault--series-fieldField for multi-series line charts---stackedEnable stacked bar modefalse--color-fieldField for stack/color categories-
OptionDescriptionDefault--open-fieldOHLC open fieldopen--high-fieldOHLC high fieldhigh--low-fieldOHLC low fieldlow--close-fieldOHLC close fieldclose
OptionDescriptionDefault--category-fieldField for pie slice categoriesx--donutRender as donut (with center hole)false
OptionDescriptionDefault--color-value-fieldField for heatmap intensityvalue--y-category-fieldY axis category fieldy
OptionDescriptionDefault--y2-fieldSecond Y axis field (independent right axis)---y2-titleTitle for second Y axisfield name--y2-colorColor for second series#60a5fa (dark) / #2563eb (light)--y2-typeChart type for second axis: line, bar, arealine Example: Revenue bars (left) + Churn area (right): node chart.mjs \ --data '[{"month":"Jan","revenue":12000,"churn":4.2},...]' \ --x-field month --y-field revenue --type bar \ --y2-field churn --y2-type area --y2-color "#60a5fa" \ --y-title "Revenue ($)" --y2-title "Churn (%)" \ --x-sort none --dark --title "Revenue vs Churn"
OptionDescriptionDefault--volume-fieldField for volume bars (enables dual-axis)---volume-colorColor for volume bars#4a5568
OptionDescriptionDefault--y-formatY axis format: percent, dollar, compact, decimal4, integer, scientific, or d3-format stringauto--subtitleSubtitle text below chart title---hlineHorizontal reference line: "value" or "value,color" or "value,color,label" (repeatable)-
OptionDescriptionDefault--annotationStatic text annotation---annotationsJSON array of event markers-
node chart.mjs --type line --data '[...]' \ --title "Iran Strike Odds (48h)" \ --show-change --focus-change --show-values --dark \ --output alert.png For recent action only: node chart.mjs --type line --data '[hourly data...]' \ --focus-recent 4 --show-change --focus-change --dark \ --output recent.png
Mark events on the chart: node chart.mjs --type line --data '[...]' \ --annotations '[{"x":"14:00","label":"News broke"},{"x":"16:30","label":"Press conf"}]' \ --output annotated.png
For proper time series with date gaps: node chart.mjs --type line --x-type temporal \ --data '[{"x":"2026-01-01","y":10},{"x":"2026-01-15","y":20}]' \ --output temporal.png Use --x-type temporal when X values are ISO dates and you want spacing to reflect actual time gaps (not evenly spaced).
Format axis values for readability: # Dollar amounts node chart.mjs --data '[...]' --y-format dollar --output revenue.png # → $1,234.56 # Percentages (values as decimals 0-1) node chart.mjs --data '[...]' --y-format percent --output rates.png # → 45.2% # Compact large numbers node chart.mjs --data '[...]' --y-format compact --output users.png # → 1.2K, 3.4M # Crypto prices (4 decimal places) node chart.mjs --data '[...]' --y-format decimal4 --output molt.png # → 0.0004 # Custom d3-format string node chart.mjs --data '[...]' --y-format ',.3f' --output custom.png Available shortcuts: percent, dollar/usd, compact, integer, decimal2, decimal4, scientific
Add context below the title: node chart.mjs --title "MOLT Price" --subtitle "20,668 MOLT held" --data '[...]' --output molt.png
Use --dark for dark mode. Auto-select based on time: Night (20:00-07:00 local): --dark Day (07:00-20:00 local): light mode (default)
echo '[{"x":"A","y":1},{"x":"B","y":2}]' | node chart.mjs --output out.png
For advanced charts: node chart.mjs --spec my-spec.json --output custom.png
After generating a chart, always send it back to the user's channel. Don't just save to a file and describe it — the whole point is the visual. # 1. Generate the chart node chart.mjs --type line --data '...' --output /data/clawd/tmp/my-chart.png # 2. Send it! Use message tool with filePath: # action=send, target=<channel_id>, filePath=/data/clawd/tmp/my-chart.png Tips: Save to /data/clawd/tmp/ (persistent) not /tmp/ (may get cleaned) Use action=send with filePath — thread-reply does NOT support file attachments Include a brief caption in the message text Auto-use --dark between 20:00-07:00 Israel time Updated: 2026-02-04 - Added --y-format (percent/dollar/compact/decimal4) and --subtitle
Data access, storage, extraction, analysis, reporting, and insight generation.
Largest current source with strong distribution and engagement signals.