agentsclimarketplace

Svg chart builder

Skill megandmartin/agent-skills-repo/skills/research-analysis/svg-chart-builder

75 production-grade agent skills for Hermes Agent + Paperclip — research, write, organize, earn, and run an AI workforce. Every skill passes a QA gate with hard safety rails. Built by Gen AI Hub.

Install
npx -y skills add megandmartin/agent-skills-repo --skill svg-chart-builder

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

2 things to look at

  • 13 days oldThe repository was created 13 days ago. New is not bad, but a brand new repository carrying a familiar-sounding name is the shape a typosquat arrives in, and there has been no time for anyone else to find a problem with it.
  • 0 stars0 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.

What its author says it does

Copied from the file, not written here

Generate clean, consistently styled SVG bar and line charts from CSV data using python3 stdlib only — no matplotlib, no dependencies — saved as .svg files. Use when the user says "chart this", "visualize this CSV", "make a bar/line chart", "graph this data", or wants a visual for a report or deck. Don't use for computing the stats and findings themselves — that's csv-data-analyst; run it first and chart its output.

The file declares its own license as MIT. That is the author’s claim about this one file, and it is not the same thing as the license GitHub reports for the repository, which is listed with the other numbers below.

SKILL.md

7.1 KB, as published. Nobody here has run it

SVG Chart Builder

Produces publication-ready bar and line charts as standalone .svg files from a two-column CSV (label, value), using only python3's stdlib. One house style — clean axis, readable labels, one accent color — so every chart from this skill looks like it belongs to the same report. The standard: the chart plots exactly the numbers in the CSV (verified against a recomputed max/min), axes never lie (bars start at zero), and the file opens in any browser.

