Chart Image

Generate publication-quality chart images from data. Supports line, bar, area, point, candlestick, pie/donut, heatmap, multi-series, and stacked charts. Use...

MIT-0 · Free to use, modify, and redistribute. No attribution required.
9 · 6.1k · 36 current installs · 38 all-time installs
byDanny Shmueli@dannyshmueli
MIT-0
Security Scan
VirusTotalVirusTotal
Benign
View report →
OpenClawOpenClaw
Benign
high confidence
Purpose & Capability
Name/description match the actual footprint: included code (scripts/chart.mjs) and package.json depend on vega, vega‑lite, and sharp which are the expected libraries for server‑side chart rendering. No unrelated binaries, credentials, or config paths are requested.
Instruction Scope
SKILL.md and CAPABILITY.md instruct the agent to run the included Node script and to pass data via JSON/temporary files. The README and capability docs explicitly warn against unsafe shell interpolation. The instructions do not attempt to read system secrets or reach out to external endpoints on their own; they rely on the operator to supply data (stdin, files, or CLI args).
Install Mechanism
No formal install spec in registry; the skill instructs running `npm install` in the scripts folder. Installing pulls packages from the public npm registry (vega, vega‑lite, sharp and platform-specific sharp binaries listed in package-lock). This is expected for a Node-based tool but carries the usual moderate supply-chain risk of npm dependencies—nothing unusual like a remote tarball or URL shortener is used.
Credentials
The skill requests no environment variables, no credentials, and no config paths. That aligns with a self-contained chart generator that runs locally on provided data.
Persistence & Privilege
Skill is not forced-always, and there is no indication it modifies other skills or global agent config. It runs as an on-demand script with no elevated persistence requirements.
Assessment
This skill appears to be what it says: a Node.js tool that renders charts using Vega/Vega‑Lite and Sharp. Before installing, consider these precautions: 1) Review the full scripts/chart.mjs source (it was included) and ensure it contains no unexpected network or filesystem operations beyond reading input and writing the output file. 2) Install dependencies (npm install) in an isolated environment or container (e.g., a Docker image or sandbox) to limit blast radius. 3) Inspect package-lock.json for any unexpected packages and pin versions or use reproducible installs if you rely on it in production. 4) Avoid passing sensitive files or piping data from untrusted network endpoints directly into the tool (prefer vetted data files or temporary files passed by the runtime). 5) Follow the CAPABILITY.md guidance: invoke the script using argv-style execution (not shell-interpolated commands) to avoid command-injection risks when user-supplied text is part of arguments. If you want higher assurance, run the npm install step offline from a vetted lockfile or audit the npm packages with your supply-chain tooling before deploying.

Like a lobster shell, security has layers — review code before you run it.

Current versionv2.6.18
Download zip
latestvk97dtk5wfapx3jbn0hsytf8frh839yse

License

MIT-0
Free to use, modify, and redistribute. No attribution required.

SKILL.md

Chart Image Generator

Generate PNG chart images from data using Vega-Lite. Perfect for headless server environments.

Why This Skill?

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)

Setup (one-time)

cd /data/clawd/skills/chart-image/scripts && npm install

Quick Usage

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

Chart Types

Line Chart (default)

node chart.mjs --type line --data '[{"x":"A","y":10},{"x":"B","y":15}]' --output line.png

Bar Chart

node chart.mjs --type bar --data '[{"x":"A","y":10},{"x":"B","y":15}]' --output bar.png

Area Chart

node chart.mjs --type area --data '[{"x":"A","y":10},{"x":"B","y":15}]' --output area.png

Pie / Donut Chart

# 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

Candlestick Chart (OHLC)

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

Heatmap

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

Multi-Series Line Chart

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

Stacked Bar Chart

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

Volume Overlay (Dual Y-axis)

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

Sparkline (mini inline chart)

