Using your own editor - marimo (original) (raw)
While we recommend using the marimo editor, we understand that you may prefer to use your own. marimo provides a--watch flag that watches your notebook file for changes, syncing them to the marimo editor or running application. This lets you edit your notebook using an editor of your choice, like neovim, VSCode, Cursor, or PyCharm, and have the changes automatically reflected in your browser.
Prefer VS Code/Cursor? Try our extension!
This guide teaches you how to use marimo with arbitrary text editors. If you use VS Code or Cursor, you might prefer using our extension, which provides a first-class experience for editing and running marimo notebooks.
marimo's file format¶
marimo stores notebooks as Python files. Cells are stored as functions, decorated with@app.cell; you can optionally give cells names in the editor UI or by editing the notebook file.
[](#%5F%5Fcodelineno-0-1)@app.cell [](#%5F%5Fcodelineno-0-2)def memorable_cell_name(auto, determined, references): # signature denotes cell references [](#%5F%5Fcodelineno-0-3) computed_value = auto + determined + references [](#%5F%5Fcodelineno-0-4) "hello!" # final statement is the visual output [](#%5F%5Fcodelineno-0-5) return computed_value # return denotes cell definitions
Run marimo tutorial fileformat at the command line for a full guide.
Cell signature and returns
Don't worry about maintaining the signatures of cells and their return values; marimo will handle this for you.
Exposing functions and classes top-level¶
You can expose top-level functions and classes in your notebook, so that other Python modules can import them:
[](#%5F%5Fcodelineno-1-1)from my_notebook import my_function, MyClass
Top-level functions are added to a notebook using the @app.functiondecorator, and classes with @app.class_definition; these appear in your notebook as cells with just a function or class definition. These functions and classes must be pure, closing over only other pure functions and classes, or imports and constants defined in an app.setup with block.
Here is a complete example that you can copy/paste and run locally:
[](#%5F%5Fcodelineno-2-1)import marimo [](#%5F%5Fcodelineno-2-2) [](#%5F%5Fcodelineno-2-3)app = marimo.App() [](#%5F%5Fcodelineno-2-4) [](#%5F%5Fcodelineno-2-5)with app.setup: [](#%5F%5Fcodelineno-2-6) # These symbols can be used by top-level functions and classes [](#%5F%5Fcodelineno-2-7) # (as well as by regular cells) [](#%5F%5Fcodelineno-2-8) import numpy as np [](#%5F%5Fcodelineno-2-9) [](#%5F%5Fcodelineno-2-10) CONSTANT: int = 1 [](#%5F%5Fcodelineno-2-11) [](#%5F%5Fcodelineno-2-12)@app.function [](#%5F%5Fcodelineno-2-13)def my_function(x: np.ndarray): [](#%5F%5Fcodelineno-2-14) return np.mean(x) + CONSTANT [](#%5F%5Fcodelineno-2-15) [](#%5F%5Fcodelineno-2-16)@app.class_definition [](#%5F%5Fcodelineno-2-17)class MyClass: [](#%5F%5Fcodelineno-2-18) ... [](#%5F%5Fcodelineno-2-19) [](#%5F%5Fcodelineno-2-20)@app.cell [](#%5F%5Fcodelineno-2-21)def _(): [](#%5F%5Fcodelineno-2-22) my_function(np.random.randn(2, 2)) [](#%5F%5Fcodelineno-2-23) return [](#%5F%5Fcodelineno-2-24) [](#%5F%5Fcodelineno-2-25)if __name__ == "__main__": [](#%5F%5Fcodelineno-2-26) app.run()
For more details see the guide on reusable functions and classes.
Types and autocompletion¶
Add type hints to your variables, and marimo will carry over these type hints to cells where these variables are used. This, combined with importing modules in the setup cell (see below for an example), makes it possible for your editor to give completions on the references of your cell.
For example:
[](#%5F%5Fcodelineno-3-1)# setup cell [](#%5F%5Fcodelineno-3-2)import numpy as np [](#%5F%5Fcodelineno-3-3) [](#%5F%5Fcodelineno-3-4)# cell 1 [](#%5F%5Fcodelineno-3-5)x: np.ndarray [](#%5F%5Fcodelineno-3-6) [](#%5F%5Fcodelineno-3-7)# cell 2 [](#%5F%5Fcodelineno-3-8)np.mean(x)
will be serialized as
[](#%5F%5Fcodelineno-4-1)import marimo [](#%5F%5Fcodelineno-4-2) [](#%5F%5Fcodelineno-4-3)app = marimo.App() [](#%5F%5Fcodelineno-4-4) [](#%5F%5Fcodelineno-4-5)with app.setup: [](#%5F%5Fcodelineno-4-6) import numpy as np [](#%5F%5Fcodelineno-4-7) [](#%5F%5Fcodelineno-4-8)@app.cell [](#%5F%5Fcodelineno-4-9)def _(): [](#%5F%5Fcodelineno-4-10) x: np.ndarray [](#%5F%5Fcodelineno-4-11) return x, [](#%5F%5Fcodelineno-4-12) [](#%5F%5Fcodelineno-4-13)@app.cell [](#%5F%5Fcodelineno-4-14)def _(x: np.ndarray): [](#%5F%5Fcodelineno-4-15) np.mean(x) [](#%5F%5Fcodelineno-4-16) [](#%5F%5Fcodelineno-4-17)if __name__ == "__main__": [](#%5F%5Fcodelineno-4-18) app.run()
As markdown¶
Markdown File format tutorial
Run marimo tutorial markdown-format at the command line for a full guide.
marimo notebooks can also be stored as Markdown files. This is a good option for prose heavy text, and can be easy to navigate and edit in external editors. To convert a marimo notebook to markdown, use
[](#%5F%5Fcodelineno-5-1)marimo export md notebook.py -o notebook.md
at the command-line, or rename your file to have an .md extension in the notebook editor.
marimo conforms to standard markdown document format, and will render most places like Github. Metadata in this file format is saved in the frontmatter, which marimo may use for information likesandboxing, and the marimo version. All other fields are kept, but ignored.
For execution, marimo extracts code fences that contain marimo in braces. For instance python {marimo}, {marimo} or {.marimo .python}. The marimo editor uses python {.marimo} which is Pandoc compatible, and correctly processed by text highlighters.
[](#%5F%5Fcodelineno-6-2)title: My Notebook
[](#%5F%5Fcodelineno-6-3)marimo-version: 0.0.0
[](#%5F%5Fcodelineno-6-4)description: A notebook with a description
[](#%5F%5Fcodelineno-6-5)---
[](#%5F%5Fcodelineno-6-6)
[](#%5F%5Fcodelineno-6-7)# Just a notebook
[](#%5F%5Fcodelineno-6-8)
[](#%5F%5Fcodelineno-6-9)```python {.marimo}
[](#%5F%5Fcodelineno-6-10)print("Hello World!")
[](#%5F%5Fcodelineno-6-11)```marimo's markdown format can be used with a mkdocs plugin andQuarto.
Note that the markdown format is not as fully featured as the Python format. Reactive tests will not work, markdown notebooks cannot be imported or used as a library, and they cannot be run as scripts.
Watching for changes to your notebook¶
Install watchdog for better file watching
For better performance, install watchdog. Without watchdog, marimo resorts to polling.
Watch works best with autosave
Verify your settings in User Settings > Editor > Autosave > Autosave enabled
marimo edit --watch¶
When you run marimo edit with the --watch flag, the marimo server will open your notebook in the browser and watch the underlying notebook file for changes. When you make changes to the notebook file, they will be streamed to the marimo editor in the browser.
By default, synced code will not be executed automatically, with cells marked as stale instead. Run all stale cells with the marimo editor's "Run" button, or the runStale hotkey, to see the new outputs.
If you want to run all affected cells automatically when you save, change theruntime config in your pyproject.toml file.
[](#%5F%5Fcodelineno-7-1)[tool.marimo.runtime] [](#%5F%5Fcodelineno-7-2)watcher_on_save = "autorun"
marimo run --watch¶
When you run marimo run with the --watch flag, whenever the file watcher detects a change to the notebook file, the application will be refreshed. The browser will trigger a page refresh to ensure your notebook starts from a fresh state.
Watching for changes to other modules¶
marimo can also watch for changes to Python modules that your notebook imports, letting you edit auxiliary Python files in your own editor as well. Learn how to enable this feature in our Module Autoreloading Guide
Watching for data changes¶
marimo supports watching data files and automatically refreshing cells that depend on them using mo.watch.file and [mo.watch.directory][marimo.watch.directory].
Learn more in the watch API documentation.
Hot-reloading WebAssembly notebooks¶
Follow these steps to develop a notebook using your own editor while previewing it as a WebAssembly notebook in the browser. This lets you take advantage of local development tools while seeing the notebook as it appears when deployed as a WebAssembly notebook.
[](#%5F%5Fcodelineno-8-1)# in one terminal, start a watched edit (or run) session [](#%5F%5Fcodelineno-8-2)marimo edit notebook.py --watch [](#%5F%5Fcodelineno-8-3) [](#%5F%5Fcodelineno-8-4)# in another terminal [](#%5F%5Fcodelineno-8-5)marimo export html-wasm notebook.py -o output_dir --watch [](#%5F%5Fcodelineno-8-6) [](#%5F%5Fcodelineno-8-7)# in a third terminal, serve the WASM application [](#%5F%5Fcodelineno-8-8)cd path/to/output_dir [](#%5F%5Fcodelineno-8-9)python -m http.server # or a server that watches for changes