Usage
figure-creationallowed-skills#agent-creator
Configuration
read_filewrite_fileapply_patchglobgrepsnapinspect_imagelint_svgask_user |
Instructions
Overview
.smd
References
references/figure-syntax-cheatsheet.md— figure syntax, labels, layouts, padding, and overlay block structure references/layout-cookbook.md— copy-paste multi-panel layout patterns references/overlay-patterns.md— common overlay annotation recipes and anchor patterns references/overlay-components-quick-ref.md— condensed attribute tables for all <s:*>components
references/figures.smd— complete figures documentation (763 lines) references/figure-overlay-components.smd— full overlay component reference with demos (980 lines) references/inspect-image-tool.md— full inspect_imagetool reference for coordinate inspection references/lint-svg-tool.md— full lint_svgtool reference for overlay static analysis references/snap-tool.md— full snaptool reference for visual verification
Required Inputs
.smd | ||
.smd |
Outputs
.smd | |
Core rules
Read the target document before editing so you can match existing figure, caption, and cross-reference conventions. Reuse existing panel order, caption tone, and labeling style unless the user asks to change them. Prefer anchor-based overlays when multiple annotations refer to the same feature. Prefer built-in subfigure labels over manually adding overlay badges just to show panel letters. Do not invent scale, orientation, measurements, or precise coordinates.
Steps
Determine the delivery mode. If the user wants a concept, design direction, or figure specification, provide a figure plan. If the user wants an actual figure added or revised in a document, make the .smdedit. If one missing detail materially changes the result, ask a clarifying question before authoring.
Determine figure type and overlay scope. Identify which combination the user needs: Simple image figure (one image + caption) Executable figure (code block output + caption) Multi-panel figure (subfigures with grid layout) Any of the above with overlay annotations Subfigure-local overlays, parent grid-spanning overlays, or both
Ask the user when information is missing. If any of the following are unspecified, ask before guessing: Which image files or panel order to use Exact annotation targets or positions Caption text or tone Whether overlays should be approximate or precise Image dimensions (if precise overlay coordinates matter) Scale calibration for scale bars Orientation semantics for compass indicators
Read the target document to understand existing figures, numbering, nearby references, and style conventions. Produce the requested output. For a plan, provide a figure specification covering figure type, panel order, caption approach, overlay strategy, and required missing inputs. For implementation, author the figure using the syntax patterns below.
Add overlays if requested — prefer anchor-based positioning over raw coordinates (see "Anchor-first positioning" below). Use inspect_imageto determine coordinates before writing overlay markup (see "Coordinate inspection" below). Lint overlays after authoring or editing overlay markup. Run lint_svgto catch layout collisions, dangling anchor references, out-of-bounds components, and invalid attributes before visual verification (see "Overlay linting" below). Verify cross-references and panel labeling. Confirm figure references still point to the right target. Avoid duplicating automatic subfigure labels with manual overlay badges unless the badge serves a different semantic purpose.
Optionally verify rendering with snapif a Stencila server and route are available (see "Visual verification" below).
Do not invent measurements
Do not fabricate scale bar values without known calibration. If the user has not provided a scale (e.g., "130px = 20 μm"), ask for it. Do not invent dimension line measurements from a screenshot or image unless the user explicitly provides a scale. Do not add compass/north arrows unless orientation is meaningful and known for the content. Do not claim precise coordinates for annotations unless you have reliable information about the image layout. Use inspect_imageto determine coordinates from the actual image rather than guessing.
label="[calibrate: ? μm]"
Figure syntax
figure#id[layout]{attrs}
::: figure <label> #<id> [<layout>] {pad="<padding>"}

