Generate charts from tabular data via the bundled scripts/charts.py toolkit.
Each function takes a DataFrame or a file path plus the columns to plot, and
saves a PNG (returning the path). It handles theming, figure sizing, label
rotation, NaN dropping, legend placement, and saving.
Instructions
- Provide the data source: a pandas DataFrame, or a path to a
.csv / .tsv /
.json file.
- Call the function for the chart you need, passing the column names:
bar(data, x, y) — one value per category (horizontal=True for barh)
grouped_bar(data, x, y, group) — value per category split by group
(stacked=True to stack)
line(data, x, y, group=None) — value over an ordered axis, one line per
group
scatter(data, x, y, group=None, size=None) — two numeric columns
histogram(data, y, bins=20, group=None) — distribution of one column
pie(data, x, y, donut=False) — share of y per category x
- Optional keyword args on every chart:
title, xlabel, ylabel (derived
from column names if omitted), out (default "chart.png"; pass None to
skip saving), dpi (default 150), figsize, palette.
- The function returns the saved image path. See
references/cheatsheet.md for
full signatures and a chart-selection table.
Usage
Import:
from charts import bar, line, pie
bar("sales.csv", x="region", y="revenue", title="Revenue by region",
out="revenue.png")
CLI:
python scripts/charts.py grouped_bar sales.csv \
--x region --y revenue --group quarter --stacked --out by_quarter.png
Bundled files
scripts/charts.py — the toolkit: load_data, apply_theme, save_fig, and
six chart functions (bar, grouped_bar, line, scatter, histogram,
pie), plus a CLI. Depends on matplotlib and pandas; runs headless.
references/cheatsheet.md — chart-selection table, full signatures, and
copy-paste CLI examples.
assets/sample_sales.csv — a small demo dataset that exercises every chart.
Defaults
- Colorblind-friendly palette and a shared theme across charts.
- Figure size, x-label rotation, and legend placement adapt to the data.
- Rows with missing values in the plotted columns are dropped before drawing.
- Output is a saved PNG at 150 DPI by default (override
out and dpi).
Run this — do not improvise
This capability's deterministic implementation is a RAPP single-file agent, linked beside this file as chart_builder_agent.py and embedded as the fenced Python below (sha256 f0e78a1c34b818da…; a byte-exact copy is also vaulted in the capsule comment at the end of this file). On a host with sandbox execution, run the linked file directly — if it is missing, write the fence contents verbatim to chart_builder_agent.py first:
python3 chart_builder_agent.py '{"key": "value"}' # arguments as one JSON object
echo '{"key": "value"}' | python3 chart_builder_agent.py # or on stdin
python3 chart_builder_agent.py --tool # emit the JSON tool contract
Treat stdout as a tool result. If it reports missing or unresolved inputs, stop and collect them. If it returns steps, execute those steps in order exactly as returned; if it returns instructions, follow them with the supplied inputs. Otherwise use the result verbatim. Do not invent behavior beyond that output. On a host without code execution, treat the Parameters schema and the code below as the exact specification and never paraphrase a step. Never edit inside the generated markers; a converter-equipped host can instead restore the original file checksum-verified with the installed rapp-agent-converter/scripts/toast.py convert SKILL.md --to agent.
"""ChartBuilder -- Use this skill whenever the user asks to visualize, chart, plot, or graph data (bar, line, scatter, histogram, pie) from a CSV, table, or DataFrame. It gives the agent prebuilt, parameterized matplotlib functions so charts are produced faster and more reliably — with consistent styling and sane defaults — instead of hand-writing matplotlib each time.
Generated by the rapp skill from chart-builder. The RCI capsule at the bottom of this file carries the full original; `toast.py convert` restores it byte-exact."""
import json
import re
import sys
try:
from agents.basic_agent import BasicAgent
except ImportError: # running OUTSIDE a brainstem -- stay executable anyway.
class BasicAgent: # noqa: D101 - minimal stand-in, same contract
def __init__(self, name=None, metadata=None):
if name:
self.name = name
if metadata:
self.metadata = metadata
def perform(self, **kwargs):
return "Not implemented."
def system_context(self):
return None
def to_tool(self):
return {"type": "function", "function": {
"name": self.name,
"description": self.metadata.get("description", ""),
"parameters": self.metadata.get("parameters", {})}}
# The procedural layer, verbatim from the source capability.
INSTRUCTIONS = 'Generate charts from tabular data via the bundled `scripts/charts.py` toolkit.\nEach function takes a DataFrame or a file path plus the columns to plot, and\nsaves a PNG (returning the path). It handles theming, figure sizing, label\nrotation, NaN dropping, legend placement, and saving.\n\n## Instructions\n1. Provide the data source: a pandas DataFrame, or a path to a `.csv` / `.tsv` /\n `.json` file.\n2. Call the function for the chart you need, passing the column names:\n - `bar(data, x, y)` — one value per category (`horizontal=True` for barh)\n - `grouped_bar(data, x, y, group)` — value per category split by `group`\n (`stacked=True` to stack)\n - `line(data, x, y, group=None)` — value over an ordered axis, one line per\n `group`\n - `scatter(data, x, y, group=None, size=None)` — two numeric columns\n - `histogram(data, y, bins=20, group=None)` — distribution of one column\n - `pie(data, x, y, donut=False)` — share of `y` per category `x`\n3. Optional keyword args on every chart: `title`, `xlabel`, `ylabel` (derived\n from column names if omitted), `out` (default `"chart.png"`; pass `None` to\n skip saving), `dpi` (default `150`), `figsize`, `palette`.\n4. The function returns the saved image path. See `references/cheatsheet.md` for\n full signatures and a chart-selection table.\n\n## Usage\nImport:\n```python\nfrom charts import bar, line, pie\nbar("sales.csv", x="region", y="revenue", title="Revenue by region",\n out="revenue.png")\n```\n\nCLI:\n```bash\npython scripts/charts.py grouped_bar sales.csv \\\n --x region --y revenue --group quarter --stacked --out by_quarter.png\n```\n\n## Bundled files\n- `scripts/charts.py` — the toolkit: `load_data`, `apply_theme`, `save_fig`, and\n six chart functions (`bar`, `grouped_bar`, `line`, `scatter`, `histogram`,\n `pie`), plus a CLI. Depends on `matplotlib` and `pandas`; runs headless.\n- `references/cheatsheet.md` — chart-selection table, full signatures, and\n copy-paste CLI examples.\n- `assets/sample_sales.csv` — a small demo dataset that exercises every chart.\n\n## Defaults\n- Colorblind-friendly palette and a shared theme across charts.\n- Figure size, x-label rotation, and legend placement adapt to the data.\n- Rows with missing values in the plotted columns are dropped before drawing.\n- Output is a saved PNG at 150 DPI by default (override `out` and `dpi`).'
# Ordered commands lifted verbatim from the capability's own documentation.
STEPS = []
class ChartBuilderAgent(BasicAgent):
def __init__(self):
self.name = 'ChartBuilder'
self.metadata = {
"name": "ChartBuilder",
"description": "Use this skill whenever the user asks to visualize, chart, plot, or graph data (bar, line, scatter, histogram, pie) from a CSV, table, or DataFrame. It gives the agent prebuilt, parameterized matplotlib functions so charts are produced faster and more reliably \u2014 with consistent styling and sane defaults \u2014 instead of hand-writing matplotlib each time.",
"parameters": {
"type": "object",
"properties": {},
"required": []
}
}
super().__init__(name=self.name, metadata=self.metadata)
def perform(self, **kwargs): # toaster:generated-perform
return json.dumps({"status": "ok", "instructions": INSTRUCTIONS,
"inputs": kwargs,
"note": "Prose-only capability: follow INSTRUCTIONS "
"with the given inputs."}, indent=2)
if __name__ == "__main__":
# echo '{"arg": "value"}' | python3 chart_builder_agent.py
# python3 chart_builder_agent.py '{"arg": "value"}'
# python3 chart_builder_agent.py --tool # emit the JSON tool contract
_a = sys.argv[1:]
if _a and _a[0] == "--tool":
print(json.dumps(ChartBuilderAgent().to_tool(), indent=2))
else:
_raw = _a[0] if _a else (sys.stdin.read().strip() or "{}")
print(ChartBuilderAgent().perform(**json.loads(_raw)))
# rci-capsule:v1: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
1---2name: chart-builder3description: Use this skill whenever the user asks to visualize, chart, plot, or graph data (bar, line, scatter, histogram, pie) from a CSV, table, or DataFrame. It gives the agent prebuilt, parameterized matplotlib functions so charts are produced faster and more reliably — with consistent styling and sane defaults — instead of hand-writing matplotlib each time.4---56Generate charts from tabular data via the bundled `scripts/charts.py` toolkit.7Each function takes a DataFrame or a file path plus the columns to plot, and8saves a PNG (returning the path). It handles theming, figure sizing, label9rotation, NaN dropping, legend placement, and saving.1011## Instructions121. Provide the data source: a pandas DataFrame, or a path to a `.csv` / `.tsv` /13 `.json` file.142. Call the function for the chart you need, passing the column names:15 - `bar(data, x, y)` — one value per category (`horizontal=True` for barh)16 - `grouped_bar(data, x, y, group)` — value per category split by `group`17 (`stacked=True` to stack)18 - `line(data, x, y, group=None)` — value over an ordered axis, one line per19 `group`20 - `scatter(data, x, y, group=None, size=None)` — two numeric columns21 - `histogram(data, y, bins=20, group=None)` — distribution of one column22 - `pie(data, x, y, donut=False)` — share of `y` per category `x`233. Optional keyword args on every chart: `title`, `xlabel`, `ylabel` (derived24 from column names if omitted), `out` (default `"chart.png"`; pass `None` to25 skip saving), `dpi` (default `150`), `figsize`, `palette`.264. The function returns the saved image path. See `references/cheatsheet.md` for27 full signatures and a chart-selection table.2829## Usage30Import:31```python32from charts import bar, line, pie33bar("sales.csv", x="region", y="revenue", title="Revenue by region",34 out="revenue.png")35```3637CLI:38```bash39python scripts/charts.py grouped_bar sales.csv \40 --x region --y revenue --group quarter --stacked --out by_quarter.png41```4243## Bundled files44- `scripts/charts.py` — the toolkit: `load_data`, `apply_theme`, `save_fig`, and45 six chart functions (`bar`, `grouped_bar`, `line`, `scatter`, `histogram`,46 `pie`), plus a CLI. Depends on `matplotlib` and `pandas`; runs headless.47- `references/cheatsheet.md` — chart-selection table, full signatures, and48 copy-paste CLI examples.49- `assets/sample_sales.csv` — a small demo dataset that exercises every chart.5051## Defaults52- Colorblind-friendly palette and a shared theme across charts.53- Figure size, x-label rotation, and legend placement adapt to the data.54- Rows with missing values in the plotted columns are dropped before drawing.55- Output is a saved PNG at 150 DPI by default (override `out` and `dpi`).5657<!-- toaster:generated:begin -->5859## Run this — do not improvise6061This capability's deterministic implementation is a RAPP single-file agent, linked beside this file as `chart_builder_agent.py` and embedded as the fenced Python below (sha256 f0e78a1c34b818da…; a byte-exact copy is also vaulted in the capsule comment at the end of this file). On a host with sandbox execution, run the linked file directly — if it is missing, write the fence contents verbatim to `chart_builder_agent.py` first:6263```bash64python3 chart_builder_agent.py '{"key": "value"}' # arguments as one JSON object65echo '{"key": "value"}' | python3 chart_builder_agent.py # or on stdin66python3 chart_builder_agent.py --tool # emit the JSON tool contract67```6869Treat stdout as a tool result. If it reports missing or unresolved inputs, stop and collect them. If it returns `steps`, execute those steps in order exactly as returned; if it returns `instructions`, follow them with the supplied inputs. Otherwise use the result verbatim. Do not invent behavior beyond that output. On a host without code execution, treat the Parameters schema and the code below as the exact specification and never paraphrase a step. Never edit inside the generated markers; a converter-equipped host can instead restore the original file checksum-verified with the installed `rapp-agent-converter/scripts/toast.py convert SKILL.md --to agent`.7071````python # rapp:deterministic72"""ChartBuilder -- Use this skill whenever the user asks to visualize, chart, plot, or graph data (bar, line, scatter, histogram, pie) from a CSV, table, or DataFrame. It gives the agent prebuilt, parameterized matplotlib functions so charts are produced faster and more reliably — with consistent styling and sane defaults — instead of hand-writing matplotlib each time.7374Generated by the rapp skill from chart-builder. The RCI capsule at the bottom of this file carries the full original; `toast.py convert` restores it byte-exact."""7576import json77import re78import sys7980try:81 from agents.basic_agent import BasicAgent82except ImportError: # running OUTSIDE a brainstem -- stay executable anyway.83 class BasicAgent: # noqa: D101 - minimal stand-in, same contract84 def __init__(self, name=None, metadata=None):85 if name:86 self.name = name87 if metadata:88 self.metadata = metadata8990 def perform(self, **kwargs):91 return "Not implemented."9293 def system_context(self):94 return None9596 def to_tool(self):97 return {"type": "function", "function": {98 "name": self.name,99 "description": self.metadata.get("description", ""),100 "parameters": self.metadata.get("parameters", {})}}101102# The procedural layer, verbatim from the source capability.103INSTRUCTIONS = 'Generate charts from tabular data via the bundled `scripts/charts.py` toolkit.\nEach function takes a DataFrame or a file path plus the columns to plot, and\nsaves a PNG (returning the path). It handles theming, figure sizing, label\nrotation, NaN dropping, legend placement, and saving.\n\n## Instructions\n1. Provide the data source: a pandas DataFrame, or a path to a `.csv` / `.tsv` /\n `.json` file.\n2. Call the function for the chart you need, passing the column names:\n - `bar(data, x, y)` — one value per category (`horizontal=True` for barh)\n - `grouped_bar(data, x, y, group)` — value per category split by `group`\n (`stacked=True` to stack)\n - `line(data, x, y, group=None)` — value over an ordered axis, one line per\n `group`\n - `scatter(data, x, y, group=None, size=None)` — two numeric columns\n - `histogram(data, y, bins=20, group=None)` — distribution of one column\n - `pie(data, x, y, donut=False)` — share of `y` per category `x`\n3. Optional keyword args on every chart: `title`, `xlabel`, `ylabel` (derived\n from column names if omitted), `out` (default `"chart.png"`; pass `None` to\n skip saving), `dpi` (default `150`), `figsize`, `palette`.\n4. The function returns the saved image path. See `references/cheatsheet.md` for\n full signatures and a chart-selection table.\n\n## Usage\nImport:\n```python\nfrom charts import bar, line, pie\nbar("sales.csv", x="region", y="revenue", title="Revenue by region",\n out="revenue.png")\n```\n\nCLI:\n```bash\npython scripts/charts.py grouped_bar sales.csv \\\n --x region --y revenue --group quarter --stacked --out by_quarter.png\n```\n\n## Bundled files\n- `scripts/charts.py` — the toolkit: `load_data`, `apply_theme`, `save_fig`, and\n six chart functions (`bar`, `grouped_bar`, `line`, `scatter`, `histogram`,\n `pie`), plus a CLI. Depends on `matplotlib` and `pandas`; runs headless.\n- `references/cheatsheet.md` — chart-selection table, full signatures, and\n copy-paste CLI examples.\n- `assets/sample_sales.csv` — a small demo dataset that exercises every chart.\n\n## Defaults\n- Colorblind-friendly palette and a shared theme across charts.\n- Figure size, x-label rotation, and legend placement adapt to the data.\n- Rows with missing values in the plotted columns are dropped before drawing.\n- Output is a saved PNG at 150 DPI by default (override `out` and `dpi`).'104105# Ordered commands lifted verbatim from the capability's own documentation.106STEPS = []107108109class ChartBuilderAgent(BasicAgent):110 def __init__(self):111 self.name = 'ChartBuilder'112 self.metadata = {113 "name": "ChartBuilder",114 "description": "Use this skill whenever the user asks to visualize, chart, plot, or graph data (bar, line, scatter, histogram, pie) from a CSV, table, or DataFrame. It gives the agent prebuilt, parameterized matplotlib functions so charts are produced faster and more reliably \u2014 with consistent styling and sane defaults \u2014 instead of hand-writing matplotlib each time.",115 "parameters": {116 "type": "object",117 "properties": {},118 "required": []119 }120 }121 super().__init__(name=self.name, metadata=self.metadata)122123 def perform(self, **kwargs): # toaster:generated-perform124 return json.dumps({"status": "ok", "instructions": INSTRUCTIONS,125 "inputs": kwargs,126 "note": "Prose-only capability: follow INSTRUCTIONS "127 "with the given inputs."}, indent=2)128129if __name__ == "__main__":130 # echo '{"arg": "value"}' | python3 chart_builder_agent.py131 # python3 chart_builder_agent.py '{"arg": "value"}'132 # python3 chart_builder_agent.py --tool # emit the JSON tool contract133 _a = sys.argv[1:]134 if _a and _a[0] == "--tool":135 print(json.dumps(ChartBuilderAgent().to_tool(), indent=2))136 else:137 _raw = _a[0] if _a else (sys.stdin.read().strip() or "{}")138 print(ChartBuilderAgent().perform(**json.loads(_raw)))139140# rci-capsule:v1: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141````142143<!-- toaster:generated:end -->144145<!-- rci-capsule:v1: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 -->