Builtin interactive matplotlib
mo.mpl.interactive() has been rewritten to use marimo's built-in communication channel instead of a separate server and WebSocket proxy. This means interactive matplotlib plots now work with no background threads or separate server process needed.
Download notebooks as ipynb
You can now export your marimo notebook as a Jupyter .ipynb file directly from the editor's download menu. Cells are exported in visual order with their captured outputs included.
🚨 Breaking changes
- Altair charts no longer stretch to full container width by default (#8696). Previously, marimo set
width: "container"on all Altair charts, which distorted aspect ratios, made charts look different from the Altair docs. Charts now render at Altair's native default size. If you want a chart to fill the container width, setwidth="container"explicitly in your chart spec.
✨ Enhancements
- Accept list args in ctx.install_packages (#8703)
- Add different auth options for Snowflake in the UI (#8661)
- Add read file and download snippets for storage inspector (#8640)
- Ruff config discovery for notebook cell formatting (#8609)
- Move matplotlib interactive to use marimo comm instead of over WS (#8612)
- Refine type inference for cache decorators (#8629)
- Improve command palette search with additional keywords (#8600)
- Download notebooks as ipynb through UI (#8582)
- Standardize file explorer icons, colors, spinner (#8571)
- Add banner about GitHub free tier models (#8575)
- Wait for buffered stdout/stderr before reading MCP execution results (#8577)
- Format CellSelectionStats (proper aggregation, 3 decimal places) (#8564)
- Storage inspector fixes and code gen update (#8566)
- Add the ability to control the cache (#8311)
- Add reactive histogram selection support (#8489)
🐛 Bug fixes
marimo export ipynbto support command-line arguments (#8709)- Tag install location on ModuleNotFound to distinguish installation on server vs kernel (#8619)
- Fix copy to clipboard on Safari (#8587)
- Debounce clearing of console outputs to prevent flickering (#8621)
- Use explicit multiprocessing
getcontext("spawn")(#8705) - Fix loguru messages not being printed (#8697)
- Convert decimals to float64 for filtering in tables (#8706)
- Catch generic exception when export to PDF (#8704)
- Use request path to scope code-mode runtime behavior (#8702)
- Add global previewed tables state (#8630)
- Re-render mutable Html children in vstack/hstack on flush (#8626)
- Fix Plotly selections returning points outside the selected range (#8685)
- Ignore sql_refs for top level determination (#8673)
- Send absolute path to frontend for file_browser (#8668)
- Handle rust panic errors when getting config for obstore (#8658)
- Don't search winpython in scanner for workspace files (#8633)
- Correctly handle IPv6 (#8650)
- Relative CSS paths (#8654)
- Clamp the height and add overflow for storage inspector error (#8647)
- Handle matplotlib boxplot/violinplot dict outputs (#8540)
- Preserve
TypeIs/TypeGuardnarrowing through@app.function,@mo.cache, and@mo.lru_cache(#8598) - Truncate HTML output of run stale cells tool (#8578)
- Do not prompt for overwrite when exporting WASM to an empty directory (#8591)
- Fix keyboard shortcuts normalization (#8576)
- Only display "Jump to page" when >100 pages (#8563)
- Prevent
NameErrorinmarimo runwhen passingmo.md()between cells (#8692) - Fix vim macros duplicating inserted characters (#8470)
- Forward cell names and configs on external file reload (#8433)
- Prevent getnameinfo hang on Windows for link-local IPv6 (3b8b9bd)
- Initialize cell_ids on notebook creation (#8310)
- Remove SVG
<title>tooltip from marimo icons (#8595) - Idempotent ipynb round-trip (#7939)
📚 Documentation
- Enable storage inspector by default (#8666)
- Add database UI - add text to help users (#8675)
- Add variable type information to 'get_cell_dependency_graph' (#8663)
- Sync Traditional Chinese README with latest updates (#8638)
- Link to docs in language server page (#8614)
- GitHub molab (#8604)
- Iframe allow forms for ui.form (#8602)
- Export, publishing, deploying refactor (#8581)
- Simplify agents.md, add general approach to PRs (#8583)
- Document session files for molab GitHub previews (#8573)
- Add section on opencode agent (#8567)
- Molab (#8554)
🔬 Preview features
- Add internal code mode module for programmatic notebook control (#8670)
- Add server registry and SSE execute endpoint (#8592)
📝 Other changes
- Update Dockerfile with metadata labels, environment variables, and user permissions (#8637)
- Remove GPT 5.4 pro (#8660)
- Add newest GPT model, remove GPT 5.2 (#8586)
- Remove old AI models, add latest ones (#8129)
- Replace hatch env layer with native uv commands (#8510)
- Prevent make dev from rewriting api.yaml version on event (#8334)
- Fix broken tests on main (#8653)
- Fix breaking tests for pandas support (#8593)
- More hatch -> uv failures (#8655)
Contributors
Thanks to all our community and contributors who made this release possible: @akshayka, @axsseldz, @chentoast, @daizutabi, @dmadisetti, @ffmiruz, @koaning, @Light2Dark, @manzt, @MarcoGorelli, @mchav, @mscolnick, @peter-gy, @PranavGopinath, @thliang01, @tigretigre, @tsubasakong, @VishakBaddur
And especially to our new contributors:
- @mchav made their first contribution in #8591
- @PranavGopinath made their first contribution in #8578
- @tsubasakong made their first contribution in #8609
- @VishakBaddur made their first contribution in #8626
- @AshtonCoates made their first contribution in #8470
- @chentoast made their first contribution in #8587
Full Changelog: 0.20.4...0.21.0
