technologies · difficulty ◆◆
marimo — reactive Python notebooks & apps
Write once, run as a notebook, a script, or a web app — always consistent.
Jupyter notebooks have a dirty secret: the output you're staring at may have nothing to do with the code. marimo was built to make that impossible.
$ marimoWhat it is
marimo is a reactive Python notebook that doubles as an app framework. Open a notebook and every cell that depends on a value automatically re-runs when that value changes — no manual "run all" ordering, no hidden state, no stale outputs. You build interactive dashboards and data apps by mixing Python with marimo.ui components and built-in reactive SQL.
Why it matters
Here is the problem marimo exists to kill: in a traditional notebook, cell output is a screenshot of what happened once, long ago. Edit cell one, and cell twelve still shows the old number until you remember to re-run it. marimo replaces that fragile top-to-bottom ritual with a reactive graph. Each cell is a node; changing an input recomputes exactly the dependent cells. The output on screen is, by construction, the truth.
How it fits your stack
marimo is installed in this environment at version 0.23.9 (the /home/kmail/marimo source checkout). It ships a CLI (edit, run, convert, export, tutorial, pair, new, recover), supports first-class SQL, AI assistance, and deployment as a read-only web app. You can also run a notebook as a plain Python script with arguments.
Example
$ marimo edit notebook.py Welcome to marimo!
Creating a new notebook...
Serving at http://localhost:2718
✓ App served at http://localhost:2718edit opens the notebook in the browser editor. New cells auto-connect to their inputs.
$ marimo run notebook.py Running as a read-only app...
✓ App served at http://localhost:2718
# notebook.py
import marimo
app = marimo.App(width="full")
@app.cell
def _():
import altair as alt
import marimo as mo
df = mo.sql("SELECT * FROM 'data.parquet'")
chart = alt.Chart(df).mark_bar().encode(x="month", y="sales")
mo.ui.altair_chart(chart)
return chart, df
if __name__ == "__main__":
app.run()run serves the same notebook as a read-only, interactive web app — no Python server code to write.
$ marimo convert notebook.ipynb Converted notebook.ipynb to notebook.py
✓ Wrote 5 cells to notebook.pyconvert turns a Jupyter notebook into a marimo .py file so you can migrate existing work.
$ marimo new What should the notebook be called? my_app.py
✓ Created my_app.py
# reactive example inside
import marimo as mo
slider = mo.ui.slider(0, 100, value=50)
slider # changing it re-runs dependent cells
result = mo.md(f"Slider value: **{slider.value}**")new scaffolds a fresh notebook. Notice slider is a reactive UI element — moving it re-runs dependent cells automatically.
Common flags
- edit
- create or edit a notebook (opens the browser editor)
- run
- run a notebook as a read-only web app (deployable)
- new
- create an empty notebook or scaffold from a template
- convert
- convert a Jupyter notebook or Markdown file into a marimo notebook
- export
- export a notebook to HTML, markdown, script, or app
- check
- check and format marimo files (like a linter/formatter)
- tutorial
- open a built-in tutorial notebook
- recover
- recover a notebook from a JSON session file
History
Origin
marimo was created by Akshay Agrawal and Myles Scolnick, co-founders of Marimo Inc. Akshay is a former Google Brain engineer who helped build TensorFlow, and a NeurIPS-published PhD from Stanford (vector embeddings and machine learning); Myles is a former Palantir and CloudKitchens engineer who led product and web platform teams. The first public commit landed in August 2023. The name draws on the Japanese word for "marimo" — the round green algae ball — a living, self-contained organism, which mirrors the idea of an always-consistent, self-contained notebook.
The reactive notebook idea
The core insight is borrowed from reactive UI programming (and the earlier Observable notebooks): instead of cells stored in a JSON document with hidden execution order, marimo stores cells as Python functions and derives the dependency graph at runtime. This makes output always consistent with code — a property traditional notebooks famously lack.
Growth & adoption
Since its public release, marimo has grown rapidly in the data-science and AI community, winning attention for being "git-friendly where Jupyter is not", gaining a strong open-source following, and positioning itself as an alternative to both Jupyter and dedicated dashboard frameworks like Streamlit and Dash. Version 0.23.9 (the version installed here) reflects years of continuous development with SQL, AI pair-programming, and app deployment built in.
Fun facts
Pros & cons
pros
- + Stored as pure Python (.py) files — diff cleanly in git, importable, reusable
- + Reactivity runs exactly the dependent cells, so outputs never drift out of sync
- + Same notebook runs as an editor, a script, or a read-only web app
- + Batteries included: first-class SQL cells, AI assistance, interactive dataframe viewer
- + Reactive UI elements (sliders, buttons) are first-class citizens
cons
- − Younger and less mature than the Jupyter ecosystem — some niche extensions missing
- − Reactive execution is a different mental model; takes getting used to
- − Large/expensive notebooks need lazy/stale mode configured or they recompute eagerly
- − Very long-running jobs still fit a plain script better than an app
Takeaways
- 1Install it and run `marimo tutorial intro` to feel reactivity in 60 seconds
- 2Convert an existing .ipynb with `marimo convert` to see the difference on disk
- 3Use `mo.ui.slider` to make one reactive element and watch dependent cells update live
- 4Ship a dashboard with `marimo run notebook.py` — no separate web server
- 5Keep cells side-effect-free so the dependency graph stays honest