Agent skill

Figure Style

by xuzhougeng in xuzhougeng/wisp-science

Correctness and legibility checklist for publication figures, plus a matplotlib sidecar.

Apache-2.0Auto-check passedData & Analytics

Install Figure Style

skills CLI
$ npx skills add xuzhougeng/wisp-science --skill figure-style -a claude-code

Project install by default; add -g for ~/.claude/skills/.

GitHub CLI
$ gh skill install xuzhougeng/wisp-science figure-style --agent claude-code

Project scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).

Manual copy
$ git clone --depth 1 https://github.com/xuzhougeng/wisp-science.git skills-src && mkdir -p .claude/skills && cp -r skills-src/skills/figure-style .claude/skills/figure-style && rm -rf skills-src

Use ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.

Claude Code skills documentation · loads skills from .claude/skills/

Facts

Skill name
figure-style
GitHub stars
1k
Token cost
~3.5k tokens
SKILL.md length
1,861 words
Files
2
Skills in repo
25
Repo updated
First seen
Licence
Apache-2.0

At a glance

Correctness and legibility checklist for publication figures, plus a matplotlib sidecar.

  • Tasks that involve Data visualization
  • SKILL.md covers Tell the truth about the data, Say less, and say it in the…, Axes and scales and Colour, plus 5 more sections
  • Runs Python scripts from its folder

What it does

Figure Style is an agent skill from xuzhougeng/wisp-science. Correctness and legibility checklist for publication figures, plus a matplotlib sidecar. Load before plotting anything and call applyfigurestyle() (role-mapped font ladder, outward ticks, frameless legends, 300-dpi saves, CJK-safe fonts). Covers data fidelity, label budgets, axis/colour/type rules, chart choice by data shape, composition, and a mandatory render-then-inspect QA pass (bbox collisions + per-panel visual crops). Helpers: focalpalette, barwithpoints, stripwithmedian, endoflinelabels, panelletter…

Its SKILL.md is about 3.5k tokens, which your agent loads only when the skill is triggered. The skill folder holds 1 other file (for example `runtime.py`).

It sits in Data & Analytics, covering Data visualization. It works with Matplotlib. The repository describes itself as: Open-source, local-first desktop AI research workbench for scientific computing with Python/R, MCP bioinformatics tools, SSH/WSL/GPU runtimes, and OpenAI/Anthropic models. The licence is Apache-2.0.

When your agent uses it

  • Tasks that involve Data visualization

Example prompts

  • “/figure-style”

Requirements

  • Python 3

What it can do on your machine

Read from SKILL.md and the folder at commit 2ba143b. It shows what the files ask for, not the result of running them.

  • Tool permissions

    Pre-approves nothing: there is no allowed-tools line, so your agent's usual permission prompts apply.

    From allowed-tools in the SKILL.md frontmatter.

  • Runs code

    Ships script files (Python), which the agent can run.

    From the folder's file list and the shell code blocks in SKILL.md.

  • Network

    No URLs in SKILL.md.

    From URLs in SKILL.md, links to its own repository left out.

  • Credentials

    Names no API keys, tokens, secrets or passwords.

    From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.

Context cost

Figure Style loads about 3.5k tokens when it runs. Until then it costs about 186 tokens; SKILL.md has 1,861 words of instructions outside code blocks.

Always · name and description, kept in context so the agent knows when to use it
~186
When it runs · the whole SKILL.md, loaded when a task matches
~3.5k

Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.

Safety

Auto-check passed

The automated check found no risky patterns in SKILL.md.

Automated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); files beside SKILL.md are not scanned.

SKILL.md

The full file from xuzhougeng/wisp-science at commit 2ba143b, republished under its Apache-2.0 licence (© xuzhougeng). 1,861 words, ~3,507 tokens.