node chart.mjs --sparkline --data '[{"x":"1","y":10},{"x":"2","y":15}]' --output spark.png

Sparklines are 80x20 by default, transparent, no axes.

Options Reference

Basic Options

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

Axis Options

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
--x-formatTemporal X axis label format (d3-time-format, e.g. %b %d, %H:%M)auto
--x-sortX axis order: ascending, descending, or none (preserve input order)auto
--x-label-limit PXMax pixel width for X axis labels before Vega truncates themauto
--y-label-limit PXMax pixel width for Y axis labels before Vega truncates themauto
--y-domainY scale as "min,max"auto
--y-padAdd vertical padding as a fraction of range (e.g. 0.1 = 10%)0

Visual Options

OptionDescriptionDefault
--colorLine/bar color#e63946
--darkDark mode themefalse
--svgOutput SVG instead of PNGfalse
--no-pointsHide point markers on line chartsfalse
--line-width NSet line thickness in pixels for line charts2
--point-size NSet point marker size for line/point charts60
--bar-radius NRound bar corners in pixels for bar-based charts0
--color-schemeVega color scheme (category10, viridis, etc.)-

Alert/Monitor Options

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
--last-valueLabel the final data point valuefalse

Multi-Series/Stacked Options

OptionDescriptionDefault
--series-fieldField for multi-series line charts-
--stackedEnable stacked bar modefalse
--color-fieldField for stack/color categories-

Candlestick Options

OptionDescriptionDefault
--open-fieldOHLC open fieldopen
--high-fieldOHLC high fieldhigh
--low-fieldOHLC low fieldlow
--close-fieldOHLC close fieldclose

Pie/Donut Options

OptionDescriptionDefault
--category-fieldField for pie slice categoriesx
--donutRender as donut (with center hole)false

Heatmap Options

OptionDescriptionDefault
--color-value-fieldField for heatmap intensityvalue
--y-category-fieldY axis category fieldy

Dual-Axis Options (General)

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
--y2-formatRight-axis format: percent, dollar, compact, integer, decimal4, or d3-format stringauto

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" --y2-format ".1f" \
  --y-title "Revenue ($)" --y2-title "Churn (%)" \
  --x-sort none --dark --title "Revenue vs Churn"

Volume Overlay Options (Candlestick)

OptionDescriptionDefault
--volume-fieldField for volume bars (enables dual-axis)-
--volume-colorColor for volume bars#4a5568

Formatting Options

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)-

Annotation Options

OptionDescriptionDefault
--annotationStatic text annotation-
--annotationsJSON array of event markers-

Alert-Style Chart (recommended for monitors)

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

Timeline Annotations

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

Temporal X-Axis

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).

Y-Axis Formatting

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

Chart Subtitle

Add context below the title:

node chart.mjs --title "MOLT Price" --subtitle "20,668 MOLT held" --data '[...]' --output molt.png

Theme Selection

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)

Social Size Presets

Use --output-size when the chart is meant for a specific surface:

# Bluesky / OG-style landscape post
node chart.mjs --type line --data '[...]' --output-size bluesky --output bluesky-chart.png

# Instagram / Threads portrait post
node chart.mjs --type line --data '[...]' --output-size portrait --output portrait-chart.png

Available presets include twitter, discord, slack, linkedin, bluesky (bsky alias), youtube, instagram, portrait, story, thumbnail, wide, and square.

Piping Data

echo '[{"x":"A","y":1},{"x":"B","y":2}]' | node chart.mjs --output out.png

Custom Vega-Lite Spec

For advanced charts:

node chart.mjs --spec my-spec.json --output custom.png

⚠️ IMPORTANT: Always Send the Image!

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 filePaththread-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-03-20 - Added --y2-format so dual-axis and volume-overlay charts can format the right axis independently (percent, dollar, compact, custom d3-format); version bumped to 2.6.17

Files

6 total
Select a file
Select a file to preview.

Comments

Loading comments…