When to Use

  • User has numbers (CSV or a table from csv-data-analyst / survey-response-synthesizer) and wants a visual.
  • Charts for HTML reports, decks, or landing pages where a dependency-free .svg is ideal.
  • Not for: the analysis itself — csv-data-analyst finds the story; this skill draws it. Not for interactive dashboards (that's an app build, outside this track).

Quick Reference

ActionCommand / Call
Precheckcommand -v python3; CSV must be label,value with a header row
Bar chartpython3 chart.py data.csv out.svg bar "Title" (script in step 3)
Line chartpython3 chart.py data.csv out.svg line "Title"
Verify outputpython3 -c "print(open('out.svg').read(120))" — starts with <svg
Viewopen the .svg in any browser; embeds directly in HTML via <img> or inline

Procedure

  1. Precheckcommand -v python3. Confirm the CSV is two columns (label,value) with a header; if it has more columns, ask which value column to plot and reshape first. Bar for categories, line for ordered sequences (time) — confirm the choice matches the data.
  2. Sanity-scan the data — check for: non-numeric values, negative numbers (bars handle them; note it), >16 categories for bars (aggregate the tail into "Other" first, with the user's OK), unsorted time labels for lines (sort chronologically, tell the user).
  3. Write the generator once per session — save as /tmp/chart.py:
    import csv, sys, html
    src, out, kind, title = sys.argv[1], sys.argv[2], sys.argv[3], sys.argv[4]
    rows = list(csv.reader(open(src, newline='', encoding='utf-8-sig')))[1:]
    labels = [r[0] for r in rows]; vals = [float(r[1]) for r in rows]
    W, H, L, R, T, B = 720, 400, 64, 24, 56, 64          # canvas + margins
    pw, ph = W - L - R, H - T - B
    top = max(max(vals), 0) or 1; bot = min(min(vals), 0)
    y = lambda v: T + ph * (top - v) / (top - bot)
    ACCENT, INK, GRID, FONT = "#4F46E5", "#1F2937", "#E5E7EB", "font-family='Helvetica,Arial,sans-serif'"
    s = [f"<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 {W} {H}' {FONT}>",
         f"<text x='{L}' y='28' font-size='18' font-weight='bold' fill='{INK}'>{html.escape(title)}</text>"]
    for i in range(5):                                    # gridlines + y labels
        gv = bot + (top - bot) * i / 4
        s.append(f"<line x1='{L}' y1='{y(gv):.1f}' x2='{W-R}' y2='{y(gv):.1f}' stroke='{GRID}'/>")
        s.append(f"<text x='{L-8}' y='{y(gv)+4:.1f}' font-size='11' text-anchor='end' fill='{INK}'>{gv:,.6g}</text>")
    step = pw / len(vals)
    if kind == "bar":
        bw = step * 0.62
        for i, v in enumerate(vals):
            x = L + i * step + (step - bw) / 2
            s.append(f"<rect x='{x:.1f}' y='{min(y(v),y(0)):.1f}' width='{bw:.1f}' "
                     f"height='{abs(y(v)-y(0)):.1f}' fill='{ACCENT}' rx='2'/>")
    else:
        pts = " ".join(f"{L + (i+0.5)*step:.1f},{y(v):.1f}" for i, v in enumerate(vals))
        s.append(f"<polyline points='{pts}' fill='none' stroke='{ACCENT}' stroke-width='2.5'/>")
        s += [f"<circle cx='{p.split(',')[0]}' cy='{p.split(',')[1]}' r='3.5' fill='{ACCENT}'/>" for p in pts.split()]
    for i, lab in enumerate(labels):                      # x labels, thinned if crowded
        if len(labels) <= 12 or i % (len(labels) // 12 + 1) == 0:
            s.append(f"<text x='{L + (i+0.5)*step:.1f}' y='{H-B+18}' font-size='11' "
                     f"text-anchor='middle' fill='{INK}'>{html.escape(lab[:14])}</text>")
    s.append("</svg>")
    open(out, "w").write("\n".join(s)); print(f"wrote {out}: {kind}, {len(vals)} points")
    
  4. Generatepython3 /tmp/chart.py data.csv revenue_by_month.svg line "Revenue by month". Expected output: wrote ... line, N points. Name files descriptively (what_by_what.svg), never chart1.svg.
  5. Verify visually and numerically — confirm the file starts with <svg, then check the tallest bar / highest point corresponds to the CSV's max value (python3 -c one-liner over the CSV). Offer the user the file and, if the destination is an HTML report, the inline-embed option.

Output Template

Chart saved: <absolute path>.svg
Type: bar|line | Points: N | Source: <csv path>, column <name>
Max plotted: <label> = <value> (matches CSV max: yes)
Style: house (720x400, indigo #4F46E5 accent, zero-based value axis)
Caveats: <tail aggregated into "Other" / labels thinned / negative values present / none>

Pitfalls

  • Truncated value axis exaggerating differences — starting bars at 90 makes a 3% gap look like 3x. Recovery: the script pins the axis to zero for bars by design (max(...,0)/min(...,0)); if the user asks for a zoomed axis on a line chart, add a visible axis-break note in the title, never silently.
  • Too many categories — 40 bars render as unreadable slivers. Recovery: cap bars at 16; aggregate the smallest into "Other" (disclosed in caveats) or switch to a sorted top-N chart with the user's OK.
  • Currency/percent strings crash float()"$1,200" in the value column throws. Recovery: strip $ € £ , % in a pre-pass (or via csv-data-analyst's cleaning), and report how many values were cleaned.
  • Unescaped labels break the XML — a label containing & or < produces an .svg that won't open. Recovery: the script routes every label and title through html.escape; if a chart won't render, check for raw ampersands first.
  • Chart contradicts the analysis — plotting a different column or stale file than the findings cite. Recovery: the numeric verification step (max value cross-check) is mandatory before delivering; state the source column in the output block.

Verification

  • File exists, starts with <svg, and opens in a browser
  • Highest/lowest plotted point matches the CSV's actual max/min
  • Bar charts have a zero-based value axis (or a disclosed break)
  • All labels readable (thinned/truncated per the script, noted if so)
  • Filename is descriptive; source CSV and column stated in the delivery note

Gives 0 of the 12 instructions most images graphics skills give

Counted across 371 of the 372 authors here whose files we hold, read 2026-08-06

  • create a complete brand world in one imagein 19 of 371, across 5 files
  • infer the brand strategy before generatingin 19 of 371, across 5 files
  • use a clean presentation gridin 19 of 371, across 5 files
  • confirm connection status is activein 19 of 371, across 4 files
  • base the visual system on meaningin 17 of 371, across 3 files
  • use very little textin 17 of 371, across 3 files
  • make every panel feel connectedin 17 of 371, across 3 files
  • call RUBE_SEARCH_TOOLS firstin 17 of 371, across 3 files
  • convert dash-format node IDs to colon formatin 17 of 371, across 5 files
  • match reference quality and rhythm if providedin 16 of 371, across 2 files
  • narrow scope or reduce depth to avoid oversized payloadsin 16 of 371, across 4 files
  • generate a simple and memorable logoin 15 of 371, across 1 file

Said here and by no other author read

  • verify python3 is available
  • confirm the CSV is two columns with a header
  • check data for non-numeric values and negative numbers
  • aggregate categories beyond sixteen into Other
  • sort line charts chronologically
  • write the generator script to tmp

Grouped from the skills themselves: near-identical wordings counted once, and counted by distinct author, so one author publishing three of these counts once.

Keep looking

Skills are one crate of 328,083. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.