Releases: marimo-team/marimo
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
0.19.3
This release introduces isolated sandbox environments for multi-notebook directories and migrates our AI integrations to pydantic-ai for improved reliability with modern LLM providers.
What's Changed
Multi-Notebook Sandboxed Home
You can now run marimo edit --sandbox directory/ to open a folder of notebooks where each notebook runs in its own isolated sandbox environment. This means:
- Every notebook automatically gets its own virtual environment with its own dependencies
- Dependencies are managed per-notebook using PEP 723 inline script metadata
- Each notebook remains reproducible and self-contained
This is useful when working on multiple notebooks with different dependency requirements, or for maintaining a collection of standalone, shareable notebooks.
# Open a directory with per-notebook isolation
marimo edit --sandbox ./notebooks/Note
This feature requires pyzmq as a dependency. If you're running marimo with uvx, use:
uvx --with pyzmq marimo edit --sandbox ./notebooks/Alternatively install marimo as marimo[sandbox] or marimo[recommended] to get all the recommended packages.
See our guide on sandboxed home and inlining dependencies guide for more details on sandboxed notebooks.
AI Provider Migration to pydantic-ai
We've migrated our AI integrations to use pydantic-ai, which brings several improvements:
- Better model support: Fixed issues with newer OpenAI models (GPT-5, Codex models) that require the Responses API and
max_completion_tokensparameter - Improved timeout handling: Resolved timeout issues when connecting to remote Ollama instances and other providers
- Support for more providers: Added support for providers like Mistral that aren't fully OpenAI-compatible
- Better error handling: More informative error messages when AI requests fail
This is a behind-the-scenes change that improves reliability—your existing AI configuration should continue to work without changes
✨ Enhancements
- Migrate AI providers to pydantic-ai (#7732)
- Add custom AI providers in config (#7771)
- Support custom models returning vercel chunks (#7797)
- Add
[tool.marimo.venv].pathto specify a specific venv (#7821) - Support images mimebundling in auto export for ipynb (#7825)
- Allow for
__contains__and__getitem__in anywidget (#7846) - Clarify column filtering is only for top 30 values (#7840)
- Update connecting alert to show a spinner and banner notification (#7839)
- Include errors with ipynb exports (#7811)
- Runtime configuration tooltips, docs (#7819)
- Parse indented code blocks (#7817)
- Don't steal focus when embedded in an iframe (#7798)
- Auto-close curly braces within strings (#7759)
- When previewing ibis tables in interactive mode, also include SQL and repr tabs (#7757)
- Sandboxed home (#7702)
- Ensure Plotly area chart is reactive (#7761)
🐛 Bug fixes
- Keep rich objects in chat message (#7851)
- Ibis Deferred expression object will not be handeled as datasource (#7801)
- Duplicate notebook when running 'marimo edit ' (#7841)
- Fix
mo.ui.dataframeshowing incorrect column count (#7845) - Start remote connection in a Connecting state (#7838)
- Escape key should not prevent exiting to Vim mode (#7812)
- Keep terminal mounted to preserve session across tab switches (#7833)
- Enhance keyboard handling in editable name cell component (#7818)
- Fix reactive Plotly heatmap selection with datetime axes (#7805)
- Limit private variable rename to current cell (#7814)
- More defensive edge cases when adding packages to inline metadata (#7813)
- Ensure
repr_mimebundlehandles empty include/exclude parameters gracefully (#7787) - Fixes chat config not updating (#7808)
- Fix opencode duplicate tokens bug (#7792)
- Return empty string if no tabs (#7772)
- Setup cell (#7778)
📚 Documentation
- Document
mo.ui.plotlysupport for bar and heatmap (#7769)
📝 Other changes
- Update react-aria dependencies (#7822)
Contributors
Thanks to all our community and contributors who made this release possible: @akshayka, @alonsosilvaallende, @andrewsoonqn, @AnirudhDagar, @dmadisetti, @koaning, @Light2Dark, @mscolnick, @NickCrews, @nojaf, @pepijndevos, @Ravinlathigra, @szst11
- @NickCrews made their first contribution in #7757
- @alonsosilvaallende made their first contribution in #7787
Full Changelog: 0.19.2...0.19.3
0.19.2
What's Changed
This PR fixes a bug that prevented deployed notebooks from accessing request context like user authentication data, cookies, headers, etc.
- fix: populate mo.app_meta().request in run mode by @Ravinlathigra in #7770
New Contributors
- @Ravinlathigra made their first contribution in #7770
Full Changelog: 0.19.1...0.19.2
0.19.1
What's Changed
This release includes a new API for formatting values in mo.ui.dataframe, as well as small bug fixes.
✨ Enhancements
- Support format_mapping for dataframe as table (#7745)
🐛 Bug fixes
- Running sandbox link in home is broken when launched under subdir (#7764)
- Lower minimap z-index to stay within panel bounds (#7766)
- fix data editor width by setting full width on parent (#7760)
📚 Documentation
- Add quotes around path in TOML (#7765)
📝 Other changes
- 0.19.1 (371f3c8)
Contributors
Thanks to all our community and contributors who made this release possible: @akshayka, @dmadisetti, @hodlen, @Light2Dark, @manzt
Full Changelog: 0.19.0...TODO_CURRENT_VERSION
0.19.0
This release introduces a refreshed UI with lighter cell styling and a new Developer Panel, along with reorganized sidebar panels and important bug fixes.
Highlights
Introducing the Developer Panel
marimo has many panels for configuring and inspecting notebooks, but mixing essential tools with advanced features can overwhelm new users. This release introduces a dedicated Developer Panel at the bottom of the editor (similar to VS Code's panel or browser DevTools) to house specialized tools like the terminal, logs, tracing, and scratchpad.
The sidebar now focuses on core panels that all users need, while power users can open the Developer Panel when they need deeper visibility into execution or want a scratchpad for experimentation. If you prefer a different arrangement, panels can be freely moved between the sidebar and Developer Panel—just drag them where you want.
- Toggle the Developer Panel with
Cmd/Ctrl + Jor via the footer - Drag panels between the sidebar and Developer Panel to customize your layout
Consolidated Sidebar Panels
To reduce clutter, several panels have been reorganized:
- Minimap has moved into the Dependencies panel as a tab. The same keyboard shortcut opens it (
Cmd/Ctrl+Shift+I) - Variables & Data Sources are now combined into a single panel with collapsible accordion sections
✨ Enhancements
- Unify panel actions to work across sidebar and developer panel (#7743)
- Move minimap into "Dependencies" panel with tabbed UI (#7742)
- Implement wrap around feature for
mo.carousel()(#7709) - Add ADBC DB-API engine for SQL connections (#7664)
- Also allow
Ctrlas modifier key on macOS (#7608) - Add panel section context for orientation-aware layouts (#7724)
- Add cross-list drag-drop for sidebar and developer panel (#7697)
- Small fixes for cell shadows and hover (#7715)
- Shadow adjustments (#7700)
- implement pydantic-ai provider for mo.ui.chat (#7636)
- Lighten shadows (#7682)
- Fix sidebar drag-and-drop requiring click before drag (#7669)
- Pytest fixtures (#7654)
- Add command history navigation with arrow keys (#7617)
- Add send button, and clean styles of AI buttons (#7445)
- Lazy backend (#7523)
- Add support for reactive Plotly bar chart (#7733)
- Feat add pivot transform to
mo.ui.dataframe(#7584) - Reactive Plotly heatmap (#7546)
- Support uv
devinstall (#7372) - Combine "Variables" & "Data Sources" panels into "Variables & Data Sources" panel (#7459)
- Detect
!pipand give better error message (#7525) - Cell styles on sort/pagination (#7452)
- Consolidate developer tools into dedicated "Developer Panel" (#7458)
- Double click to reveal hidden markdown code (#7495)
- Create cell button, collapse strokes/size (#7448)
- Always collapse runtime settings into a single dropdown (#7461)
🐛 Bug fixes
- Remove width param for data editor (#7741)
- Relative path fixes for home mode (#7722)
- Fix duplicate HTML5 backend error in file explorer (#7723)
- refresh table on cell styles change (#7705)
- Fix path resolution for .resolve() and .absolute() for correctness and security (#7703)
- Disallow file access outside directory where 'marimo edit <folder' is run (#7701)
- Ipynb export matplotlib (#7696)
- Windows path validation, convert to longpath (#7691)
- Specific handling for lazy requests (#7698)
- Fix
Ctrl+Clickto select cell type on Windows/Linux (#7580) - Fix escape logic for selections and multiple cursors in a cell (#7434)
- Fix request type (#7601)
- Fix dataframe flaky test (#7589)
- Fix example code in
UIElement.formdocstring (#7578) - Fix for pasting images in markdown (#7536)
📚 Documentation
- Add "using claude code" section (#7687)
- Add pydantic-ai to chatbot docs (#7706)
- Add Codex agent support to agents guide and update AI completion reference (#7658)
- Correct spelling of 'sqlalchemy' in SQL docs (#7509)
- Fix new stat docs (#7503)
- Use update cell code to not wait for cell editor (#7520)
📝 Other changes
- Split out docker ci to be manually run (#7740)
- Add repository to package.json (#7725)
- Single release.yml with switch (#7719)
- Address windows flakiness by reducing introspection calls (#7678)
- Turn off auto install for micropip (#7680)
- Update all storybook dependencies to ^10.1.11 (#7610)
- Path validation test and public asset logic (#7688)
- Home page lazy loading (#7689)
- interpolate globals into sql query using string formatting for validate_sql (#7562)
- Fix cross-view interactions (e.g., brush selections) breaking in concatenated Altair charts when using
mo.ui.altair_chart. (#7673) - Preserve symlinks in path validation check (#7671)
- Better parsing for pep dependencies in pyodide (#7670)
- Point selection for altair heat maps (#7675)
- Respect include_code setting for code downloads in run mode, and show "Download as .py" (#7642)
- Add accept & reject buttons for setup cell (#7667)
- Cgroup-aware machine stats (#7488)
- Add marimo as a dependency if it isn't already (#7656)
- Add cell prefix to setup cell registration (#7648)
- Invalid error thrown when undefined setup variables (#7649)
- Wider duckdb support, wider types check (#7644)
- Remove some duplication in pyproject.toml (#7646)
- Use dependency-groups in pyproject.toml (#7325)
- Better minimum resolutions (#7639)
- Allow saving notebooks on /tmp_mnt paths (#7641)
- Do not use shared memory in run case (#7637)
- Quarto specific code block (#7623)
- Cleanup app-router (#7628)
- Move find-free port so _plugins don't depend on _server (#7633)
- Improve clarity in Traditional Chinese README (#7635)
- Set only partial updates for config changes (#7634)
- Use Com...
0.18.4
What's Changed
- fix download_json in tables by adding strict_json arg by @Light2Dark in #7429
- fix: allow generics on top level definitions by @dmadisetti in #7417
- docs: update slurm by @akshayka in #7418
- ux: single-click to create Python cells by @akshayka in #7440
- [pre-commit.ci] pre-commit autoupdate by @pre-commit-ci[bot] in #7438
- add a html slot on the right side of a stat plugin by @Light2Dark in #7384
- fix wide notebook banner for column layout by @Light2Dark in #7436
- Unify handling of widget state/buffers/bufferPaths by @mscolnick in #7441
- add not_in filter for tables and dataframes by @Light2Dark in #7439
Full Changelog: 0.18.3...0.18.4
0.18.3
What's Changed
✨ Enhancements
- handle nans and infs in table filter (#7402)
- Improve scroll position handling when toggling between edit and app mode (#7406)
- Enhance lazy df utilities and ensure dataframe type preservation in transformations (#7401)
- Add file limit, warning, and more performant file detection (#7368)
- Detect and warn about duplicate shortcuts (#7412)
🐛 Bug fixes
- Update NavigationMenu for correct popover positioning (#7403)
- Line parsing for debugpy (#7415)
- Bump max version altair (#7414)
- Handle decimal in column hist (#7413)
- Hide pylsp error on the home page (#7416)
- Lazy import psutil for windows (#7411)
- Deserialization of user config in pyodide (#7405)
Contributors
Thanks to all our community and contributors who made this release possible: @dmadisetti, @Light2Dark, @mscolnick
Full Changelog: 0.18.2...0.18.3

