๐ Drawing a figure: the figure-drawer skill¶
Status: how-to.
Written for anyone who wants a figure in a draft: a pipeline, a
control loop, a taxonomy or an architecture, drawn once as TikZ for
the PDF and once as ASCII for every other format. Assumed: you have
a draft under content/drafts/, or are about to have one from a genre
skill (GENRE.md). Not covered here: what a good figure
looks like, which is TIKZ-STYLE.md; the two-form
contract, the marker syntax and originality, which are
WRITING-STANDARDS.md ยง10; and what each
figure check finding means, which is
figure-checks/README.md. This page says what
the skill does and when it runs.
๐งญ Table of contents¶
- What it is, and what it is not
- Three ways it runs
- What you get
- What it does, step by step
- The eleven layouts
- What the skill reads
- Checking a figure
- A worked example
- Thesis fragments
- What it never does
- Why the genre skills keep a short figure step
- When something goes wrong
โ What it is, and what it is not¶
figure-drawer owns how a figure is drawn: the layout, the
scaffold it starts from, panel letters, the ASCII twin, the check and
the look at the render. It does not decide whether a draft gets a
figure. Each genre sets its own threshold, from the tutorial (draw
every figure that makes a step clearer) to the survey (rarest of all,
since the comparison table usually does the work). deep-research
draws no figures.
It also never presents a draft. It draws one figure, checks it, and returns to whichever skill called it. The gate, the render, the prose check and the verbatim scan stay with that skill.
๐ฆ Three ways it runs¶
| Who calls it | When | What happens after |
|---|---|---|
A genre skill: survey-writer, tutorial-writer, textbook-chapter-writer, thesis-chapter-writer |
mid-draft, once the genre's figure step decides a figure is warranted | back to the genre skill's next step, which places the marker and caption, gates and renders |
draft-reviser |
you asked to redraw or fix a figure in an existing draft | back to draft-reviser, which logs the change in revisions.md |
| You, directly | you asked for a figure in an existing draft | a revision: the session continues in draft-reviser's write-back and gate steps |
You never name a skill. Ask in ordinary words and the right one answers. A direct request needs three things: which draft, where in it, and what the figure shows.
1 2 3 | |
1 2 | |
1 2 | |
On a direct request the genre's threshold does not apply, because you asked for the figure. With no draft to put it in, the skill says so and stops.
๐ฏ What you get¶
Two files under the draft's topic directory, plus one line (or block) in the draft that names them:
| Draft | In the draft | Files |
|---|---|---|
.md (survey, tutorial, textbook chapter) |
<!-- figure: figures/<name> --> on a line of its own, a caption line directly below it if the figure warrants one, and <!-- figureref: <name> --> wherever prose points at it |
figures/<name>.tex and figures/<name>.txt |
.tex (thesis chapter) |
\input{figures/<name>.tex} then %figure: figures/<name>, inside a hand-written figure float with \caption and \label when captioned |
the same pair |
The renderer puts the TikZ in the tex and pdf outputs and the ASCII
form, in a code block, in md, html and docx. Nothing writes
"Figure 3" by hand: the renderer, or your thesis's own LaTeX, numbers
it.
A flat draft (content/drafts/<slug>.md with no topic directory) would
put its figures in content/drafts/figures/, shared with every other
flat draft. The skill asks whether to move the draft and its dossier
into a topic directory first, or to drop the figure.
๐ช What it does, step by step¶
These are the nine steps of .claude/skills/figure-drawer/SKILL.md, in
its order.
- Looks, never copies (optional).
python -m chitragupta.draft figures <citekey>lists a cited paper's figures, with a crop of each. Seeing how a concept is usually drawn is fine. Reproducing one is not (AGENTS.md, WRITING-STANDARDS.md ยง10). - Picks the pattern, then the layout. It names what the figure argues, routes that to one of the eleven layouts, and reads that layout's reference file before drawing.
- Runs the taste gate. Before anything is written it asks: would a sentence or a table do this? Which node, edge or label can go? Which two nodes always travel together and become one? Is there one focal node? Is this one figure or two? It makes the trims itself. If the answer is a sentence, a table or two figures, it draws nothing and returns that verdict to the caller, or asks you on a direct request.
- Starts from the scaffold.
kpsewhich tikz.styfirst. If TikZ is missing, it writes no pair: the ASCII goes inline instead (a fence in Markdown,verbatimin a thesis fragment), with no marker. Otherwisepython -m chitragupta.figure new <figures-dir> <name> --layout <id>copies the layout's scaffold and its twin, keeps its% cg-layout:line, brings the house style block up to date asfigure syncwould, and never overwrites a figure (CLI.md). - Draws below the house block, never inside it
(TIKZ-STYLE.md). It
re-labels, names every node, places nodes relative to one another,
letters panels
(a),(b)if there is more than one, and keeps every citekey out of the figure file, because the gate reads the draft and does not follow\input. - Redraws the ASCII twin at
figures/<name>.txt, in ยง10's 7-bit alphabet: the same boxes, arrows and panel letters, named in the TikZ's own words. - Checks it with
python -m chitragupta.figure check figures/<name>.tex, and resolves or allows every objective finding. See Checking a figure. - Looks at the real render.
figure checkcompiles the figure in a bare article class, but the pipeline's own PDF is the draft's whole document, with its floats and neighbouring text, so labels can wrap and gaps close differently there.python -m chitragupta.figure looksets the figure alone on the page it prints on (the book's, for a book unit's figure), cropped to it, as a PDF and a 300 dpi PNG; once the draft carries the marker,--draftrenders the PDF too and writes a PNG of the page that holds the figure (CLI.md). The skill reads both against the pre-flight list in TIKZ-STYLE.md. This needs LuaLaTeX andpdftoppm(poppler), andpandocfor the page, whichchitragupta install os-depsinstalls on Linux. Without them, or in a harness that cannot view an image, the skill skips the look and says so. - Returns the two paths (or the taste gate's verdict), what the
taste gate cut, what
figure checkreported and allowed, and whether it looked at the render. The caller places the marker and the caption, then gates and renders.
๐งฉ The eleven layouts¶
Every figure starts from one of eleven scaffolds in assets/tikz/:
pipeline, map, layered stack, control loop, branching tree,
hub-and-spoke network, zoned spine, state machine, comparison, sequence
and timeline. assets/tikz/README.md says
when to reach for each, and
TIKZ-STYLE.md
gives the TikZ idiom each one uses.
๐ What the skill reads¶
SKILL.md is a short router. It reads one of these only when a step
sends it there, one copy whichever harness runs it:
File under .claude/skills/figure-drawer/references/ |
What it holds |
|---|---|
patterns.md |
what a figure argues, routed to the nearest layout |
layouts/<layout>.md |
one per layout: its anti-patterns and the reference ranges (node and edge counts, width, height, slack) measured from its scaffold and exemplars |
taste.md |
the taste gate's questions, and what goes back to the caller |
figures.md |
choosing a metaphor, panels, fitting without scaling, an annotated exemplar, looking at a source's figures, libraries and compiling, looking at the render |
placement.md |
where the pair goes, a host with no TikZ, a flat draft, a thesis fragment |
check.md |
the fix for each figure check finding, and the cg-allow form |
๐ Checking a figure¶
python -m chitragupta.figure check figures/<name>.tex compiles the
figure and reports every rule it breaks, one line each, by rule id. For
each objective finding the skill either changes the figure or records
why the break is deliberate with a % cg-allow: line in the figure
file. It reads the advisory size and wording reports but does not act
on them. The command exits 0 whatever it finds, because it is an aid,
not a gate; exit 2 means it checked nothing.
figure-checks/README.md explains how to read
the report, every rule with a faulty and a fixed example, the
cg-allow form, and how review figure relates to figure check.
๐ฑ A worked example¶
Step 4 of a potted-plant tutorial wires a simulated pot to a digital twin that predicts when the soil will dry and waters it. The request:
1 2 | |
The cycle closing is the whole point, so the layout is a control
loop, and the drawing starts from assets/tikz/control-loop.tex.
Two zone cards separate the physical side from the twin, and the one
edge that crosses back (the twin watering the pot) is drawn dashed as
the loop's return:

The figure's own body, below the house style block the scaffold carries:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | |
and its ASCII twin, which is all a reader of the md, html or docx
output sees:
1 2 3 4 5 6 7 8 9 10 11 12 | |
Each zone holds one column, so every edge is level or upright and meets
the middle of a side, and no edge passes a zone title. With the house
block above it and the twin beside it, figure check reports no
findings for this figure.
figure check passing is not the last word. At 30mm boxes the same
figure also checks clean, but figure look shows "moisture"
hyphenated inside its box on the render's page. Widening every box to
40mm fixed it. Step 8 exists for defects like that one, which only
show on the rendered page.
๐ Thesis fragments¶
A thesis chapter is a .tex fragment that you \input into your own
thesis, so two things are yours to act on:
- TikZ libraries. When the render prints a
[tikz-libraries]line, add the\usetikzlibrary{...}it names to your thesis preamble, beside\usepackage{tikz}. Keep the figure's own\usetikzlibraryline and add nothing else about loading, such as flag-clearing or a hook save and restore (TIKZ-STYLE.md says why). - Unicode. When it prints a
[unicode]line, copychitragupta-unicode.stynext to your thesis and load it.
A third line, [floats], is a choice rather than a fix. It copies
chitragupta-floats.tex beside the fragment: \input it in your thesis
preamble to get the float placement the pdf preview used, which keeps a
figure that fits on a text page out of a page of its own, or leave it
out to keep your template's.
The fragment never writes \renewcommand{\thefigure}: your thesis's
own counter numbers the figure. WRITE-A-THESIS-CHAPTER.md
covers the rest of putting a fragment into a thesis.
๐ซ What it never does¶
- Never puts a citekey in a figure file. Attribution goes in the prose beside the figure, where the gate can see the key (CLAUDE.md's one rule).
- Never reproduces a source figure, in either notation.
- Never scales a figure to fit. No
\resizebox, noscale=. A figure that does not fit gets a different layout. - Never gates.
figure checkandreview figureonly report.python -m chitragupta.draft gateis the only gate.figure sync --checkexits 1 on a stale block, which is what the pre-commit hook runs; it does not block a draft. - Never presents a draft. It returns to its caller.
๐งฑ Why the genre skills keep a short figure step¶
Skills are picked by their trigger descriptions, not called by name, so
a step that says "now use figure-drawer" depends on the model actually
loading it, in Claude Code, Codex and OpenCode alike. Each genre's
figure step therefore keeps whatever must hold even if that handoff is
skipped:
- its threshold for drawing at all;
- its output shape (the marker, or the thesis's
\inputand float); - the TikZ probe and the compile check, with its inline fallback;
- an originality line;
- no citekey inside either figure file.
Everything else lives once, in figure-drawer.
tests/test_skill_figure_step.py pins each stub and fails if a rule
that moved comes back into a genre skill.
๐ฉน When something goes wrong¶
| Symptom | Likely cause | What to do |
|---|---|---|
| The figure came back as ASCII inline, with no marker | kpsewhich tikz.sty found no TikZ on this host |
install TeX Live's texlive-pictures, then ask for the figure again |
| The whole PDF render fails | a figure file does not compile | ask to fix that figure; figure check reports does-not-compile with TeX's first error |
figure check exits 2 |
no lualatex or tikz.sty on this host, or a usage error |
install them; it checked nothing, so read nothing into the silence |
A label hyphenates or an arrow crosses a title in the PDF, though figure check is clean |
the PDF sets labels on the draft's own page | widen the boxes or move the edge, and check with figure look --draft |
| Labels look small in the PDF | the draft wraps the figure in \resizebox |
remove the wrapper and ask for a re-layout (TIKZ-STYLE.md) |
figure check reports nothing-measurable for a busy figure |
its nodes have no names, so nothing was measured | name every node |
| A render warns that the figure's style block is stale | the block predates the installed one | python -m chitragupta.figure sync <file> |
Your thesis build fails on of in a node position |
the TikZ library is not loaded in your preamble | add the [tikz-libraries] line's libraries to it |
| A survey asked for a figure and got none | the survey's threshold: the comparison table usually carries that structure | ask directly if you still want one |