The caption text.
:::
Labels, IDs, and cross-references
fig-fig-1fig-1a[Figure 1](#fig-1)[](#fig-1)
Stable IDs
#<id>
::: figure #specimen-1

Photograph of the first specimen.
:::
#specimen-1#id
The figure is referenced from other documents, external links, or APIs. You want to use snapto target a specific figure — a stable ID gives a reliable CSS selector (e.g. selector: "[id='specimen-1']") that won't break when figures are reordered.
Panel labels vs overlay badges
<s:badge label="A"><s:badge label="B">
Executable figures
::: figure
````plotly exec
{
"data": [{"type": "bar", "x": ["A","B","C"], "y": [4,7,2]}],
"layout": {"xaxis": {"title": {"text": "Category"}}}
}
````
A bar chart of values by category.
:::
plotlyrpythonnode
Multi-panel layouts
::: figurefigure
[row] | |
[2][3] | |
[30 70] | |
[40 g20 40] | g |
[a b | a c] | a |
[a a | b c] | a |
[a . | b c] | . |
[30 70 : a b | a c] |
ab|references/layout-cookbook.md
Overlays
svg overlay<s:*>
Always declare xmlns:s="https://stencila.io/svg"on the <svg>element when using components. The viewBoxdefines the coordinate system. Matching image dimensions is convenient (coordinates map to pixels) but any viewBox works. For browser-rendered charts (Plotly, eCharts), set explicit width/ heightin the chart config and use a matching viewBox. All components support stroke, fill, and colorattributes. The colorshorthand sets both; explicit fill/ strokeoverride it. Arrow markers automatically match the line's stroke color.
Choose the right overlay scope
Overlay inside a subfigure : use when the annotation belongs to one panel and should use that panel's local coordinate system. Overlay on the parent figure : use when the annotation spans the grid, connects panels, or needs figure-level positioning. Both : use subfigure overlays for panel-local highlights and a parent overlay for cross-panel connectors or labels.
Anchor-first positioning
xy
<!-- Define named anchors for important features -->
<s:anchor id="peak" x="250" y="80"/>
<s:anchor id="valley" x="420" y="200"/>
<!-- Reference anchors instead of repeating coordinates -->
<s:halo at="#peak" r="15" width="8"/>
<s:callout from="#peak" dx="150" dy="-60" label="Maximum" to="#peak"/>
<s:arrow from="#peak" to="#valley" curve="quad" label="Transition"/>at="#s:bottom-left"at="#s:top-right"at="#s:center"
<s:anchor>
Component quick reference
<s:arrow> | curvetiplabel | |
<s:callout> | labelshapecurve | |
<s:badge> | label | |
<s:scale-bar> | lengthlabel | |
<s:dimension> | labelside | |
<s:angle> | rlabel | |
<s:brace> | sidelabel | |
<s:bracket> | sidevariantlabel | p < 0.05 |
<s:roi-rect> | widthheightlabel | |
<s:roi-ellipse> | rxrylabel | |
<s:roi-polygon> | pointslabel | |
<s:spotlight> | ropacity | |
<s:marker> | symbolcolorlabel | circlecrossdiamondpinplussquarestartriangletriangle-down |
<s:crosshair> | sizegapringlabel | |
<s:halo> | rwidthcoloropacity | |
<s:compass> | sizevariantaxes |
references/overlay-components-quick-ref.mdreferences/figure-overlay-components.smd
Padding
{pad="..."}
::: figure {pad="0 0 56 0"}
50"30 60""10 20 30 40"
pad="T R B L"
viewBox = "0 0 (W+L+R) (H+T+B)"
Image top-left is at coordinate (L, T)
All image-space coordinates shift by +L, +T{pad="0 0 56 0"}viewBox="0 0 600 356"{pad="50 20 56 20"}viewBox="0 0 640 406"
Examples
Simple image figure
::: figure

A photograph of the study site taken in September 2024.
:::
Executable figure with anchor-based overlay
::: figure
```r exec
hist(rnorm(1000), breaks=30, col='#b0d0e8', border='#7aaccc', main='')
```
```svg overlay
<svg viewBox="0 0 600 400" xmlns:s="https://stencila.io/svg">
<s:anchor id="peak" x="335" y="100"/>
<s:halo at="#peak" r="20" width="8" color="crimson" opacity="0.4"/>
<s:callout from="#peak" dx="125" dy="-55" label="Peak near μ=0" to="#peak" curve="quad" fill="crimson"/>
</svg>
```
Distribution of 1000 random normal variates.
:::
Two-column layout with subfigure overlays
::: figure [2]
::: figure

```svg overlay
<svg viewBox="0 0 400 250" xmlns:s="https://stencila.io/svg">
<s:anchor id="region-a" x="120" y="85"/>
<s:roi-rect from="#region-a" dx="-70" dy="-45" width="140" height="90" label="Region A" stroke-style="dashed"/>
</svg>
```
Left panel.
:::
::: figure

```svg overlay
<svg viewBox="0 0 400 250" xmlns:s="https://stencila.io/svg">
<s:roi-ellipse cx="200" cy="125" rx="80" ry="50" label="Region B"/>
</svg>
```
Right panel.
:::
Two panels with individual overlay annotations.
:::
Coordinate inspection
inspect_imagesnap
Grid — overlay a labeled grid to identify approximate regions: inspect_image(file_path: "figure.png", grid: {x_divisions: 10, y_divisions: 10})Crop + grid — zoom into the region of interest for precise coordinates: inspect_image(file_path: "figure.png", crop: {x: 80, y: 100, width: 140, height: 100}, grid: {x_divisions: 5, y_divisions: 5})Probe — verify candidate coordinates before writing the overlay: inspect_image(file_path: "figure.png", probes: [{id: "tip", x: 112, y: 160}, {id: "base", x: 185, y: 118}])
{pad="..."}inspect_image
inspect_image(file_path: "figure.png", coordinate_space: {pad: {top: 0, right: 220, bottom: 0, left: 0}}, grid: {x_divisions: 10, y_divisions: 10})references/inspect-image-tool.md
Overlay linting
lint_svg
lint_svg(svg_content: "<svg viewBox=\"0 0 600 400\" xmlns:s=\"https://stencila.io/svg\">...</svg>")Collisions — overlapping labels, labels crossing lines from other components Out-of-bounds — components extending outside the viewBoxDangling references — from="#missing"pointing to undefined anchors Unused anchors — <s:anchor>defined but never referenced Missing namespace — forgetting xmlns:son the <svg>element Invalid attributes — unknown attributes or invalid enum values (e.g. curve="wobbly")
snap<!-- lint-ignore collision -->
Visual verification
snap
snap(route: "/docs/", screenshot: true, selector: "stencila-figure")#id
snap(route: "/docs/", screenshot: true, selector: "[id='specimen-1']")index.*main.*README.*docs/README.mddocs/main.mddocs/index.md"/docs/"
inspect_imagesnapinspect_imagesnap
snapsnap
references/snap-tool.md
Edge cases
Subfigure indentation : subfigure ::: figureblocks must be indented 4 spaces inside the parent. Missing indentation makes them sibling figures, not subfigures. Duplicate panel lettering : subfigures already get automatic A/B/C labels. Do not add matching overlay badges unless the user explicitly wants separate in-image labels. Executable + overlay alignment : for Plotly/eCharts/Vega-Lite, pin widthand heightin the chart config and match the overlay viewBox. Dynamic resizing can misalign overlays. Parent overlay on mobile : parent-level overlays (spanning the grid) auto-hide when the grid collapses to vertical on small screens. Subfigure overlays are unaffected. viewBox coordinate system : the viewBoxcan use any coordinate system — matching image pixel dimensions is convenient but not required. All annotation geometry must use the same coordinate space as the viewBox. Multi-value padding : quote the padvalue when using more than one number: {pad="30 60"}, not {pad=30 60}. Cross-reference IDs : auto-derived IDs use a fig-prefix with the label lowercased — fig-1, fig-2a. Use #<id>on the fence line for a stable ID that survives reordering (e.g. ::: figure #specimen-1). Namespace declaration : forgetting xmlns:s="https://stencila.io/svg"on the <svg>element causes components to be treated as unknown elements and silently ignored. Mixing components and raw SVG : components and standard SVG elements work together in the same overlay. Use components for high-level annotations and raw SVG when precise control is needed.
.stencila/skills/figure-creation/SKILL.md