Releases: marimo-team/marimo
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
0.19.9
What's Changed
- docs: molab links by @akshayka in #8112
- docs: fix bold formatting by @akshayka in #8153
- improvement: add terminal width by @mscolnick in #8151
- cli: format help message with colors, bold by @akshayka in #8141
- Update CONTRIBUTING.md to include note about WSL by @Ethan-Prunty in #8140
- refactor: move thumbnail gen tool under
marimo exportnamespace by @peter-gy in #8154 - ci: split labeler workflow to prevent cancellation failures by @akshayka in #8160
- fix: additional validation by @dmadisetti in #8162
- Separate anywidget Model from widget binding lifecycle by @manzt in #8156
- fix: failed package installation commands should not kill kernel by @akshayka in #8158
New Contributors
- @Ethan-Prunty made their first contribution in #8140
Full Changelog: 0.19.8...0.19.9
0.19.8
This release introduces notebook galleries with OpenGraph previews, along with anywidget improvements, AI enhancements, and many bug fixes.
⭐️ Highlights
Serve a gallery of notebooks
You can now serve multiple marimo notebooks as a gallery using marimo run with folders or multiple files. This is useful for showcasing collections of notebooks, tutorials, or dashboards in a single browsable interface.
# Serve all notebooks in a folder
marimo run my_notebooks/
# Serve multiple folders and files
marimo run tutorials/ examples/ standalone.py
# Run with sandboxed environments per notebook
marimo run my_notebooks/ --sandboxRich gallery previews with OpenGraph metadata
Gallery cards can be customized with OpenGraph metadata. Define metadata in your notebook's PEP 723 script block to control how each notebook appears in the gallery:
[tool.marimo.opengraph]
title = "My Analysis"
description = "Exploratory data analysis of Q4 results"
image = "https://example.com/thumbnail.png"For dynamic metadata, define a generator function that computes OpenGraph fields at runtime.
You can also auto-generate thumbnail images for your notebooks using marimo export thumbnail:
# Generate thumbnails (code-only, no execution)
marimo export thumbnail my_notebooks/
# Generate thumbnails with notebook execution for richer previews
marimo export thumbnail my_notebooks/ --execute --sandboxThumbnails are stored in the __marimo__/ directory alongside your notebooks and served automatically in gallery mode.
Attach images to "Generate with AI"
You can now attach images when using "Generate with AI" to provide visual context for code generation. This is useful for sharing mockups, charts, or screenshots that help the AI understand what you're trying to build.
✨ Enhancements
- Add attachments for 'Generate with AI' & ensure UI consistency (#7996)
- Update models.yml for Opus 4.6 (#8142)
- Add proxy_path support for ClickHouse Connections (#8128)
- Require playwright installation for pdf export (#8121)
- Improve design of chat mode selector (#8114)
- Set markdown to hide after conversion for consistency (#8117)
- Anywidget dynamic imports in static notebooks (#8110)
- Rich notebook previews through OpenGraph metadata (#8097)
- Graduate performant table charts and chat modes from experimental (#8107)
- Sandboxed gallery (#8076)
- Replace logo with back button for notebooks in gallery mode (#8099)
- Register Office document mimetypes for cross-platform compatibility (#8068)
- Support serving a gallery of notebooks (#8056)
🐛 Bug fixes
- Fix spurious "truth value of UIElement" warning for anywidgets (#8148)
- Decouple anywidget model and view (#8124)
- Support pandas 3.0 str col (#8146)
- Follow ruff rules for formatting trailing space after imports/ functions (#8086)
- Search functionality for DataFrames with index columns (#8136)
- Support multiple vfile registries with shared inmemorystorage (#8145)
- Don't error when writing UI elements values that already exist (#8147)
- Avoid unnecessary throwing error in delete cell (#8134)
- Remove some deprecation warnings (#8113)
- Handle bang statement edgecases in ipynb convert (#8126)
- Top-level defs showing up in wasm (#8138)
- Use cell name to identify setup cells when id is null (#8137)
- Hash on unspecified keyword values (#8127)
- Handle marimo tex components when exporting to PDF (#8062)
- Sandbox package listing (#8104)
- Preserve whitespaces & new lines when inferring parts during rendering outputs (#8116)
- Don't allow '.' when creating custom provider names (#8115)
- Fix schema drift for chat-ui (ai-sdk 6) (#8105)
- Handle objects with
__getattr__returning non-callable values in serialization (#8109) - Gracefully handle timeouts/input from uv when adding script metadata (#8111)
- Add missing word to UI tutorial (#8087)
- Handle sqlglot OptimizeError for DuckDB unnest with JSON access (#8083)
- Enable weave tracing on chat widget (#8078)
- Table data not refreshing after
mo.output.replace()when first-page data is unchanged (#8066)
📚 Documentation
- Clarify markdown section in Jupyter users tutorial (#8092)
📝 Other changes
- Update all biome dependencies to v2.3.13 (#8044)
- Upgrade pytest plugins, upperbound sqlglot (#8077)
- Update WebSocket URL generation for agents to work on remote deployments (#8065)
- Update all npm non-major dependencies (#8085)
- Add missing type field to control requests (#8071)
Contributors
Thanks to all our community and contributors who made this release possible: @dmadisetti, @gvwilson, @koaning, @Light2Dark, @lucharo, @manzt, @maruthgoyal, @mscolnick, @peter-gy, @marcodlk
New Contributors
- @bxff made their first contribution in #8083
- @gvwilson made their first contribution in #8087
- @maruthgoyal made their first contribution in #8128
- @Deufel made their first contribution in #7681
Full Changelog: 0.19.7...0.19.8
0.19.7
⭐️ Highlights
PDF Export
marimo now supports exporting notebooks as PDFs, both from the CLI and directly from the notebook interface. Whether you're generating documentation, creating reports, or sharing your work, you can now produce professional-looking PDF outputs with full support for your notebook's visualizations and markdown content.
Export from the command line using the new marimo export pdf command, with options to control output format and include CLI arguments for parameterized notebooks. The PDF exporter runs your notebook, captures all outputs, and uses nbconvert's WebPDF exporter (powered by Chromium) for high-quality rendering. When running marimo as a notebook, you'll find a new "Export as PDF" option in the export menu.
# Export a notebook to PDF
marimo export pdf notebook.py -o notebook.pdf
# Pass CLI arguments to your notebook
marimo export pdf notebook.py -o report.pdf -- --date 2026-01-29 --region west
# Watch for changes and auto-regenerate
marimo export pdf notebook.py -o notebook.pdf --watchRequirements: PDF export requires nbformat and nbconvert[webpdf] to be installed.
✨ Enhancements
- apply patch for extraStyleContent (#8043)
- add more linking to provider page (#8041)
- Lsp status icon and refresh (#8011)
- Additional print configuration, fix race conditions in export to pdf (#8038)
- Include mime-type precedence and visibilty rules (#8037)
- add snappy parameter to speed up auto-export (#8032)
- fix carousel styles (#8022)
- add progress bar for download pdf (#8016)
- add placeholder images for external iframes on export to pdf (#8003)
- Support srcdoc screenshots (#8001)
- link to provider and model page directly (#7979)
- Dont set --compile-bytecode for uv installation (#7985)
- Add Minimap/Graph toggle to dependencies panel in developer panel (#7976)
- Downgrade dataframe in non-interactive environments (#7940)
🐛 Bug fixes
- No diff churn when adding requires-python to a sandboxed file (#8054)
- Add back LSP snippets, upgrade codemirror-languageserver (#8052)
- LSP reconfiguration missing cell-id (#8050)
- remove manual handling of local iframes, only external iframes (#8051)
- Ensure overflow is captured in screenshots, and ensure smooth capture (#8046)
- fix timing issue to apply edits after data has come in (#8025)
- Lsp potential race conditions (#8012)
- Save content when creating a new file via filename input (#8009)
- Ensure logs are scrollable in developer panel (#8002)
- Refine rendering of equations in chat pane (#7961)
- Add plotly scattermap/scattermapbox point selection support (#7975)
- prevent layout shift for auto-export ipynb (#7965)
- Avoid ValueError when comparing embed defs with NumPy arrays (#7980)
- fix setting UI config to empty for AI custom & displayed models (#7991)
- Plotly shapes not clearing when removed from figure (#7974)
- Correct input channel direction for IPC sandbox mode (#7973)
- support ansi characters in pdf export (#7962)
📚 Documentation
- Small textual corrections in Claude Code doc (#7951)
🔬 Preview features
- turn on server_side_export_to_pdf flag (#8036)
📝 Other changes
- 0.19.7 (fc88208)
- Default to wedpdf since tex seems to have more issues (#8055)
- Proper fallback for mo.watch.file in wasm (#7982)
- toast an error if Export as png fails (#8049)
- Preserve
_marimo_row_idwhen clamping table columns (#8029) (#8035) (83f0901) - Update all biome dependencies to v2.3.12 (#8039)
- Update pymdownx admonition smoke tests with new syntax (#8028)
- Consolidate
watch_and_exportimplementations (#8000) - Export notebooks as PDFs via CLI (#7997)
- Windows path issue (#7978) (#7990) (6d3a6eb)
- Update all storybook dependencies to ^10.2.0 (#7987)
Contributors
Thanks to all our community and contributors who made this release possible: @akshayka, @app/renovate, @dmadisetti, @faysou, @Light2Dark, @manzt, @mscolnick, @MukeshK17, @peter-gy, @sswatson-ap
New Contributors
- @sswatson-ap made their first contribution in #7951
- @kitswas made their first contribution in #7990
- @MukeshK17 made their first contribution in #7980
- @faysou made their first contribution in #7961
Full Changelog: 0.19.6...0.19.7
0.19.6
What's Changed
🐛 Bug fixes
- fix number component navigation (#7957)
- --sandbox flag should add script metadata when none exists (#7954)
- Include rich console outputs in PDF/ipynb export (#7955)
📚 Documentation
- Add screenshot and clarify ipynb snapshotting docs (#7952)
📝 Other changes
Contributors
Thanks to all our community and contributors who made this release possible: @akshayka, @app/renovate, @manzt, @mscolnick
Full Changelog: 0.19.5...TODO_CURRENT_VERSION
0.19.5
What's Changed
✨ Enhancements
- inverted flag for pdfDownloadEnabled (#7936)
- smartly set chat & edit models based on ai config (#7901)
- CLI update secure docker to python3.14 (#7926)
- Fallback to png for matplotlib when in a non-interactive environment (#7924)
- Add config for default csv encoding (#7875)
- Fail CLI edit if shared memory is not available (#7921)
- Move marimo import to top in convert command (#7828)
- add new endpoint to download pdf using nbconvert & feature flag (#7894)
- Use vega 6 mimetype, capture screenshots on pdf export (#7906)
- Export mo.mpl.interactive as PNG, and altair as json spec when running (#7874)
- Normalize git urls in conversion from jupyter to marimo deps (#7876)
- Include marimo metadata on ipynb export (#7878)
- Add [marimo.server.disable_file_downloads] (#7844)
- Add
--session-ttlflag to marimo edit (#7863)
🐛 Bug fixes
- Fixes cases where images end up clipped when taking screenshots for pdf downloads (#7933)
- fix chat panel clipping issue (#7930)
- Don't broadcast variables from embedded apps (#7896)
- Serialize geopandas geometry columns as WKT strings (#7923)
- Specify a package name to be installed by DependencyManager (#7907)
- Dont hide cell if interactive with vim search or dropdowns (#7911)
- Skip normalization for cloudpath (#7904)
- Fix SQL f-string placeholder causing parsing errors in interval expressions (#7881)
- UI element interaction should respect overridden defs in embedded apps (#7889)
- fix run buttons being flexed in compact mode (#7885)
- LSP diagnostics (#7877)
- Preserve trailing comments in pure functions, setup cell (#7879)
- Remove hover border on borderless cells (#7870)
- Nested display math (#7873)
- Improve error handling for pyiceberg list_namespaces permission errors (#7864)
📚 Documentation
- Plotly express install needs dependency group (#7897)
- Fix some embeds (#7890)
- Update sandbox documentation link to correct page (#7888)
- Remove opt-in note about reactive reference highlighting (#7868)
📝 Other changes
- Pandas dataframe named index cells showing empty (#7942) (#7944) (3127f40)
- Data-explorer charts from vega-upgrade (#7941)
- Support base-url in LSPs (#7909)
- Add deserialize NotebookSerializer (#7925)
- [pre-commit.ci] pre-commit autoupdate (#7900)
- Add documentation for sidebar and developer panel (#7758) (9bcb4ff)
Contributors
Thanks to all our community and contributors who made this release possible: @akshayka, @AnirudhDagar, @app/pre-commit-ci, @dmadisetti, @EdSwarthout, @koaning, @Light2Dark, @manzt, @mscolnick, @tokoko, @VedantMadane
New Contributors
- @VedantMadane made their first contribution in #7864
- @tokoko made their first contribution in #7875
- @EdSwarthout made their first contribution in #7926
Full Changelog: 0.19.4...0.19.5
0.19.4
What's Changed
- Increase codecov timeout by @akshayka in #7852
- refactor: move files and tests around to cleanup
marimo._convertby @mscolnick in #7858 - fix: skip conencting to terminal in windows by @mscolnick in #7861
Full Changelog: 0.19.3...0.19.4







