A marimo notebook is an ordinary Python module that marimo writes and reads back. There is no separate specification.
Sources: marimo’s documentation on the
file format
(Python and Markdown forms) and on
sandboxes
(inline script metadata); the App API
page; and marimo’s source code on GitHub, marimo/_ast/codegen.py (the
order of the file’s parts and unparsable cells), marimo/_ast/app_config.py
and marimo/_config/types.py (App options and their values) and
marimo/_ast/cell.py (cell options).
Parts of the file, in order
| Part | Form | Meaning |
|---|---|---|
| Script metadata (optional) | # /// script … # /// | A PEP 723 comment block at the top with requires-python and dependencies (and tool tables such as [tool.uv.sources]), from which marimo builds the notebook’s isolated environment. Any header comments are kept above import marimo. |
| Import | import marimo | Written first after any header comments. |
| Version | __generated_with = "0.x.y" | The version of marimo that wrote the file. |
| App | app = marimo.App(…) | The notebook object and its options; see App options. |
| Setup (optional) | with app.setup: block (app.setup(hide_code=True) when hidden) | Imports and constants that reusable functions and classes may use. |
| Cells | functions decorated @app.cell | One per cell; see cells. |
| Reusable definitions | @app.function, @app.class_definition | A function or class written at top level, so other modules can import it. It may use only the setup block and other such definitions. |
| Entry point | if __name__ == "__main__": app.run() | Runs the app when the file is executed. |
Cells
Each cell is a function. Its parameters are the variables it reads from other
cells, and its return lists the variables it defines; marimo maintains
both itself. The last expression in the body is the cell’s visible output. Cells may
be named; the documentation’s examples use names such as def config():.
Type annotations on variables are copied into the cells that use them.
| Decorator option | Type, default | Meaning (source comments) |
|---|---|---|
column | integer or none, none | Column of the multi-column layout the cell is in. |
disabled | boolean, False | The cell and its descendants cannot run, but stay in the graph. |
hide_code | boolean, False | The cell is hidden from the editor. |
expand_output | boolean, False | The cell’s output is shown in full rather than clamped to a fixed height. |
Code that marimo cannot parse is written as
app._unparsable_cell(r"""…""", …) with the cell’s options and name as
keyword arguments (a normal escaped string when the code itself contains
""").
App options
The API page documents only App(**kwargs). marimo’s
_AppConfig class accepts these keys, logs a warning for any other and
writes only those that differ from the default. Their effects are not documented on
the pages read; only names, types and values are given here.
| Option | Type and values | Default |
|---|---|---|
width | "normal", "compact", "medium", "full", "columns" | "compact" |
app_title | string | none |
layout_file | string (path) | none |
css_file | string (path) | none |
html_head_file | string (path) | none |
auto_download | list of "html", "markdown", "ipynb" | empty |
sql_output | "polars", "lazy-polars", "pandas", "native", "auto" | "auto" |
Markdown variant
marimo can also keep a notebook as a .md file. Metadata such as
title, marimo-version and description goes in
YAML front matter; other keys are kept but ignored. Code cells are fenced blocks
whose braces contain marimo: python {marimo},
{marimo} or {.marimo .python}; marimo itself writes the
Pandoc-compatible python {.marimo}. Everything else is Markdown text.
This variant has fewer features: reactive tests do not work, and it cannot be
imported or run as a script.