English for Marimo Developers
Vocabulary for developers building reactive Python notebooks with marimo — cell dependencies, reactivity, and app export — for teams discussing reproducible notebooks in English.
marimo is a Python notebook that stores itself as a plain .py file and automatically re-runs any cell affected by a change — no hidden execution order, no stale state left over from a cell you deleted three edits ago. Because it fixes a well-known Jupyter pain point (execution order vs. visual order), review conversations often center on that specific distinction. Here’s the English you need.
Reactivity and Dependency Graph
Reactive execution — marimo’s core behavior: when a variable changes in one cell, every other cell that depends on it automatically re-runs, in dependency order, not visual top-to-bottom order.
“You don’t need to manually re-run the plotting cell — reactive execution already reran it the moment you changed the filter above.”
Dependency graph — the internal structure marimo builds by statically analyzing which variables each cell reads and writes, determining which cells must re-run when a given cell changes.
“marimo caught that unused import because it’s tracked in the dependency graph — Jupyter would have just let it silently sit there.”
Hidden state — the classic Jupyter problem where a notebook’s visible cell order doesn’t match its actual execution history, leaving stale variables from deleted or reordered cells.
“That bug only existed because of hidden state — a variable from a cell you’d already deleted was still lingering in the kernel. marimo’s reactive model makes that class of bug structurally impossible.”
Cells and Variables
Cell — marimo’s unit of code, similar to a Jupyter cell, but with the constraint that a variable can only be defined in one cell across the whole notebook, enforced to keep the dependency graph unambiguous.
“You can’t redefine
dfin a second cell like you would in Jupyter — marimo needs each variable’s definition to be traceable to exactly one place.”
UI element — an interactive widget (mo.ui.slider, mo.ui.dropdown) that, like a normal variable, triggers reactive re-runs of dependent cells whenever its value changes.
“Bind the slider’s value to a variable and let reactive execution handle the redraw — you don’t need a manual callback like you would in a plain script.”
Pure functions between cells — the practice of keeping cross-cell dependencies limited to simple variable reads rather than complex mutable objects, so the dependency graph stays predictable.
“Don’t mutate that dataframe in place across three different cells — split it into pure transformations so the dependency graph actually reflects what’s happening.”
Notebook as Code and Export
Notebook-as-.py-file — marimo’s decision to store notebooks as plain, git-diffable Python files instead of JSON, so version control and code review work the same as for any other Python module.
“We can finally do a real code review on this notebook — the diff is readable Python, not a JSON blob of cell outputs and metadata.”
App export — converting a marimo notebook directly into a standalone, deployable web app (via marimo run) without rewriting it in a separate framework like Streamlit.
“We don’t need to rebuild this as a separate Streamlit app — marimo can export the same notebook directly as a shareable app.”
Common Mistakes
- Saying “the notebook re-ran everything” as a complaint, without recognizing that’s reactive execution correctly propagating a change — often the exact behavior that prevents hidden-state bugs.
- Trying to redefine the same variable name in two different cells out of Jupyter habit, then being confused by marimo’s error instead of restructuring the cells.
- Treating the dependency graph as something the developer must manually manage, when it’s inferred automatically from static analysis of variable reads and writes.
Practice Exercise
- Explain, in two sentences, how marimo’s reactive execution prevents the “hidden state” bug common in traditional Jupyter notebooks.
- Write a short PR description for splitting an in-place dataframe mutation across cells into pure, dependency-graph-friendly transformations.
- Draft a code review comment explaining why a notebook stored as
.pyis easier to review than one stored as.ipynb.
Related Resources
Navigating Nuance: Addressing Feedback & Collaboration
Many non-native speakers find the subtleties of professional English incredibly challenging. It’s not just about knowing the individual words; it’s about understanding how those words are used within a specific context, particularly when discussing technical work like Marimo notebooks. Code reviews, Slack conversations, and pull request descriptions are rife with implicit expectations and preferred phrasing that can be difficult to decipher without experience. One common area of confusion revolves around giving and receiving feedback – it’s rarely just about pointing out an error; it’s about suggesting a solution or guiding the developer towards understanding the reasoning behind the desired change.
Consider this scenario: you’re reviewing a PR that implements a new data transformation within a Marimo notebook cell. A reviewer might leave a comment like, “This cell could benefit from clearer dependency tracking. Consider adding a depends_on relationship to the data source.” Simply stating “needs better dependency tracking” isn’t helpful. It lacks context and doesn’t explain why it matters. A more constructive response would be, “This is great work! However, currently, Marimo can’t fully optimize this transformation because it doesn’t understand how this cell depends on the data source. Adding depends_on('data_source') will allow Marimo to better manage the reactivity and potentially improve performance by caching intermediate results.” Notice the added explanation – linking the technical detail (dependency tracking) back to a tangible benefit (performance optimization).
Similarly, Slack conversations often involve complex discussions about notebook reproducibility. Developers might use phrases like “ensure consistent behavior across environments” or “validate the output against the specification.” These aren’t just buzzwords; they represent a fundamental concern: that changes made during development don’t inadvertently break existing functionality or introduce unexpected side effects. It’s crucial to be precise when discussing these issues, avoiding vague statements and focusing on verifiable outcomes.
Finally, crafting effective pull request descriptions is vital for communicating your intentions clearly. Instead of just saying “Fixed bug,” explain what the bug was, how you fixed it, and why the fix matters in the broader context of the notebook’s functionality. This proactive communication reduces ambiguity and streamlines the review process.
Here’s a simple example of how marimo can be used to demonstrate dependency management:
marimo cell inspect --cell-id my_transformation_cell
This command, when executed within Marimo’s CLI, would reveal the dependencies declared for the cell identified by my_transformation_cell. The output would show a list of cells that this cell depends on, allowing you to immediately understand the impact of changes. This directly relates to the “dependency tracking” discussed earlier and highlights how Marimo facilitates understanding complex notebook relationships.