Download SKILL.mdSave it as .claude/skills/figure-style/SKILL.md (or your agent's skills folder). This skill also uses 1 other file; get the full folder from GitHub.
name
figure-style
description
Correctness and legibility checklist for publication figures, plus a matplotlib sidecar. Load before plotting anything and call `apply_figure_style()` (role-mapped font ladder, outward ticks, frameless legends, 300-dpi saves, CJK-safe fonts). Covers data fidelity, label budgets, axis/colour/type rules, chart choice by data shape, composition, and a mandatory render-then-inspect QA pass (bbox collisions + per-panel visual crops). Helpers: focal_palette, bar_with_points, strip_with_median, end_of_line_labels, panel_letter, set_frame, panel_crops, save_panel_crops (QA crops go to .cache/, never into the output figures directory). Multi-panel assembly lives in figure-composer; whole-paper figure ordering in paper-narrative.
license
Apache-2.0

Figure correctness checklist

This skill makes one plot trustworthy and readable. It deliberately has no house aesthetic — frame, font family, and sizes are all parameters of apply_figure_style(), which must run before the first plotting call. Multi-panel assembly is figure-composer's job; deciding what each figure in a paper should argue is paper-narrative's.

Loading the Python helpers only defines them; it does not select a matplotlib backend or apply a style. Call apply_figure_style(...) explicitly for plotting. The optional figure_style_self_check() applies the defaults and checks font wiring when called; it is not a load-time check.

Two tiers of rule live below. Hard rules — everything under Tell the truth, Never do, and Prove the render, plus any rule stating a perceptual or factual invariant (semantic-zero centring, colour-vision safety, leader-line anchoring) — apply to every plot with no override. Everything else is a default: deviate when you have a deliberate reason, not by accident.

Tell the truth about the data

  • Excluded means excluded. A row the source data marks excluded either disappears from the plot or appears as a clearly distinct open/hatched marker named in the key — and it never contaminates a summary statistic drawn next to included rows.
  • Peers must be comparable. Arms measured under different N, budget, initialisation, or protocol don't sit side by side as if equivalent. Facet them apart or mark the label, and state the difference once in the caption.
  • The figure can't contradict itself. Before saving, trace every categorical label, threshold, and title back to the rule that defines it and check each plotted row satisfies it. A row that contradicts its label means the figure is wrong.
  • A sentence-title is a claim — test it. Check the claim against every category on the axis. One counterexample means qualifying ("on 3 of 4 pairs") or demoting the title to a description.
  • State n and what's held fixed. Any summary mark comes with n and the unit of replication; any small-multiple that fixes a variable names the fixed value — in-panel, or in the caption when the label budget is tight.
  • Context structure comes from references. A tree, ordering, or topology drawn as background (scale bar, category strip) uses an established reference. Infer it from the plotted data only when the structure is itself the finding.
  • One claim, one number. Each quantitative claim (accuracy, runtime, count) has a single canonical value reused identically in every panel, caption, and the abstract — with a definition of what it measures.

Say less, and say it in the right place

The panel shows the pattern; the caption carries the context. Design for a general scientific reader, not for yourself.

  • Floor. Every visually distinct mark must be identifiable from the figure alone. Deleting a label may only ever leave the reader asking "why is that there?" — never "what is that?". Comparators are named for what they are ("no joint training", "prior method"), not a role word ("baseline"). Gloss any term a general scientist can't parse.
  • Ceiling. Per panel: title, axis labels, ticks, series identity (labelled once per row of small multiples), and at most 2–3 narrative annotations. More than ~6 strings beyond axes/ticks means over budget. Identity labels are floor, not budget.
  • Caption material: n=, held-fixed values, abbreviation expansions, exclusion rationale, non-comparability footnotes, methods caveats.
  • Titles state takeaways. "Robust to gene dropout" works; "Fewer genes" doesn't — read it aloud and if a listener would ask "fewer genes what?", rewrite. A row of small multiples varying one thing gets one row header, not per-panel titles.
  • Numbers on marks: headline only. Print the one value a reader would quote; the axis serves the rest.
  • Tie-break: delete and re-read. If the message survives without the label, the label stays gone.

Axes and scales

  • Limits clear the data by at least a marker radius on every side — ax.margins(0.04) — and no mark or text touches a spine.
  • Data using under 40% of an axis calls for a break or a data-floor start with an explicit non-zero tick. Nothing may be drawn inside a break gap: the gap has no coordinates.
  • Log ticks read as 10²/1k/10k/100k, never raw exponents. Filled bars on a log value axis are banned outright — bar length would encode the ratio to an arbitrary floor. Points with a median tick replace them.
  • In a row/column of small multiples, tick labels appear once (leftmost or bottommost); interior panels keep tick marks only. Panels sharing y and differing only in x abut (wspace≤0.06) under one row header.
  • A panel's data envelope fills ≥75% of its rectangle; dead bands mean reshaping the grid, not padding the panel.
  • When better-is-up/down isn't obvious from the axis label, put an upright "higher = better" cue in the margin — once per row, never per panel, never caption-only, and never rotated with rotated text (goodness_arrow).
  • The full-width figure must fit the venue's double-column width at 300 dpi, and adding a schematic or label never squeezes the data panels narrower.

Colour

  • A colour is a binding. Once an entity gets a colour, every mark for that entity — line, fill, marker, text, heatmap row — reuses it exactly. Colour is the cross-reference; nobody should read a legend twice.
  • Few hues, one dominant. Use the minimum hue count. A focal series is saturated and heavy; comparators desaturate and thin (focal_palette). The focal hue may not collide with any categorical palette in the same figure, and the focal series must stay identifiable even at zero width or full overlap — outline, marker, or tinted band.
  • Nested categories: outer level chooses the hue family, inner level samples within it.
  • Continuous data: perceptually uniform sequential map; single-hue ramp for rank/size; diverging map for signed values, centred on the semantic zero (0, 1.0, median) — never the data midpoint.
  • Colour-vision safety. No red/green binary. Every binary pair survives a deuteranopia simulation. One alarm hue is reserved for error/anomaly/perturbation and never doubles as a series colour.
  • Two palettes ⇒ two legends, each adjacent to the first panel using its palette.

Type

  • Panel titles are plain-language sentences, regular weight, left-aligned; metric names live on the axis.
  • Three sizes, mapped to roles: base for titles/axis labels/series identity, one step down for legends/annotations, one more for ticks (apply_figure_style(sizes=(8,7,6))). Panel letters alone break the rule (bold, larger). A label that doesn't fit gets a layout fix or a shorter string, never a fourth size.
  • Species, genes, and variables that convention italicises are italicised; abbreviations inherit the style and expand once on first use.
  • Large numbers wear magnitude suffixes — 4.2B, 120 kb — not comma grouping.
  • On-mark values: ≤2 significant figures, unless rounding would collapse two distinct rows, in which case show the separating digit. Text on a fill needs 4.5:1 contrast or it moves outside the mark.
  • No codebase identifiers as labels: readable name first, code in parentheses or the caption.
  • Panel letters: bold, top-left, outside the axes box; case per venue (panel_letter(ax, 'a', case=...)).
Show full SKILL.md (732 more words)Show less

Match the chart to the data

  • Category × number: show the distribution. Small n → jittered strip with median tick (strip_with_median); large n → box/violin; mean-as- message → bar with raw points or interval (bar_with_points), not both. errorbar='ci95' is the t-interval, valid at small n. A missing category is marked n.d./—/hatched ghost — an empty slot reads as zero — and a true zero gets a visible stub.
  • One observation per category: lollipop (dot plus thin stem to the semantic zero), value beside the dot.
  • Series over a continuum: mean line with markers, raw runs as thin translucent traces behind it, series named by text at the line's right end (end_of_line_labels) rather than a legend box. Per-bin summary glyphs are unmistakable-for-raw, identical across series, and drawn under the raw points.
  • Overlapping distributions: stacked panels with shared x, or a ridgeline; overlay only when separation is obvious.
  • Matrices: under ~200 cells, print every value; state the threshold in the colourbar label.
  • Embedding scatters (UMAP/t-SNE/PCA): no ticks or tick labels, a corner arrow pair for axes, clusters labelled by thin leaders into whitespace.
  • Prediction vs. observation: adjacent tracks, identical x and colours, alignment carries the comparison; target regions as translucent spans in the legend.
  • Insets connect visibly to their source region: box plus connectors, or a wedge.
  • Named-point scatters direct-label at least max, min, and every flagged point via thin leaders — and after rendering, confirm each leader ends within a marker radius of its row.

Composition

  • Show what is being measured before the result — plain title, labelled schematic, or panel order — and any schematic reuses the exact words and glyphs of the data panels.
  • A multi-panel figure exists to make one sentence true. Panels that neither state, support, nor bound that sentence move to the supplement.
  • Legends are frameless, sit in natural whitespace or become direct labels, read swatch-first left-aligned, and resolve every distinct glyph.
  • Grouped small multiples take one spanning header per group, not repeated titles.
  • Across a paper, Figure 1 renders the pitch as data (scope, not architecture); later figures carry mechanism, evidence, robustness, application. Panels are judged against the paper's pitch and move between figures when the story requires (paper-narrative runs that review).
  • Between revision rounds, a passing panel is left alone — decorating a clean panel is a regression.

Never do

Each of these is a correctness failure:

  • red vs. green as an opposing pair;
  • filled bars on a log value axis;
  • a diverging map centred on the data midpoint, or a colourbar whose ticks skip the semantic centre;
  • an axis title that repeats the tick labels;
  • direction-of-goodness explained only in the caption;
  • a "reference" line at a value that is one of the plotted points;
  • an excluded row inside a plotted summary;
  • a leader line whose nearest mark is not its target.

Prove the render

Run both checks after fig.savefig(...) and before presenting the file.

1. Collision scan. Assert no visible text box overlaps another or a spine (a tick label touching its own spine doesn't count), and every text box sits inside fig.bbox:

python
rend = fig.canvas.get_renderer()
labels = [(t, t.get_window_extent(rend)) for t in fig.findobj(mpl.text.Text)
          if t.get_text().strip() and t.get_visible()]
frames = [(s, s.get_window_extent(rend)) for ax in fig.axes
          for s in ax.spines.values() if s.get_visible()]
own_ticks = {ax: set(ax.get_xticklabels(which='both') + ax.get_yticklabels(which='both'))
             for ax in fig.axes}
hits  = [(a, b) for i, (a, ba) in enumerate(labels)
         for b, bb in labels[i+1:] if ba.overlaps(bb)]
hits += [(t, s) for t, bt in labels for s, bs in frames
         if bt.overlaps(bs) and t not in own_ticks[s.axes]]
assert not hits

Move, shorten, or stagger until the scan is clean, re-saving each time.

2. Visual pass. Geometry can't see a low-contrast label, crossing leaders, or two confusable series colours. Crop each panel to its own file and inspect every crop with Wisp's view_image tool:

python
fig.savefig("figure.png")
save_panel_crops("figure.png", panel_crops(fig))  # → .cache/figure-style/

Leave Python, then view_image each returned path asking: every glyph legible against its background? smallest element still has a stroke or stub? leaders uncrossed? any two series colours confusable? legend beside what it keys? A visual defect that passed the collision scan is still a defect.

Crops are not products. They are throwaway inspection files and never go in the figures/output directory, not even in a subfolder of it — only the figure itself is delivered. save_panel_crops keeps them in .cache/figure-style/ and wipes that directory on every call; if you crop by hand, write to the same place. Delete it once the figure passes (shutil.rmtree(".cache/figure-style", ignore_errors=True)), and never report a crop as an output.

3. R output. Prefer explicit ggsave(filename, plot = p, dpi = 300, bg = "white", ...) over the active device; for base graphics open png(..., bg = "white", res = 300), draw, and always dev.off(). Then assert the file exists and is non-empty and inspect it — a "successful" R call with a missing, zero-byte, or blank file is a failed render.


Defaults when unsure: fewer hues, direct labels over legends, raw data over summaries, and name the measurement before showing its result.

© xuzhougeng, Apache-2.0. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file

Files

SKILL.md and 1 other file in skills/figure-style of xuzhougeng/wisp-science.

  • SKILL.md
  • runtime.py

Open the folder on GitHubat commit 2ba143b

Compare with similar skills

Figure Style next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.

Figure Style compared with similar skills
SkillStarsUsed inTokensAuto-checkLicenceRepo updated
Figure Style this skillxuzhougeng/wisp-science1k—~3.5kAutomated safety check: PassApache-2.0
MatplotlibzLanqing/codex-claude-academic-skills4.7k17 repos~2.9kAutomated safety check: PassMIT
Scientific Visualizationmims-harvard/OptimusKG14719 repos~6.3kAutomated safety check: PassMIT
SeabornzLanqing/codex-claude-academic-skills4.7k15 repos~4.9kAutomated safety check: PassBSD-3-Clause
Plot From DataTrae1ounG/paper-plot-skills8721 repos~583Automated safety check: PassNone
Scientific Figure MakingChenLiu-1996/figures4papers8.3k—~557Automated safety check: PassCustom licence

Similar skills

  • Matplotlib

    zLanqing/codex-claude-academic-skills

    Low-level plotting library for full customization. An agent skill from zLanqing/codex-claude-academic-skills.

    4.7k GitHub starsUsed in 17 repos~2.9k tokens
    Data & AnalyticsAuto-check passed
  • Scientific Visualization

    mims-harvard/OptimusKG

    Create publication figures with matplotlib/seaborn/plotly. An agent skill from mims-harvard/OptimusKG.

    147 GitHub starsUsed in 19 repos~6.3k tokens
    Data & AnalyticsAuto-check passed
  • Seaborn

    zLanqing/codex-claude-academic-skills

    Statistical visualization with pandas integration. An agent skill from zLanqing/codex-claude-academic-skills.

    4.7k GitHub starsUsed in 15 repos~4.9k tokens
    Data & AnalyticsAuto-check passed
  • Plot From Data

    Trae1ounG/paper-plot-skills

    Generate publication-quality matplotlib figures by selecting a pre-built paper style and substituting user data.

    872 GitHub starsUsed in 1 repo~583 tokens
    Data & AnalyticsAuto-check passed
  • Scientific Figure Making

    ChenLiu-1996/figures4papers

    Covers publication-ready matplotlib figures for academic papers, slides, and reports—bars, trends, scatter, heatmaps, and multi-panel layouts—with this…

    8.3k GitHub stars~557 tokensUpdated yesterday
    Data & AnalyticsAuto-check passed
  • Plot From Image

    Trae1ounG/paper-plot-skills

    Reproduce any academic paper figure from an uploaded image using accumulated style experience.

    872 GitHub starsUsed in 1 repo~868 tokens
    Data & AnalyticsAuto-check passed

More from xuzhougeng/wisp-science

All 25 skills in this repo
  • Singlecell Qc

    xuzhougeng/wisp-science

    A skill your agent uses when designing, reviewing, or implementing single-cell RNA-seq QC in Python or R with a human-in-the-loop, data-driven approach.

    1k GitHub stars~1.6k tokensUpdated today
    Auto-check passed
  • Research Integrity Audit

    xuzhougeng/wisp-science

    学术审查 / research-integrity screening of a manuscript's figures and reported numbers.

    1k GitHub stars~2.6k tokensUpdated today
    Auto-check passed
  • Distill Concept Books

    xuzhougeng/wisp-science

    将概念、理论或分析方法类图书蒸馏为证据可追溯、经人工门禁审核且不暴露书名、作者、出版社等来源身份的任务型 Skill 候选。用于新建或恢复图书蒸馏、以本地 Tesseract 扫描 DOCX 全部内嵌图像或 Poppler 渲染的扫描 PDF 全页、建立 source map 与 evidence/claim/relation/capability…

    1k GitHub stars~2.3k tokensUpdated today
    Auto-check passed
  • Skill Creator

    xuzhougeng/wisp-science

    Create, update, validate, and evaluate Wisp skills. An agent skill from xuzhougeng/wisp-science.

    1k GitHub stars~1.3k tokensUpdated today
    Auto-check passed
  • Word Zotero Citations

    xuzhougeng/wisp-science

    Build, audit, authorize, recover, or finalize dynamic Zotero citations and bibliographies in Microsoft Word DOCX files with a protected-source, digest-bound workflow.

    1k GitHub stars~3.7k tokensUpdated today
    Auto-check passed
  • Compute Env Setup

    xuzhougeng/wisp-science

    Set up and validate a reproducible Python or R environment on a Wisp execution context.

    1k GitHub stars~1.1k tokensUpdated today
    Auto-check passed

Works with

Questions about Figure Style

What does Figure Style do?

Correctness and legibility checklist for publication figures, plus a matplotlib sidecar. Figure Style is an agent skill from xuzhougeng/wisp-science. Correctness and legibility checklist for publication figures, plus a matplotlib sidecar.

When should I use Figure Style?

Figure Style fits situations like: tasks that involve Data visualization.

How do I install Figure Style in Claude Code?

Run `npx skills add xuzhougeng/wisp-science --skill figure-style -a claude-code`. Or copy the skill folder (skills/figure-style in xuzhougeng/wisp-science) into .claude/skills/figure-style in your project. Claude Code loads it when a task matches its description.

How do I install Figure Style in Codex?

Run `npx skills add xuzhougeng/wisp-science --skill figure-style -a codex`. Or copy the skill folder (skills/figure-style in xuzhougeng/wisp-science) into .agents/skills/figure-style in your project. Codex loads it when a task matches its description.

Can I use Figure Style in Cursor, Gemini CLI or GitHub Copilot?

Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add xuzhougeng/wisp-science --skill figure-style -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/figure-style, .gemini/skills/figure-style, .github/skills/figure-style and .opencode/skills/figure-style in your project.

What does Figure Style need to run?

Going by SKILL.md and its folder, Figure Style needs Python for the scripts in its folder. Our summary lists: Python 3.

Does Figure Style access the network?

SKILL.md contains no URLs. Any network use would come from the scripts or tools the agent runs. This is read from the text; nothing was executed.

Is Figure Style safe to install?

Our automated static check of SKILL.md found no risky patterns, such as piping downloads into a shell, reading credential files or hidden Unicode. It is not a guarantee. Review the folder before installing.

What licence does Figure Style use?

Figure Style is published under the Apache-2.0 licence (declared in SKILL.md). It allows redistribution, so the full SKILL.md is shown on this page.

How many tokens does Figure Style use?

About 3.5k tokens (SKILL.md is roughly 14k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full.

What are the alternatives to Figure Style?

Skills that share tags, products or a category with Figure Style: Matplotlib (zLanqing/codex-claude-academic-skills, 4.7k stars), Scientific Visualization (mims-harvard/OptimusKG, 147 stars), Seaborn (zLanqing/codex-claude-academic-skills, 4.7k stars) and Plot From Data (Trae1ounG/paper-plot-skills, 872 stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.

Who maintains Figure Style?

xuzhougeng (a GitHub user) maintains it in xuzhougeng/wisp-science, which has 1,026 GitHub stars. The repository holds 25 skills in this directory. The repository was last updated on October 10, 2026.

Source: xuzhougeng/wisp-science on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.