
Hey guys, Mr. Technology here.
If you've been writing Python for data, ML, or LLM work, you've been fighting Jupyter for a decade. You know the failure mode: run a cell, scroll back, change a variable, run another cell, and now your notebook is a haunted house of stale state. Re-run the whole thing from the top and watch your 40-minute feature pipeline rebuild itself because you tweaked a constant three cells down.
Marimo fixes this. Not by patching Jupyter. By replacing the entire model.
The fundamental thing Jupyter gets wrong is that a notebook is a sequence of cells. Marimo's insight — and it's the right one — is that a notebook is a directed acyclic graph of variables. Each cell declares the variables it reads and writes. Run a cell, and Marimo walks the graph and runs every cell that depends on the variables you just produced. Change a slider, and only the cells downstream re-execute. Delete a cell, and Marimo scrubs its variables from memory. No hidden state, no "Restart Kernel and Run All" emergency ritual.
The reactive runtime is built on a Python static-analysis pass that runs at edit time. It builds the dependency DAG by walking your AST, not by parsing notebook JSON, so it understands import statements, function calls, and reassignments the way Jupyter never has. HTTP is Starlette, the editor is Monaco with Vim keybindings, and the dataframe viewer handles million-row tables without freezing. Apache 2.0, ships roughly twice a week, latest release 0.23.12 — which dropped yesterday.
The reason Marimo has 21,600 GitHub stars and 1,150 forks is that a single .py notebook does what previously required five separate tools: Jupyter for editing, Streamlit for the deployable app, Jupytext for the .ipynb-to-.py round-trip, ipywidgets for the controls, and Papermill for parameterized batch execution. Run marimo edit notebook.py and you have a reactive notebook. Run python notebook.py and you have a reproducible script. Run marimo run notebook.py and you have an interactive web app. Run pytest notebook.py and you have a testable artifact. Run it via WASM and Pyodide and you have a shareable zero-server notebook.
The format itself is the killer feature. Marimo notebooks are pure Python — no JSON, no base64, no metadata churn. The diff in git is readable. Code review works. You can grep your notebooks. Every CI system on earth understands .py; none of them understand .ipynb without a conversion step that loses something every time.
Here's where Marimo gets interesting for the moment we're in. Marimo ships marimo pair, an integration that lets you connect an agent CLI — Claude Code, Codex, OpenCode, anything that speaks the standard stream-json protocol — directly to a running notebook. The agent sees the cell structure, the variable types, the dataframe schemas, and the current execution state. It edits cells, runs them, reads the outputs, and iterates. This is what a coding agent looks like with actual context about a data-science workflow, and it's the single best argument for the notebook-as-file format in the LLM era. Jupyter's JSON spec was designed for human hand-editing; Marimo's .py spec is designed for both humans and agents to read and write deterministically.
The editor's AI completion also uses variable types in memory as system-prompt context. When you ask it to plot the distribution of df, it knows df is a 47-column DataFrame before it suggests df.hist(). That's a meaningfully different product from Copilot in Jupyter, which guesses types from surrounding code rather than reading live kernel state.
Stanford's ICME publishes Marimo notebooks, internal teams at OpenAI ship Marimo-based eval dashboards, and the WASM build on molab.marimo.io is the default share-button for data-blog posts in research labs I follow. Small community, right one.
I'm not going to pretend Marimo is a perfect drop-in. The Jupyter ecosystem is still bigger and the format wars won't be over for years. Libraries that depend on Jupyter-specific protocol messages will take time to port. The reactive model has a sharp edge: if a cell depends on a global defined outside the notebook, Marimo refuses to track it. The community Discord is active but the Stack Overflow corpus is thin. The editor is good, not great — if you live inside JupyterLab's full IDE experience you'll feel the gap.
None of this changes the structural argument. The reactive DAG is the right execution model. Pure-Python storage is the right format. One-file-script-app-test is the right packaging. Jupyter's core idea — interleaving code, output, and prose — was always right. The execution model and the file format were always wrong. Marimo fixed both, and it didn't need a billion-dollar company to do it.
I've been moving my own research workflows over for six weeks. Every LLM eval, dataset experiment, and blog chart now live in Marimo. The .py files diff cleanly in pull requests. The reactive execution has eliminated an entire category of bugs I used to debug weekly. marimo run deploys a dashboard to a teammate in 30 seconds. I haven't opened .ipynb since.
If you write Python notebooks for a living and you haven't tried Marimo, you're paying Jupyter's tax for nothing. pip install marimo && marimo tutorial intro. Forty-five minutes from now you'll have the same reaction I did.