Skip to content

Getting Started

Installation

As a stand-alone tool

uv tool install marimo-md-export
pipx install marimo-md-export

The marimo-md-export command is then available globally on your system.

To run without installing:

uvx marimo-md-export notebook.py output.md

As a project dependency

Install and add to your pyproject.toml:

uv add marimo-md-export
pip install marimo-md-export

Then manually add marimo-md-export to 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.

marimo-md-export notebook.py output.md

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:

docs:
  marimo-md-export examples/notebook.py docs/example.md
  zensical build

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:

marimo-md-export examples/notebook.py docs/example.md --figures-dir figures

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:

![png](figures/example-1.png)

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:

docs:
  marimo-md-export examples/notebook.py docs/example.md --figures-dir figures
  zensical build

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.


  1. Using .py format as the notebook source means you can take advantage of Python tooling (linters, type checkers etc.) and python notebook.py just works.