Releases: marimo-team/marimo
0.23.2
What's Changed
🚨 Breaking changes
- Mo.ui.refresh typing and docs (#9229)
✨ Enhancements
- Code-mode .screenshot() api (#9232)
- Visible markers for leading/trailing whitespace in string cells (#9256)
- swap reveal.js instead of swiper for slides (#9166)
- change wasm link to molab link on run page (#9240)
- Bail out of type inference when completion budget expires (#9247)
- Introduce better_inspect module for enhanced dir() and help() functionality for marimo-pair (#9223)
- add molab resource to edit homepage (#9241)
- Add
ctx.packagesnamespace to code mode (#9233) - Backend-based file and directory duplication (#9142)
- Support columns in marimo-pair (#9212)
- Expand
uv_buildsupported versions in build-system (#9231) - Visually distinguish null, empty, whitespace, NaN, and Infinity in table cells (#9218)
- Restore Altair SVG output as base64-encoded Data URLs (#9104)
- Auto-save in code-mode and marimo-pair (#9191)
- add molab share action (#9207)
- LSP root and document URI integration from backend (#9143)
- Decouple Matplotlib render resolution (DPI) from display size (#9144)
🐛 Bug fixes
- Hold references to asyncio tasks (#9261)
- Use urlparse instead of regex for proxy determination (#9254)
- Preserve columns in DefaultTableManager exports (#9258)
- Drop dangling @file URLs from the session cache (#9278)
- Make
FieldTypesaMapto preserve column order (#9279) - Avoid double-mangling names inside walrus comprehension (#9276)
- Static path handling (#9281)
- Restore plain text tracebacks and fix exit codes for code mode (#9224)
- Suppress
marimo-ui-value-updateecho for user-initiated changes (#9262) - "Download as .py" in WASM run-mode exports (#9268)
- Tailwind v4 opacity fix, selection toggle, hover colors, and cleanup (#9259)
- Export menu works for plain-Python data without
pandas/polars/pyarrow(#9246) - Drop stale autosaves after newer foreground writes (#9239)
- Preserve column order in DefaultTableManager select/drop (#9235)
- Use the proactor event loop policy on Windows in edit-mode runtimes (#9194)
- Allow for data-uris in mpl-interactive and marimo-panel after a cell has run (#9196)
- Opencode marimo-pair skill discovery (#9225)
- fix variants for toast (#9230)
- Only toast cell logs in app mode (#9190)
- fix label not being passed through for mo.ui.tabs (#9187)
- Support
mo.ui.matplotlibselections from code mode (#9195) - fix cte refs for errored paths, and dml (#9188)
- Add warning log when repr_mimebundle fails (#9199)
- Use shared memory for virtual files when running with app isolation (#9181)
- Virtualize dataframe page selector to fix "No matching page" bug (#9178)
- Arrow keys lose selection in vim visual mode (#9172)
- Strip access token via redirect (#9170)
- Pair direction (#9161)
- Require auth in LSP middleware (#9160)
- With_dynamic_directory path traversal (#9162)
- Image dimensions for Altair PNG outputs (#9149)
📚 Documentation
- Update Traditional Chinese README to highlight marimo pair (#9183)
- Maintainer approval in contributing (#9153)
- Link to marimo pair in the README (#9145)
📝 Other changes
- Clear error state on disabled-transitively cells when ancestor recovers (#8784) (ba12764)
- Update dependency dompurify to v3.4.0 [security] (#9216)
- Update dependency lodash-es to v4.18.1 [security] (#9217)
- Add lazy cache blob types (arrow, npy) (#9035) (6baa22d)
- Widen
Html.batch()type to accept all UIElement subclasses (#9163) (#9176) (73ff622) - Handle list-type tooltip encoding in altair chart (#9167) (#9175) (386cba6)
- Add reactive funnel and funnelarea selection support (#9044) (b95d26d)
- Add reactive box plot selection support (#9010) (b73a370)
Contributors
Thanks to all our community and contributors who made this release possible: @akshayka, @app/renovate, @daizutabi, @dmadisetti, @kirangadhave, @Light2Dark, @manzt, @moble, @mscolnick, @nojaf, @shaun0927, @thliang01
New Contributors
- @shaun0927 made their first contribution in #9239
Full Changelog: 0.23.1...0.23.2
0.23.1
What's Changed
This release includes quality of life improvements to marimo slides, bug fixes to marimo islands that revive our quarto extension, a new lint rule, and minor security improvements.
⭐ Highlights
Slides minimap
Slide mode now has a minimap: a scrollable panel showing your cells at reduced scale, with click-to-navigate and drag-to-reorder support. It's performance-aware — cells only render in the minimap when they're in view.
Screen.Recording.2026-04-08.at.6.46.33.PM.mov
Islands revived
We've fixed many bugs with [marimo islands], a way to embed marimo outputs and/or Python code in other HTML. These fixes also make our quarto-marimo. (#9071) extension compatible with this version of marimo as well.
Security
This release includes minor security improvements, including input sanitization, path traversal prevention, open redirect blocking, and auth endpoint hardening.
- Sanitize plugin output slots (
marimo-mpl-interactive,marimo-panel) to prevent script injection (#9133) - Restrict
head_htmlinjection to run mode only (#9137) - Prevent directory traversal via symlinks in asset serving (#9134)
- Sanitize user-supplied
custom.css(#9131) - Block open redirects via protocol-relative URLs (e.g.
//evil.com) (#9112) - Restrict health endpoint exposure and add path validation for document writes (#9115)
We've also updated our security documentation with a standard operating procedure for future disclosures (#9114).
Thank You. The enthusiasm following our recent CVE disclosure is a testament to what a healthy open-source community looks like. A special thank you to @GCXWLP, @Jvr2022, @offset, @l3tchupkt, @Fushuling, @RacerZ-fighting, and @q1uf3ng for their engagement and reports during this sprint. It takes a community to keep FOSS secure. We're lucky to have this one!
All changes
- fix: sanitize marimo-mpl-interactive marimo-panel by @mscolnick in #9133
- fix: restrict head_html to run by @dmadisetti in #9137
- fix: don't follow symlinks in assets.py by @mscolnick in #9134
- fix: sanitize custom.css by @mscolnick in #9131
- fix: prevent open redirect via protocol-relative URLs by @mscolnick in #9112
- chore: reported code scanning issues by @dmadisetti in #9115
- docs: Update security docs for 0.23.0 and outline SOP by @dmadisetti in #9114
- improvement: revive islands by @mscolnick in #9071
- feat: Lint rule to detect ordering discrepancies on top level functions by @dmadisetti in #8996
- add slides minimap by @Light2Dark in #9097
- Fix
mo.ui.matplotlibrendering on browser zoom by @manzt in #9125 - fix: handle mixed-type column sorting in data table by @kirangadhave in #9102
- fix: add requires() to set_ui_element_value, set_model_value, function_call by @mscolnick in #9113
- fix: wrap plugin slot in TooltipProvider to fix tooltip regression by @mscolnick in #9126
- fix keyboard shortcuts for input elements inside shadow DOM by @Light2Dark in #9105
- don't render data-tooltips for marimo components with tooltips by @Light2Dark in #9129
- fix: minor fixes to the data-table by @kirangadhave in #9100
- fix: added exception handling to _style_cells by @kirangadhave in #9101
- additional ruff fixes by @Light2Dark in #9132
- Ruff autofixes + some manual changes by @Light2Dark in #9121
- chore: bump ruff target-version to py310 by @kirangadhave in #9118
- fix: bump ruff version in pytest_changed plugin to 0.15.9 by @kirangadhave in #9135
- tests: verify empty env vars by @mscolnick in #9130
Full Changelog: 0.23.0...0.23.1
0.23.0
Security Announcement
This release contains important security updates for CVE-2026-39987. See Terminal WebSocket Authentication Bypass
The /terminal/ws endpoint is accessible without authentication on default marimo installations. This allows for unauthenticated users to remote execute code via this endpoint.
Who is affected
- If you have deployed marimo as an editable notebook (not an application) to the public internet and only using marimo’s built-in authentication.
- If you expose marimo to your shared network using
--host 0.0.0.0and while in edit mode (not an application).
Likely not affected
You are not affected if any of these are true.
- If you have your own authentication proxy on top of editable marimo notebooks.
- If you are not exposing marimo to the public internet
- If you are running marimo as an application (in run mode)
- WebAssembly (WASM) notebooks are not affected
- molab is not affected
Please upgrade to 0.23.0 or later.
What's Changed
- chore: harden df numeric checking by @dmadisetti in #9086
- docs: marimo pair by @akshayka in #9089
- fix: Tab in AI chat triggers autocomplete instead of indenting (#5718) by @mscolnick in #9069
- feat: indicate server side installations by @dmadisetti in #8998
- fix: reset Plotly axis settings when switching between different chart types by @mscolnick in #9067
- fix: table filtering by NaN in pandas string columns by @kirangadhave in #9092
- docs: fix a misformatted markdown link by @YDX-2147483647 in #9093
- fix use API.get for pair with agent modal by @mscolnick in #9090
- feat: Accept suggestion on Enter (frontend-only localStorage pref) by @alwaysahustler in #9016
- feat(plotly): add reactive violin plot selection support by @axsseldz in #9011
- feat(plotly): add reactive area chart selection support by @axsseldz in #9046
- fix: properly authenticate terminal route by @mscolnick in #9098
- release: 0.23.0 by @mscolnick in #9099
Full Changelog: 0.22.5...0.23.0
0.22.0
What's Changed
This release brings a unified data table explorer, reliability improvements to the programmatic notebook API that power the new marimo-pair agent skill, smarter numeric formatting in tables, faster mo.persistent_cache, and a contextual tips system in the CLI.
⭐ Highlights
Combined row viewer and column explorer
The row viewer and column explorer panels are now unified into a single tabbed "Table Explorer" pane. A single toolbar button opens and closes the panel; Rows and Columns tabs live inside it, and your selected tab persists across open/close.
Pair programming with marimo-pair
The experimental _code API receives reliability fixes in this release, enabling the new marimo-pair agent skill for pair programming in marimo notebooks.
npx skills add marimo-team/marimo-pair🚨 Breaking changes
mo.image no longer normalizes uint8 values (#8889)
Previously, mo.image() normalized all numeric arrays (including uint8) to the [0, 1] float range. Now, uint8 arrays are always rendered with values in [0, 255] without normalization. Two new parameters — vmin and vmax — let you set explicit value bounds for under- or over-saturated displays. If you relied on the old uint8 normalization, pass vmin=0, vmax=1 explicitly.
__marimo__ location now follows sys.pycache_prefix (#8797)
The __marimo__ directory now respects sys.pycache_prefix, consistent with Python's own __pycache__ placement. This also fixes cache placement for notebooks in nested directories. Existing caches will not be migrated — they can be safely deleted.
Cache version bump (#8793)
The cache format version has been bumped, invalidating existing caches.
✨ Enhancements
- Remove auto-instantiate from /api/execute endpoint (#8943)
- Use document as source of truth in code_mode _apply_ops (#8944)
- Enhance SQLAlchemy engine with safe_execute and inspector methods for SnowFlake (#8920)
- Support custom cloudpathlib providers in path normalization (#8929)
- Use variable name as download filename in dataframe viewer (#8811)
- Unify row viewer and column explorer (#8905)
- Fix
hide_codenot taking effect on kernel-created cells (#8926) - Virtualize data table rows when pagination is disabled (#8899)
- Emit document transactions from
--watchfile reload (#8846) - Remove document mutation from
session.notify()(#8886) - Style fix for li & ol: reduce margin and restore original disc (#8768)
- Avoid selecting cells in table when interactive elements (#8862)
- Lazy-load KaTeX via dynamic import of @streamdown/math (#8874)
- Display startup tips in CLI (#8836)
- Add ListSQLSchemas to support lazy schema fetching in datasource panel (#8824)
- Auto right-align numeric columns and normalize decimal formatting in tables (#8887)
- Mechanism for parallel read/write in mo.persistent_cache (#8805)
- Convert fonts from TTF to WOFF2, remove unused font files (#8873)
- Prefer tomllib over tomlkit for reading TOML (#8827)
- Support markdown in file tree notebook creation (#8770)
- Allow
codeas positional arg inedit_cell(#8806) - Discourage casual cell naming in code mode (#8804)
- Rename check to skip_validation in code mode API (#8803)
- Document stale globals caveat on ctx.globals (#8802)
- Make _CellsView behave like a read-only ordered dict (#8778)
- Downgrade model fallback log from warning to debug (#8773)
- Add snippet buttons in storage file viewer (#8737)
- Isolation when running multiple notebooks in an app server (#8611)
- Pass raw data for tables during search and copy text/html to clipboard (#8622)
- Support dragging range slider track to move entire range (#8698)
- Propagate notebook
__doc__to cell execution namespace (#8636) - Add POST /api/kernel/focus_cell endpoint for external editor integration (#8497)
🐛 Bug fixes
- Fix
_code_modecell ID collisions on large notebooks (#8951) - Support datetime values in
mo.ui.matplotlibselection masks (#8940) - Sanitize password in frontend render (#8857)
- Kill LSP child processes on shutdown to prevent memory leak (#8927)
- Replace lodash imports with built-in or custom (#8878)
- Remove Content-Length from virtual file StreamingResponse (#8928)
- Enforce cell_ids parameter in session serialization and caching (#8904)
- File descriptor conflicts in terminal ws (#8896)
- Remove matplotlib stretch effect in
mo.ui.matplotlib(#8883) - Key pending tasks by event loop (#8875)
- Use decoding as a heuristic for binary data, and download accordingly (#8858)
- Add script dependencies to data_editor example (#8867)
- Fix cached self entries fsspec (#8863)
- Provide a warning when toml keys are skipped for security (#8854)
- Set file in compilation for app mode linecache and better stack traces (#8800)
- Use python -m pip instead of pip --python for PipPackageManager (#8840)
- Remove litellm (#8852)
- Render data-tooltip in portal to prevent clipping in overflow containers (#8813)
- Clamp memory reported in cgroup v1 reports (#8841)
- Fix asyncio tasks starved by blocking control loop (#8825)
- Keep markdown preview in sync on local edits (#8832)
- Stop mac completion bindings from stealing backticks (#8829)
- Ignore blank line rules (E302, E305) (#8815)
- Fix cells stuck as "needs run" after backend-initiated execution (#8794)
- Graceful fallback for unsupported extension dtypes in to_arrow_ipc (#8785)
- Harden conversion path for ipynbs (#8795)
- Fix console output routing for code_mode run_cell (#8790)
- Append .py extension to markdown notebooks for correct ruff formatting (#8786)
- Patch html-to-image for PNG export font crash and tainted canvas (#8754)
- Exclude index columns for pivot for count/sum agg (#8769)
- Markdown bullets inside of details (#8767)
- Make the pickling mechanism in mo.cache more robust (#8761)
- Recursive private function not detected (#8762)
- Fallback static parsing for completely invalid notebooks (#8723)
- Fix Ty LSP startup and stale diagnostics in notebook editor (#8390)
- Slider editable input ignores debounce bug (#8682)
- Fix three issues with
mo.mpl.interactiveinmarimo runmode ([#8760](https://github.com/marimo-team...
0.21.0
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
0.20.3
What's Changed
This release brings improved PDF export with slide deck support and interactive widget rasterization, along with spreadsheet-style selection statistics for data tables.
⭐️ Highlights
Export slides as PDF
Notebooks using the slides layout can now be exported as PDF:
marimo export pdf --as=slidesThe UI automatically recommends the right preset based on your notebook's layout.
Additionally, the new --rasterize-outputs flag captures interactive widgets (Plotly, anywidgets, etc.) as images in PDF exports — so your interactive components are preserved in the final document. Read the docs for more details.
Summary statistics for selected cells in data tables
Select two or more cells in a data table to see count, sum, and average of the selected numeric values — just like a spreadsheet. Works with mo.ui.table and mo.ui.dataframe.
Smart previews for SQL and markdown cells in the minimap
The dependency minimap now shows the actual content of SQL and markdown cells instead of unhelpful boilerplate like mo.sql(f""".
✨ Enhancements
- Add storage/database connections UI (#8528)
- Add
marimo export sessionCLI tool (#8533) - Export slides as PDF (#8523)
- Add simpler page selector with text input (#8532)
- Add storage file viewer and unify components (#8500)
- Disable "Open in Vega Editor" link in
ChartBuilder(#8503) - PathState follows os.PathLike ABC (#8403)
- Stream virtual files instead of buffering entirely in memory (#8499)
- Render web elements in PDF export (#8458)
- Expand
uv_buildsemver range to "<0.11.0" (#8502) - Improve DuckDB EXPLAIN rendering to show clean query plan text (#8487)
- Unify Marimo icons to SVG and improve component structure (#8471)
- Add dark and light logos for more storage providers (#8476)
- Storage download with signed url and vfile cleanup (#8441)
- Show smart previews for SQL and markdown cells in minimap (#8466)
- Dynamic gallery index refresh on
marimo run <folder> --watch(#8460) - Output Altair SVG charts as base64-encoded images (#8443)
- Add option to create notebook from file tree (#8412)
- Add Dataframe download separator (#8318)
- Add reactive scattergl selection support (#8490)
- Add
html_headparameter tocreate_asgi_app()(#8302) - Add
get_cell_dependency_graphMCP tool (#8174) - Add expand console output button (#7919)
- Add summary statistics for selected cells (#8326)
- CLI error UX improvements (#8375)
🐛 Bug fixes
- Preserve SVG elements and href attributes in sanitization (#8520)
- Improve storage protocol detection (#8513)
- Safer ends_with_semicolon with token errors (#8548)
- Fix pdb arrow navigation (#8543)
- Use custom renderer for marimo elements for chatbot (#8546)
- Memory leak in ASGI session cleanup (#8495)
- When parent dir is searched, child files should be open too in storage-inspector (#8525)
- Fix Panel DynamicMap and interactive streams not updating (#8538)
- Return cell name in run mode (#8524)
- Skip weave on windows (#8539)
- Latex in notebook outline (#8505)
- Remove duplicate separators in action menus (#8509)
- Add "marimo-sidebar" to excluded tags in outline (#8504)
- Fix matrix widget showing stale values after cell re-execution (#8507)
- Fix
mo.cachereturning stale values (#8411) - Detect symlinked files inside assets directory for follow_symlink warning (#8474)
- Render all markdown cells in snippets, not just the title cell (#8480)
- Preserve cell config (hidden/disabled) on undo delete (#8483)
- Implement no-op edit skipping in EditNotebookTool (#8486)
- change copilot endpoint to follow pydantic-ai (#8481)
- remove duplicated system prompt (#8482)
- Prevent TTL timer from killing session when new consumer reconnects (#8461)
- Fix SQL cell deps lost when duckdb fails to parse normalized SQL (#8437)
- Handle gallery crash on file deletion (#8459)
- Stop serving duplicate notebooks when
auto_downloadis set (#8462) - Perform a vectorized search for tables (#8450)
- Plotly-resampler (and other FigureWidget subclasses) not working in marimo by routing
FigureWidgetthrough the anywidget formatter and syncing widget state via_repr_mimebundle_(). (#8430) - More sql prepared statements and quoting (#8431)
- Hide unsupported codemirror language warning when LLM generated (#8432)
- Exclude kernel memory from server memory stats to prevent double-counting (#8426)
- quote duckdb tables, schema with double quote (#8387)
- Sql explain query with newline (#8428)
- Normalize paths in file router to prevent HTTPException with dotdot paths (#8425)
- Use dynamic filename for "Download image" context menu (#8408)
- External cells should not capture vscode cells (#8401)
- Fix sql validation errors not cleared on cell-language switch (#8388)
- Fix command palette not restoring focus to editor on close (341af73)
- Handle
with_dynamic_directorymounted at sub-path (#8322) (#8434) - Prevent stale closure in useNonce hook (#7763)
- Normalize math rendering in docs panel and LSP tooltips (#8315)
📚 Documentation
- Fix authentication middleware example to use pure ASGI middleware (#8473)
- Add cli option to disable DNS rebinding protection for the MCP server (#8464)
- Add docs for supported LSPs (#8463)
- Add wasm example for matplotlib to docs (#8415)
🔬 Preview features
Contributors
Thanks to all our community and contributors who made this release possible: @24f2006299, @akshayka, @Antyos, @app/renovate, @axsseldz, @bxff, @daizutabi, @dmadisetti, @ffmiruz, @giulio-leone, @kyrre, @Light2Dark, @manzt, @mscolnick, @peter-gy, @tigretigre
And especially to our new contributors:
- @zhihuidev made their first contribution in https://github.co...
0.20.2
This release improves the experience of imperatively writing output with mo.Threads, and also includes an important bug fix for mo.ui.matplotlib selection.
⭐️ Highlights
Write to a single cell's output with multiple threads
It is now possible for multiple mo.Thread objects to write to a single cell's output area using mo.output.append().
Communicate progress to the user with a thread-safe progress bar
mo.status.progress_bar is now thread-safe, making it possible for multiple mo.Thread objects (started in the same cell) to update a single progress bar. This lets you communicate progress to the user when multiple threads are sharding work. (Example notebook.)
🐛 Bug fixes
- Fix mo.ui.matplotlib pixel bounds calcuation (#8419)
- Make threads share their accumulated output (#8418)
- Copy
ExecutionContext.outputtomarimo.Thread(#8413)
📚 Documentation
- Fix incorrect data sources panel reference in SQL tutorial (#8422)
- Interrupt a progress bar (#8406)
- Add mo.ui.matplotlib to API inputs documentation (#8394)
Contributors
Thanks to all our community and contributors who made this release possible: @akshayka, @coastalwhite, @icholy, @manzt
And especially to our new contributors:
- @coastalwhite made their first contribution in #8413
- @icholy made their first contribution in #8422
Full Changelog: 0.20.1...0.20.2
0.20.0
This release brings richer interactivity to scientific computing workflows in marimo with new UI primitives and a small breaking change to make mo.stop more predictable.
⭐ Highlights
Reactive selections for Matplotlib scatter plots
mo.ui.matplotlib adds reactive box and lasso selection to Matplotlib scatter plots.
Box select by default, Shift+click for lasso. Read the docs for more details.
Editable matrix and vector inputs
mo.ui.matrix provides interactive numeric grid inputs. Initialize with a nested list or NumPy array and get a reactive element that updates as the user edits cells.
Supports per-element bounds, symmetric constraints, and custom precision. Read the docs for more details.
Rich PyTorch nn.Module display
PyTorch nn.Module instances now render as collapsible HTML trees with color-coded layer categories.
Frozen layers are visually dimmed with trainable parameter counts shown inline. Hover any layer to view its docstring in the Documentation panel.
🚨 Breaking changes
mo.stop now waits for all dependencies to unblock (#8374)
Previously, when a cell depended on two branches that were both stopped with mo.stop, unblocking just one branch would trigger the dependent cell — often resulting in a NameError because the other branch's variables were still undefined. Now, marimo waits until all of a cell's dependencies are unblocked before running it. This also means that manually running a cell with a stopped ancestor will show a clear "ancestor stopped" message instead of a NameError.
✨ Enhancements
- Add
mo.ui.matplotlib()(#8342) - Add Matplotlib SVG output support (#8312)
- Add
mo.ui.matrix()(#8354) - Add default focus for cell-links (#8372)
- Allow excluding code blocks when exporting to PDF (#8362)
- Include
playwrightwhen running sandboxed thumbnail generation (#8339) - Mask
getpass.getpass()input in notebook UI (#8345) - Add sidebar upload progress toast and optional finish title (#8308)
- Use
click.ClickExceptionfor sandbox missing pyzmq error (#8347) - Add interactive doc lookup for
data-marimo-docin cell output (#8343) - Add rich HTML formatter for PyTorch
nn.Module(#8307) - Support
__buffer__objects in widget comm buffers (#8283) - Add r2 support for 'marimo edit' (#8278)
- Render
IPython.display.Imagewith raw bytes (e.g. GIFs) (#8282)
🐛 Bug fixes
- Only trigger cell when ALL its dependencies are unblocked (#8374)
- Supress warnings for meta information in config in markdown (#8290)
- Remove resize when tracing panel in sidebar (#8366)
- Display mermaid error if present and strip diagram (#8368)
- Merge new panels into saved localStorage layout on upgrade (#8351)
- Thread-safe redirection of console outputs in run mode (#8353)
- Apply flex only for nested stacks (#8357)
- Prevent duplicated system prompts in PydanticAI completions (#8356)
- Display math rendering (#8348)
- Fix
+character in file paths being decoded as space in URLs (#8344) - Fix minor typo in mount.tsx (#8325)
- Stop hardcoding us-central1 as vertex ai default location (#8313)
- Suppress dark-mode hover border on published cells (#8297)
- Prevent duplicate execution of nested marimo custom elements (#8286)
- Comment only files count as empty files (#8289)
- Refresh mpl interactive plots when browser tab becomes visible (#8287)
- Fix
mpl.interactivebecomes blank with large plots (#8285) - Add a
has_warningsparse enum to indicate formatting errors (#8288) - Fix flakey
print_codetest (1f706a2) - Fix
--base-urlbreaks og:thumbnail generation path (#8329)
📚 Documentation
- Fix documentation and argument-parsing for thumbnails export (#8301)
- Skills (#8321)
- Clarify pixi vs hatch setup guidance in CONTRIBUTING (#8291)
🔬 Preview features
- Storage inspector backend logic and models (#8233)
Contributors
Thanks to all our community and contributors who made this release possible: @akshayka, @andrewsoonqn, @axsseldz, @daizutabi, @dmadisetti, @fpreiss, @jacobcbeaudin, @jeffs, @Light2Dark, @manzt, @Mr-Neutr0n, @mscolnick, @mstanowski, @peter-gy, @snooze92, @xfy0012
And especially to our new contributors:
- @axsseldz made their first contribution in #8291
- @jeffs made their first contribution in #8297
- @snooze92 made their first contribution in #8301
- @Mr-Neutr0n made their first contribution in #8313
- @xfy0012 made their first contribution in #8308
- @mstanowski made their first contribution in #8329
- @fpreiss made their first contribution in #8356
- @jacobcbeaudin made their first contribution in #8351
Full Changelog: 0.19.11...0.20.0
0.19.11
What's Changed
- docs: minor grammatical corrections to Marimo SQL tutorial. by @gvwilson in #8258
- Bulk notebook state visibility for MCP tools by @nojaf in #8269
- Add Pyrefly support by @yangdanny97 in #7567
- Add marimo-lsp compatibility check by @manzt in #8279
- Revert "improvement: enable reading session cache in App Mode (configurable) (#7895)" by @mscolnick in #8281
New Contributors
- @yangdanny97 made their first contribution in #7567
Full Changelog: 0.19.10...0.19.11
0.19.10
This release focuses on anywidget improvements, along with UI enhancements and many bug fixes.
⭐️ Highlights
anywidget improvements
This release improve marimo's anywidget integration with better lifecycle management, performance, and static export support (#8244, #8166, #8163, #8256, #8168, #8159, #8082). Anywidgets now render in static HTML exports with client-side interactivity preserved, and mo.state setters work in widget callbacks.
Together these changes improve performance and reliability for interactive widget libraries. Here's 10M points rendered interactively on a 24GB M4 MacBook Air with jupyter-scatter:
Try it for yourself on molab!
Column header alignment in tables
Column headers now follow the same alignment as cell data when using text_justify_columns, fixing the visual mismatch where headers stayed left-aligned while data was right- or center-aligned. (#8236)
Hide reusable functions from the dependency graph
A new "Hide reusable functions" toggle in the dependency graph settings panel lets you declutter the graph by hiding def cells that don't have edges to other cells. (#8228)
✨ Enhancements
- Allow
mo.statesetters in widget callbacks (#8244) - Persist anywidget model state in static HTML exports (#8166)
- Add toggle to hide reusable functions from dependency graph (#8228)
- Always show default value for CLI args (hide if default is None) (#8246)
- Add disabled parameter to mo.ui.chat (#8214)
- Align column headers with text_justify_columns setting (#8236)
- Support for
dict(ChatMessage(...))(#8091) - Add uv version to
marimo envoutput (#8157) - Merge model messages into a single replay snapshot (#8163)
🐛 Bug fixes
- Grab module css from model-state instead of passing via DOM attributes (#8256)
- Remove openai from required dependencies (#8265)
- Add back margin for missing gap in file explorer panel (#8267)
- Batch anywidget model updates like UI element updates (#8168)
- Better datastructures for kernel Runner (#8251)
- Don't read the full file for OSFileSystem._is_marimo_file (#8253)
- Prevent sidebar resize handle from overlapping file explorer buttons (#8181)
- Normalize Html subclasses in as_html for correct f-string formatting (#8223)
- Use variable name as download filename in dataframe viewer (#8227)
- Avoid unnecessary duckdb calls in stats and getting db names (#8250)
- Use mount_config.code and filename as fallback in WASM mode (#8161)
- Continue on thumbnail capture timeout (#8254)
- Include xfailed and xpassed in pytest summary counts (#8220)
- Preserve justify on nested stacks when widths/heights are set (#8219)
- Suppress RuntimeWarning for all-NaN DataFrame columns (#8217)
- Allow interaction with sidebar behind package alert popup (#8216)
- Prevent margin collapse between consecutive cell outputs (#8215)
- Don't enable reactive tests in run mode (#8252)
- Upgrade codemirror-languageserver to fix prefix completions with underscore (#8245)
- Handle null registration.active in service worker registration (#8213)
- Set data-theme attribute on body for third-party dark mode compat (#8231)
- Decorator invalidation for caching (#8171)
- Disable panel resize handles when panels are collapsed (#8183)
- Preserve return statements inside nested functions when pasting (#8222)
- Close anywidget comms on cell re-execution and deletion (#8159)
📚 Documentation
- Fix reddit links (#8266)
- Gallery + OpenGraph preview docs (#8122)
- Removes ploomber deployment (#8249)
📝 Other changes
- Preserve function return type in live docs panel (#8210) (#8263) (3828e5f)
- Bump loro (#8264)
- Update Plotly to 3.3.1 and add heatmap click event (#8255)
- Update dependency anywidget to ~=0.9.21 (#8082)
- Enable reading session cache in App Mode (configurable) (#7895) (d85e9b7)
- Update codemirror dependencies (#8170)
- Replace react-plotly.js with vendored Plot component (#8238)
- Respect display.dataframes config setting (#8053) (190ca31)
Contributors
Thanks to all our community and contributors who made this release possible: @AhmadYasser1, @akshayka, @dmadisetti, @ffmiruz, @julianpistorius, @koaning, @Light2Dark, @manzt, @maxkoretskyi, @mscolnick, @nojaf, @peter-gy
And especially to our new contributors:
- @chrisflath made their first contribution in #8053
- @jpopesculian made their first contribution in #7895
- @AhmadYasser1 made their first contribution in #8222
- @julianpistorius made their first contribution in #8249
- @ffmiruz made their first contribution in #8161
Full Changelog: 0.19.9...0.19.10










