Skip to content

Edit the figure. Keep the code.

A visual editor for matplotlib and AI-generated scientific figures. Click what you want to change, arrange the panels in millimetres, check publication requirements, and export — without losing the code behind the figure.

Or from PyPI, on any platform: pipx install "tavotto[worker]"

The Tavotto window: a tree of the elements inside the figure on the left, three panels arranged as (a)(b)(c) on a 150 × 112.5 mm page in the middle, and the properties of the selected title on the right — font, 9 pt, its text, and the source file fig1_kinetics.py.

150 × 112.5 mm

Your plot is finished. Figure 1 isn’t.

The last stretch before submission goes: change a line, re-run the script, look, change it again. Twenty times, for things you can see but not easily say — the legend three millimetres to the left, the tick labels one point smaller, panel (b) aligned to panel (a).

The other way out is to finish the PDFs by hand in a vector editor, and accept that the figure and the code that made it have parted company.

Tavotto is the third option. Open the figure, change what you can see, export. The script stays where it was, and every change can be undone.

  1. 1 change code
  2. 2 run script
  3. 3 inspect
  4. 4 change code
  5. 5 run again
  6. 6 repeat
  1. 1 click the title
  2. 2 drag the legend
  3. 3 align the panels
  4. 4 export

matplotlib draws the plot. Tavotto is the visual last mile — it does not replace your plotting code.

From plot to Figure 1

Close-up of figure editing in Tavotto: the title “Reaction kinetics” selected on the canvas, and the properties panel showing its font, size of 9 pt and the source script fig1_kinetics.py.

Edit what matplotlib already drew.

Double-click a panel and Tavotto runs your script once, keeping the matplotlib Figure in memory. From then on you are editing that figure directly: pick the title, an axis label, a tick, a curve, the legend, an arrow your script drew — from the element tree or by clicking it on the canvas — and change its size, colour, weight, dash pattern, or drag it somewhere else. The figure follows the cursor frame by frame; matplotlib runs once, when you let go.

  • Title · legend · curves
  • Axes, ticks and their formatters
  • Fonts, colours, positions
  • Arrows and annotations

Serif · 9 pt · fig1_kinetics.py

Build Figure 1 in millimetres.

Panels land on a page measured in millimetres, at the size their script drew them. Drag them, snap them to each other, align and distribute a selection, or bind panels into a row, column or grid that reflows when a size changes. Panel labels (a)(b)(c) come from one command, and annotations — text, arrows, shapes — sit on top.

  • Physical page, physical sizes
  • Snap, align, distribute, group
  • Rows, columns and grids that reflow
  • Panel labels from one command
Tavotto in layout mode: the asset library on the left with three source PDFs and their physical sizes, the composed page in the middle with one panel selected, and its position, millimetre size and scale on the right.
The preflight list in the export dialog: blocking findings about text below the profile’s 8.5 pt and 8 pt floors, warnings about a frame line width and a legend font size, suggestions, and one item marked not verifiable.

Catch publication problems before the reviewer does.

Before anything is written, Tavotto checks the figure against a publication profile. Font sizes are judged at their final physical size — a panel placed at 60% is checked against fontsize × 0.6, not against what the script asked for.

Blocking
Stops the export until you confirm in writing.
Warning
Always shown, never silently dropped.
Not verifiable
What genuinely cannot be checked — text inside an imported bitmap — and needs a human.
Suggestion
Never decides anything for you.

Checks run against a publication profile you can override per journal. Tavotto flags what can be checked — it does not promise acceptance.

Export the figure, not a screenshot of it.

PDF export embeds each original vector panel as it was drawn, so the text stays real, selectable, searchable text. PNG is rasterised from that same PDF, so the two can never disagree. The preflight findings — and anything you confirmed past — can be written into a proof report beside the exported files.

  • Vector PDF, text stays text
  • PNG rasterised from the same PDF
  • Optional proof report on the side

tavottofile/export/

  • Fig1.pdf vector · real text
  • Fig1.png 300 dpi · same pdf
  • Fig1_proof.json findings + confirmations

VECTOR PDF · 300 DPI PNG

Let AI write the first draft. Finish the figure visually.

Coding agents write good first-pass matplotlib. What is left over is visual — the legend two lines too tall, the panel that wants to be a little smaller, the label overlapping a data point. Describing that in a prompt is slower than doing it.

Workflow: a Python script — written by you, Claude or Codex — runs matplotlib, which produces a vector PDF; Tavotto handles visual editing, layout and the publication preflight; the result is a PDF or PNG. The script stays the source throughout.

Hand a figure over with one command

tavotto open figures/Fig1_kinetics.pdf

From a terminal or from an agent. It opens that figure’s library as a project and hands the figure to the app — into the window that is already open, if there is one.

Codex plugin

A skill, a local MCP server, and an embedded canvas built from the same frontend code the desktop app runs. Parts of the Codex Desktop integration are not yet verified inside a real Codex Desktop — the plugin README says which.

The script stays the source throughout.

Built for the last 5% before submission.

Publication rules are physical: column widths in millimetres, font floors in points, raster floors in dpi. Tavotto measures the finished page against them.

80 / 150 mm
Single- and double-column widths in the default profile
8.5 pt
Strict font floor — judged at final physical size, 8 pt absolute
300 dpi
Minimum for rasterised output
0.5–1.5 pt
Line-width steps the frame and curves are checked against

The rules live in one versioned profile that engine and interface both read. A journal with its own widths needs a one-line override, not a fork — and the override is recorded in the proof report.

Your figures stay on your machine.

Rendering, composition and export are local processes. Tavotto does not upload your figures, scripts, project files or data anywhere — unpublished results do not leave the building.

  • Local rendering
  • Local layout
  • Local export
  • No figure upload
  • No source upload

Exactly two requests of its own

A once-a-day check of GitHub Releases for a new version, and — only after you explicitly opt in — anonymous usage statistics whose event schema cannot represent filenames, paths, figure text or prompts. Each has its own off switch; neither covers the other.

The optional AI assistant hands a request to a Codex or Claude CLI on your machine, only when you ask it to.

Read the privacy policy

Finish the figure without rewriting it.

macOS (Apple Silicon) · Windows · PyPI for Linux and everything else

Open source under AGPL-3.0. The figures and PDFs you produce with it are entirely yours.