Marimo Development Skill
Expert guidance for building reactive Python notebooks and applications with marimo.
MCP Integration Overview
marimo exposes MCP tools for notebook inspection, debugging, and linting.
Installation:
# Install as UV tool (recommended) uv tool install "marimo[lsp,recommended,sql,mcp]>=0.18.0"
Start MCP Server:
marimo edit --mcp --no-token --port 2718 --headless
Available MCP Tools:
- •
get_active_notebooks- List open notebook sessions - •
get_lightweight_cell_map- Cell structure preview - •
get_cell_runtime_data- Cell code, errors, variables - •
get_cell_outputs- Visual/console output - •
get_tables_and_variables- DataFrame and variable info - •
get_notebook_errors- Find all errors - •
lint_notebook- Check for issues (breaking, runtime, formatting)
When to use MCP tools:
- •Debugging notebook errors programmatically
- •Inspecting cell dependencies and variables
- •Validating notebooks before deployment
- •Accessing runtime data from running notebooks
See: references/mcp_integration.md for complete guide
Core Principles
Reactive Programming Model
- •Cells automatically re-execute when dependencies change
- •Execution order determined by dependency graph, not cell position
- •UI element changes trigger automatic updates in dependent cells
Best Practices
- •Minimize global variables - Keep namespace clean
- •Write idempotent cells - Same inputs → same outputs
- •Avoid mutations across cells - Mutate only in defining cell
- •Cache expensive computations - Use
@mo.cache - •Encapsulate in functions - Avoid polluting global namespace
Essential UI Elements
1. Slider (Numeric Input)
slider = mo.ui.slider(start=0, stop=100, value=50, label="Threshold")
2. Dropdown (Selection)
dropdown = mo.ui.dropdown(
options=["Option 1", "Option 2", "Option 3"],
value="Option 1",
label="Select"
)
3. Button (Actions)
button = mo.ui.button(
label="Click me",
on_change=lambda v: print(v)
)
4. Table (Data Display)
table = mo.ui.table(data, sortable=True, filterable=True)
5. Text Input
text = mo.ui.text(placeholder="Enter name", label="Name")
Critical Rule: Access .value in a DIFFERENT cell than where element is defined.
# Cell 1: Define slider = mo.ui.slider(0, 100, value=50) slider # Cell 2: Use result = slider.value * 2
See: references/ui_components.md for complete UI catalog
Layout Components
# Vertical stack
mo.vstack([element1, element2], gap=1.5)
# Horizontal stack
mo.hstack([element1, element2], gap=2, widths="equal")
# Tabs
mo.tabs({"Tab 1": content1, "Tab 2": content2})
State Management
# Initialize state
get_count, set_count = mo.state(0)
# Update state
set_count(42) # Set value
set_count(lambda count: count + 1) # Update function
# Use in buttons
increment = mo.ui.button(
label="Increment",
on_change=lambda _: set_count(lambda v: v + 1)
)
# Display
mo.md(f"Count: {get_count()}")
Key Rule: Always assign state getters to global variables.
See: references/state_management.md for advanced patterns
Simple Reactive Pattern
# Cell 1: Control
n_points = mo.ui.slider(10, 100, value=50, label="Points")
n_points
# Cell 2: Generate data
import numpy as np
x = np.random.rand(n_points.value)
y = np.random.rand(n_points.value)
# Cell 3: Visualize (auto-updates)
import altair as alt
chart = alt.Chart({"x": x, "y": y}).mark_circle().encode(x="x", y="y")
chart
See: references/reactive_patterns.md for advanced patterns
Basic App Template
import marimo
app = marimo.App(width="medium", app_title="My App")
@app.cell
def imports():
import marimo as mo
import pandas as pd
return mo, pd
@app.cell
def ui_elements(mo):
slider = mo.ui.slider(0, 100, value=50, label="Value")
slider
return slider,
@app.cell
def use_value(slider, mo):
result = slider.value * 2
mo.md(f"Result: **{result}**")
return result,
if __name__ == "__main__":
app.run()
Deployment Commands
Run Locally
# Development mode marimo edit notebook.py # Production mode (read-only) marimo run notebook.py # As Python script python notebook.py
Export Options
# Static HTML (snapshot) marimo export html notebook.py -o output.html # Interactive WASM (runs in browser) uv run marimo export html-wasm notebook.py -o output.html # Editable WASM uv run marimo export html-wasm notebook.py -o output.html --mode edit # Script marimo export script notebook.py -o script.py
WASM exports:
- •✅ Fully interactive, no server needed
- •✅ Deploy to GitHub Pages, Netlify, Vercel
- •⚠️ Limited to Pyodide-compatible packages
- •⚠️ Must be served over HTTP
See: references/deployment.md for full deployment guide
Optimization
# Cache expensive operations
@mo.cache
def expensive_computation(params):
return results
# Lazy rendering
mo.lazy(mo.ui.table(large_data))
# Memory cleanup
large_object = load_data()
process(large_object)
del large_object
Common Pitfalls
1. Accessing UI Value in Same Cell
# ❌ WRONG slider = mo.ui.slider(0, 100) result = slider.value # ERROR # ✅ CORRECT: Use different cells
2. Mutating Across Cells
# ❌ WRONG # Cell 1: numbers = [1, 2, 3] # Cell 2: numbers.append(4) # ✅ CORRECT # Cell 1: numbers = [1, 2, 3] # Cell 2: extended = numbers + [4]
3. State Without Assignment
# ❌ WRONG: Local scope def create(): return mo.state(0) # ✅ CORRECT: Global scope get_count, set_count = mo.state(0)
Reference Documentation
UI Components: references/ui_components.md
- •Complete catalog of UI elements
- •Layout components
- •Dynamic collections
- •Embedding UI in markdown
Reactive Patterns: references/reactive_patterns.md
- •Task management
- •Periodic updates
- •Dependent dropdowns
- •Data filtering pipelines
- •Real-time validation
State Management: references/state_management.md
- •Basic state usage
- •Complex state objects
- •Batch updates
- •State patterns (undo/redo, loading)
- •Debugging state
Deployment: references/deployment.md
- •Local development
- •Export formats (HTML, WASM, script)
- •Docker, Kubernetes, cloud deployment
- •Performance optimization
- •Security considerations
MCP Integration: references/mcp_integration.md
- •marimo as MCP server
- •marimo as MCP client
- •marimo-docs tools
- •Integration examples
- •Security best practices
Example Templates
Basic Dashboard: examples/basic_dashboard.py
- •Simple dashboard with UI controls
- •Data processing and filtering
- •Reactive visualization
- •Summary metrics
Task Manager: examples/task_manager.py
- •State management with tasks
- •Button callbacks
- •Dynamic UI updates
- •Form-like interactions
Reactive Visualization: examples/reactive_viz.py
- •Interactive scatter plot with selection
- •Linked visualizations
- •Statistics panel
- •Multiple chart types
Cross-Skill Integration
MLflow Experiment Console
Build interactive MLflow dashboards:
import marimo as mo
import mlflow
# Experiment selector
experiments = mlflow.search_experiments()
exp_dropdown = mo.ui.dropdown(
options={e.name: e.experiment_id for e in experiments},
label="Experiment"
)
# In another cell: display runs
runs = mlflow.search_runs(experiment_ids=[exp_dropdown.value])
mo.ui.table(runs[["run_id", "metrics.loss", "params.learning_rate"]])
PINA Training Dashboard
Interactive physics-informed neural network training:
import marimo as mo
from pina import Trainer
from pina.solver import PINN
# Hyperparameter controls
epochs = mo.ui.slider(100, 5000, value=1000, label="Epochs")
lr = mo.ui.number(value=0.001, label="Learning Rate")
train_btn = mo.ui.run_button(label="Train")
# Training cell
if train_btn.value:
trainer = Trainer(solver, max_epochs=epochs.value)
trainer.train()
mo.output.replace(plot_solution(solver))
Using context7 for Documentation
Query up-to-date marimo documentation directly:
# context7 Library IDs (no resolve needed):
# - /marimo-team/marimo (official docs, 2413 snippets)
# - /llmstxt/marimo_io_llms_txt (llms.txt, 7417 snippets)
# Example: query-docs("/marimo-team/marimo", "mo.ui.table parameters")
When to Use This Skill
✅ Use marimo when:
- •Building interactive data dashboards
- •Creating reproducible notebooks
- •Deploying notebooks as web apps
- •Need automatic reactivity
- •Want git-friendly format
❌ Don't use marimo when:
- •Need traditional Jupyter format
- •Require specific Jupyter extensions
- •Working with large Jupyter codebases
Resources
- •Documentation: https://docs.marimo.io
- •GitHub: https://github.com/marimo-team/marimo
- •Examples: https://marimo.io/gallery