Your Own Charts, Not a Prescribed Stack
Prerequisite: the weekly rhythm from Module 2 so far, and a transformation-log.jsonl with
at least one real week in it. Week 1 from Lesson 3 is enough to follow along.
After this lesson, you can: read your own log into whatever charting tool your project
already has, with zero new dependencies, and know why this course never hands you one.
The question this lesson answers
You have a log file. Every week adds one more line of JSON to it. At some point you want to see
the trend, not just read report.py's printed summary. So: what charting library does this
course tell you to install?
None. That refusal is the lesson.
What the original tracker required, and what this one doesn't
Lesson 2 already told you log_week.py and report.py import only from Python's standard
library, argparse, json, pathlib, datetime, and called that a deliberate choice. Here's
the rest of that choice. The original Billion Transformation Tracker, an earlier project by the
same author this course re-platforms from, required Polars, DuckDB, and Plotly as install
dependencies before you could see a single chart. Three packages, none of them stdlib, all of
them necessary just to look at your own numbers.
This re-platform ships zero charting dependency. Not a lighter one. None. log_week.py and
report.py stay stdlib-only, and transformation-log.jsonl is plain JSONL for the same reason
the scripts are plain Python: so nothing about seeing your own data depends on a stack this
course picked for you.
Here's the skill's own instruction on this, verbatim from SKILL.md:
"If the operator's project already has a charting tool in its own stack (matplotlib, a notebook,
a dashboard framework, anything), offer to read transformation-log.jsonl and feed it into that
tool instead of just printing the table, the log is plain JSONL specifically so it is not tied to
this skill's own scripts. If they have nothing, the table above is the whole deliverable; do not
install a charting library on their behalf."
Read that instruction twice, because it's doing two things at once. It tells Claude Code to
offer your own project's tooling first. And it tells Claude Code not to install anything on your
behalf if you don't have one. Both halves matter. A skill that quietly pip installs matplotlib
into your project because it seemed convenient is a skill that just added a dependency you never
asked for, to a project whose own linters and CI have never seen it before.
Why plain JSONL is the actual interface
A JSON object per line is not a clever format. That's the point. Parsing JSON isn't a charting feature, it's a language feature, so almost anything can pick the file up. Python needs two stdlib imports. A Jupyter notebook takes one cell. Most BI tools ship a JSON connector out of the box. Even Excel gets there, through CSV import once you've reshaped a few rows into columns.
transformation-log.jsonl was never going to be Plotly's format, or matplotlib's format, or any
single vendor's format. It's a text file with one record per line, wide enough a surface that
every option above can read it without this course picking a winner for you.
Reading your own log, stdlib only
Here's the minimal version, proving the portability claim rather than just asserting it. This is plain Python, no new imports beyond the standard library, reading whatever your log currently holds:
import json
rows = []
with open("transformation-log.jsonl") as f:
for line in f:
rows.append(json.loads(line))
weeks = [r["week_number"] for r in rows]
automation = [r["automation_index"] for r in rows]That's the whole read. Run it against the real Week 1 row from Lesson 3 and rows has one
dictionary in it, weeks is [1], automation is [14.55]. Log a few more weeks the way
Lesson 5 walks through and the same six lines read every one of them, in order, with no schema
migration and no format conversion, because the format never changed. It was JSONL from the
first line you ever wrote.
Once you have weeks and automation as two plain Python lists, you're done with what this
course teaches. Hand them to matplotlib.pyplot.plot(weeks, automation) if that's what your
project has. Paste the loop into a notebook cell if you work in one. Point your BI tool's JSON
connector at the file directly and skip the Python step entirely. All three are one honest step
past the six lines above, and none of those three steps belong to this course, because none of
them are the same for any two readers.
If you have nothing, the table is not a fallback
Say it plainly, because the skill's own instruction says it plainly: if your project has no
notebook, no BI tool, no charting library, running report.py and reading its printed table is
a complete, sufficient deliverable. Not a placeholder until you get around to installing
something. Not a lesser version of the "real" dashboard. The table has the same five metrics,
the same week-over-week numbers, the same graduation gate math, in the same file's data. What
changes with a chart is how the trend looks to your eye across twelve weeks, not what the
program measured or whether you completed it correctly.
That's the actual argument this lesson is making, not a footnote to it: your skills, your linters, your project structure. If your project already renders charts, the log is ready for that the moment it exists. If it doesn't, you graduate on the table exactly the same as someone who built a dashboard, because this program was never measuring your matplotlib setup. It was measuring five numbers against your own Week 1.
Every log eventually has a bad week in it, one where a number was wrong or a bottleneck was mis-typed. Lesson 8 covers how to fix that without hand-editing history to make the trend look better than the week actually was.
Reply here and it goes straight to Rod. Same as replying to one of his emails.