marimo v0.23.9 Release Notes
Release Date: 2026-06-04 // 6 days ago-
What's Changed
This release makes opening a notebook in a second tab non-destructive,
mo.ui.tableadds new args forhidden_columns/visible_columns(mutually exclusive), and tightens sharing and error-output behavior across the board.⭐️ Highlights
Open the same notebook in a second tab
💻 Opening a notebook in a second browser tab no longer forcibly disconnects the first. The new tab joins as a live, read-only viewer, and you can take over editing from either side with a single click — no destructive modal and no reload required (#9746).
💅 Screen.Recording.2026-06-01.at.3.31.17.PM.mov
👉 Show and hide table columns
💻
mo.ui.tablenow supports column visibility. Hide and show columns from the column header menu, Column Explorer with a click, find columns fast with smart prefix-based search, and control initial visibility from Python. A hidden-count and "Unhide all" link keep things discoverable (#9687, #9696).💅 Screen.Recording.2026-05-26.at.6.35.04.PM.mov
Cells with no output now show in slides
Because slides allow code edits, a slide edited to no longer produce an output used to disappear from the deck entirely. Such cells now appear in the slides minimap and viewer so you can edit them back in (they're still skipped during a presentation). Minimap thumbnails are also larger and more readable (#9771).
💅 Screen.Recording.2026-06-03.at.2.25.46.PM.mov
✨ Enhancements
- Add MARIMO_RESTRICT_SHARING env var machine-wide (#9756)
- Non-destructive local takeover (read-only viewer + bidirectional takeover) (#9746)
- ➕ Add cells with no output to the minimap & viewer (#9771)
- ➕ Add GET /api/kernel/status endpoint (#9768)
- 🔒 Enforce sharing config as server-side security (#9578)
- ➕ Add filter param for regex and callable filtering (#9667)
- 0️⃣ Slides config panel open by default (#9737)
- ➕ Add pair with agent link (#9738)
- ➕ Add Opus 4.8 and script to append models to the top (#9723)
- ✂ Remove mapping for 'src' to 'auto-mix-prep' (#9725)
- ➕ Add workflow to automate running llm-sync-models script (#9724)
- Automation script to pull models.yml (#9635)
- 👌 Support Dremio ADBC data source browsing (#9694)
- Add auto_close_pairs setting (#9711)
- WASM compatibility rule checks (#9587)
- 🛠 Fix dropped error hints and improve error output UI (#9673)
- Column Explorer visibility controls + smart-search (#9696)
- Sort toml entries when writing config (#9686)
- Pretty format hidden variable behavior in stack traces (#9660)
- ➕ Add column visibility kwargs and UI controls (#9687)
- 💻 Unified filter pill UI with overflow strip (#9638)
- ➕ Add padding between cell number and minimap dependency lines (#9675)
🛠 🐛 Bug fixes
- 👷 Escape user-controlled file_key in service worker injection (#9789)
- 🛠 Fix completions in slides view (#9769)
- Arg/kwarg collision for local numpy vars in caching (#9751)
- Suppress marimo hover tooltip for all LSP providers, not just pylsp (#9741)
- 🛠 Fix SQL defs lookup (#9754)
- Keep stepped range progress totals aligned (#9582)
- 0️⃣ Per-provider max_tokens defaults with optional override (#9703)
- 💻 Accept ChartDataType in mo.ui.table to resolve pyright error when passing chart.value (#9674)
- Jump to running notebook cells only (#9707)
- Fix mo.cache raising KeyError: ' scratch' in scratchpad (#9664)
- 🛠 Fix interruption for pydantic-ai chatbot (#9620)
- Preserve top level names for name thrashing (#9695)
- Lazy download-size RPC + first-page extrapolation (#9691)
📚 📚 Documentation
- ➕ Add config to disable AI (#9739)
- ⚡️ Update molab docs with new compute and sharing features (#9748)
📝 Other changes
- 🖨 Don't shadow builtin print unless mo.Thread is used (#9765, #9766)
- Zz/zt/zb scroll for notebook viewport (#9701, #9728)
- ➕ Add rule to prevent test files from having the same name (#9671)
Contributors
🚀 Thanks to all our community and contributors who made this release possible: @akshayka, @corleyma, @dmadisetti, @everettroeth, @foxcroftjn, @GHX5T-SOL, @kirangadhave, @kjgoodrick, @kratos0718, @Light2Dark, @mscolnick, @nojaf, @Rowlando13, @VishakBaddur, @XanthanGum
And especially to our new contributors:
- @everettroeth made their first contribution in #9664
- @foxcroftjn made their first contribution in #9686
- @GHX5T-SOL made their first contribution in #9582
- @kratos0718 made their first contribution in #9667
- @XanthanGum made their first contribution in #9725
Full Changelog : 0.23.8...0.23.9
Previous changes from v0.23.7
-
What's Changed
🚀 This release brings major upgrades to table filtering, adds speaker notes to slide view, and lets WASM notebooks query remote files with DuckDB.
⭐ Highlights
Powerful new table column filters
Table columns now support the full operator set across every dtype. Text columns get
contains,starts_with,ends_with,equals,regex,is_empty, and more, with a slash-bracketedregexinput and a creatable values picker forin/not_in. Number columns get nativebetween, and the new date/datetime/time filter UI brings the same operator coverage to date-like columns with smart clipboard paste for ISO/US/RFC dates andA - Branges (#9597, #9615).💅 Screen.Recording.2026-05-18.at.7.54.06.PM.mov
Speaker notes for slides
Press
Sin slide view to open speaker notes alongside the current slide, including in fullscreen and kiosk mode (#9533).💅 Screen.Recording.2026-05-12.at.5.32.23.PM.mov
Query remote files with DuckDB in WASM notebooks
WASM notebooks can now read CSV, Parquet, JSON, and GeoJSON over HTTP from
mo.sql, SQL cells, rawduckdb.sql/query/execute, connection SQL methods, and theduckdb.read_csv/read_parquet/read_jsonPython API. marimo rewrites the AST withsqlglot, fetches the remote file via its shared WASM fetch util, and binds the result as a pandas DataFrame that DuckDB can scan (#9480).SELECT\*FROMread_csv('https://example.com/cars.csv')✨ Enhancements
- Expand column filter operators and pill-editor UX (#9597)
- 💻 Date/datetime/time filter UI (#9615)
- ➕ Add speaker notes for slides (#9533)
- 👌 Support HTTP DuckDB queries in WASM notebooks (#9480)
- Snapshot document and outputs in MCP execute_code (#9654)
- Rename ctx.notify to broadcast_raw_notification (#9581)
- Record staleness reads on .code access only (#9655)
- 🔦 Expose cell outputs to code_mode (#9653)
- 👉 Make
marimo newCLI help page render properly at 80 columns (#9636) - Read-before-write protection for cell edits (#9585)
- 📦 Skip stdlib/site-packages on per-cell check (#9629)
- 👉 Show cell index in dependency minimap (#9633)
- Extract ModuleReloader/ModuleWatcher into AutoreloadManager (#9590)
- DRY up code between wasm and native kernel (#9591)
- ⚡️ Update default duckdb mo.sql deps (#9599)
- 💻 Show .git and .venv in file browser (#9606)
- 👌 Support disabled on dropdown and multiselect (#9600)
- Split kernel command dispatch into router + callback bundles (#9577)
- ➕ Add Prompt tab to pair-with-agent modal (#9568)
- Replace MarimoFileKey alias with FileKey ADT (#9483)
- Optimize memoize_last_value for faster UI reactivity (#9555)
- 🗄 Hardening pass — utilities, deprecated API cleanup, lifespan fix (#9552)
- Stream uploads to disk instead of buffering (#9527)
- ➕ Add
kernel_session()as context manager, DRY up tests (#9554) - Sandboxed exports for consistent wasm envs (#9519)
- ➕ Add tool approval flow for chat-panel (#9507)
- ✂ Remove input for hidden cells from exports (#9548)
- Parallelize file uploads with bounded concurrency (#9528)
- 👉 Use multipart/form-data for /api/files/create (#9521)
- 👉 Show loading and success toasts for exports (#9509)
- ➕ Add cut cells command (#8019)
- 👍 Allow def declarations within functions (#9379)
- Correlate scratchpad completion with run_id (#9350)
- 👉 Make disconnect indicator clickable to reconnect (#9410)
🛠 🐛 Bug fixes
- Guard SQL ref extraction on sqlglot availability (#9656)
- 🛠 Fix lru_cache(...) resetting when cell is rerun (#9609)
- Skip reload when notebook has git conflict markers (#9626)
- Stream
lazy-polarsoutput viapl(lazy=True)(#9648) - Trigger downloads programmatically to work inside cross-origin iframes (#9649)
- Stdin handling for empty submissions (#9556)
- Avoid pyarrow requirement for polars output in DuckDB engine (#9643)
- Isolate test_project_dependencies from pyproject.toml pollution (#9634)
- ⏪ Restore selection_mode='all' and accept list form (#9630)
- 👍 Allow freezing pandas index columns (#9631)
- Inline
public/images in static HTML export (#9627) - ✂ Remove unused flush_messages plumbing (#9598)
- Migrate remaining background-task sites to asyncio_utils (#9596)
- Normalize dev version in static notebook asset URL (#9592)
- 🌐 JSON-escape > and < in web-component attrs (#9595)
- Render Enum members as str in JSON serializer (#9594)
- Narrow callback deps, drop get_context in cache (#9589)
- ⚡️ Callback bug fixes in cache clear, dataset connections, and model updates (#9588)
- Avoid treating class-like array refs as data primitives (#9569)
- Group kernel streams into KernelStreams; phase-key NotebookCellHooks (#9571)
- Pass theme to register_formatters in pyodide and script runner (#9553)
- 🍎 Use Referrer-Policy same-origin to fix Chrome 147+ Error code 5 on macOS (#9543)
- Extract shared kernel lifecycle for subprocess and pyodide (#9541)
- 🖨 Hide watermark when printing (#9525)
- Markdown singleton to mitigate reported race condition (#9530)
- Contain comm callback errors in mpl_interactive (#9532)
- Disconnect toolbar callbacks on cell rerun (#9531)
- 🛠 Fix overflow and support vertical tabs (#9511)
- 👍 Allow hosts to size-gate downloads (#9510)
- 📄 Detect marimo notebooks with long module docstrings (#9652)
- 🛠 Fix argument splitting on '--' in the command line (#9368)
📚 📚 Documentation
- ⚡️ Update markdown_indentation.md (#9622)
- 💻 Standardize supported dataframe backends across UI elements (#9583)
- Attribution (#9608)
- 💅 Polish tutorial notebooks (#9573)
- ➕ Add detailed docstring for CLI recover command (#9546)
- Note that an added notebook will be downloaded if it's a URL path (#9545)
- 0️⃣ Clarify that marimo run hides source code by default (#9529)
- ➕ Add Mermaid theme customization options (#9478)
- ✂ Remove formatter recommendation section from guide (#9434)...