Getting Started¶
Installation¶
As a stand-alone tool¶
The marimo-md-export command is then available globally on your system.
To run without installing:
As a project dependency¶
Install and add to your pyproject.toml:
Usage¶
Write your notebook¶
This tool requires marimo notebooks in .py format (not .md).1
Cell outputs are rendered in the export by default.
If a cell produces output you don't want in the export, add # @suppress anywhere inside the cell.
The cell's code block still appears in the markdown — only its rendered output is omitted.
There is currently no way to hide a cell's code.
If you mark a cell with @app.cell(hide_code=True) (as the marimo editor does when you hide a cell's code), its code block is omitted from the export, while its output is still rendered (unless you use # @suppress).
Run the export¶
marimo-md-export is a CLI tool (built with Typer).
There are two required path-like arguments: the .py marimo notebook and the output path.
Run marimo-md-export --help to see all available options.
Options
| Flag | Description |
|---|---|
--html-output PATH |
If provided, also save the intermediate HTML export to this path |
--figures-dir PATH |
Write figures as image files into this directory and link to them from the markdown, instead of embedding them as base64 data URIs. Relative paths are resolved against the output file's directory. |
--marimo-args TEXT |
Extra arguments forwarded to marimo export (space-separated) |
--sandbox/--no-sandbox |
Run marimo export in an isolated uv environment |
--timeout SECONDS |
Maximum seconds to wait for each marimo export subprocess (default: no timeout) |
--overflow |
Default overflow behavior for long output lines: wrap (default) or scroll. Can be overridden per cell with # @scroll or # @wrap. |
-v, --verbose |
Print progress to stdout |
-h, --help |
Show help and exit |
Integrating with documentation sites¶
marimo-md-export is designed to produce markdown pages for static site generators like mkdocs or zensical.
Both work identically for this purpose.
My suggestion is to add an extra build step that converts your notebook(s) before building the site (and to gitignore the outputs).
For example, this project uses the following just command to build the docs:
This runs marimo-md-export to produce a self-contained markdown page (with cell
outputs injected), then builds the site.
Writing figures to files¶
By default, figures are embedded directly in the markdown as base64 data URIs, which keeps the page self-contained but makes it large.
Pass --figures-dir to write them out as image files instead:
This writes docs/figures/example-1.png, docs/figures/example-2.svg, and so on, and references them from the markdown with standard image syntax:
Files are named after the output file's stem, so several notebooks can safely share one figures directory.
Each image keeps its native format — matplotlib plots become .png, graphviz graphs become .svg, and so on; nothing is converted.
The path is interpreted relative to the directory containing the output file, so the links in the markdown are relative too and survive being served from any URL prefix. Because they are ordinary markdown image links, your site generator resolves them exactly as it would any other relative link in your docs.
Give an absolute path if you'd rather write elsewhere; the links will then be absolute as well.
This project's own docs are built this way — see the docs recipe in the justfile:
Gotchas¶
Existing files are overwritten by default.
marimo-md-export invokes marimo export as a subprocess.
To ensure fully non-interactive operation, --force is always passed to marimo export, suppressing file-overwrite prompts.
Long output lines are a bit awkward.
By default, long output lines wrap within the container using CSS white-space: pre-wrap; overflow-wrap: break-word;.
This keeps everything visible without scrolling but can break custom __str__ formatting.
Use --overflow scroll to switch to horizontal scrolling globally.
This preserves the original formatting exactly but requires users to scroll horizontally for long lines.
You can also override the global default on a per-cell basis by adding # @scroll or # @wrap anywhere inside the cell (similar to # @suppress).
The last marker in a cell wins if both are present.
Stale figure files are not cleaned up.
With --figures-dir, re-running the export overwrites <stem>-1, <stem>-2, ... in place, but nothing is deleted.
If a notebook loses a figure, the leftover file from the previous run stays behind.
Point --figures-dir at a directory used for nothing else (and gitignore it), so you can safely delete it before a rebuild.
-
Using
.pyformat as the notebook source means you can take advantage of Python tooling (linters, type checkers etc.) andpython notebook.pyjust works. ↩