name: marimo description: Use when working with marimo notebooks — creating, editing, debugging, converting from Jupyter, or pairing with a running marimo server. user-invocable: false
Contents
- Editing and Verification Enforcement
- Key Concepts
- Cell Structure
- Editing Rules
- Core CLI Commands
- Export Commands
- Live Session (marimo-pair)
- Data and Visualization
- Debugging Workflow
- Common Issues
- Additional Resources
Marimo Reactive Notebooks
Marimo is a reactive Python notebook where cells form a DAG and auto-execute on dependency changes. Notebooks are stored as pure .py files.
Editing and Verification Enforcement
IRON LAW #1: NEVER MODIFY CELL DECORATORS OR SIGNATURES
Only edit code INSIDE @app.cell function bodies. This is not negotiable.
NEVER modify:
- Cell decorators (
@app.cell) - Function signatures (
def _(deps):) - Return statements structure (trailing commas required)
ALWAYS verify:
- All used variables are in function parameters
- All created variables are in return statement
- Trailing comma for single returns:
return var,
IRON LAW #2: NO EXECUTION CLAIM WITHOUT OUTPUT VERIFICATION
Before claiming ANY marimo notebook works:
- VALIDATE syntax and structure:
marimo check notebook.py - EXECUTE with outputs:
marimo export ipynb notebook.py -o __marimo__/notebook.ipynb --include-outputs - VERIFY using notebook-debug skill's verification checklist
- CLAIM success only after verification passes
This is not negotiable. Skipping execution and output inspection is NOT HELPFUL — the user gets a notebook that fails when they open it.
Marimo Facts
marimo checkvalidates syntax and structure only — it never executes cells. Claiming a notebook works because check passed is an unverified claim presented as fact.- Reactivity propagates every edit through the DAG: a one-line change re-executes all dependent cells. Verifying only the edited cell misses downstream breakage — counterproductive on its own terms.
- Wrong dependencies or missing returns break reactivity silently: no error at edit time, only a NameError when a dependent cell runs. Validate that all used variables are in params AND all created variables are in returns.
- A variable created but not returned raises NameError in every cell that depends on it.
- Python treats
return varas returning the bare value, which breaks unpacking — single returns require the trailing comma (return var,).
Red Flags — STOP If About To:
- Edit a
@app.celldecorator ordef _(...)signature → STOP. Marimo manages these; edit only the function body. - Claim done after only
marimo check→ STOP. Execution with--include-outputsis required. - Claim the notebook works from reading the code → STOP. Reactive correctness shows only at runtime.
- Define a variable that another cell already defines → STOP. One variable = one cell.
Editing Checklist
Before every marimo edit:
Structure Validation:
- Only edit code INSIDE
@app.cellfunction bodies - Do NOT modify decorators or signatures
- Verify all used variables are in function parameters
- Verify all created variables are in return statement
- Ensure trailing comma used for single returns
- Ensure no variable redefinitions across cells
Syntax Validation:
- Execute
marimo check notebook.py - Verify no syntax errors reported
- Verify no undefined variable warnings
- Verify no redefinition warnings
Runtime Verification:
- Execute with
marimo export ipynb notebook.py -o __marimo__/notebook.ipynb --include-outputs - Verify export succeeded (exit code 0)
- Verify output ipynb exists and is non-empty
- Apply notebook-debug verification checklist
- Verify no tracebacks in any cell
- Verify all cells executed (execution_count not null)
- Verify outputs match expectations
Only after ALL checks pass:
- Claim "notebook works"
Gate Function: Marimo Verification
Follow this sequence for EVERY marimo task:
1. EDIT → Modify code inside @app.cell function bodies only
2. CHECK → marimo check notebook.py
3. EXECUTE → marimo export ipynb notebook.py -o __marimo__/notebook.ipynb --include-outputs
4. INSPECT → Use notebook-debug verification
5. VERIFY → Outputs match expectations
6. CLAIM → "Notebook works" only after all gates passed
NEVER skip verification gates. Marimo's reactivity means changes propagate unpredictably.
Key Concepts
- Reactive execution: Cells auto-update when dependencies change
- No hidden state: Each variable defined in exactly one cell
- Pure Python:
.pyfiles, version control friendly - Cell structure:
@app.celldecorator pattern
Cell Structure
import marimo
app = marimo.App()
@app.cell
def _(pl): # Dependencies as parameters
df = pl.read_csv("data.csv")
return df, # Trailing comma required for single return
@app.cell
def _(df, pl):
summary = df.describe()
filtered = df.filter(pl.col("value") > 0)
return summary, filtered # Multiple returns
Editing Rules
- Edit code INSIDE
@app.cellfunctions only - Never modify cell decorators or function signatures
- Variables cannot be redefined across cells
- All used variables must be returned from their defining cell
- Markdown cells: Always wrap
$in backticks -mo.md("Cost:$50")notmo.md("Cost: $50")
Core CLI Commands
| Command | Purpose |
|---|---|
marimo edit notebook.py |
marimo: Open notebook in browser editor for interactive development |
marimo run notebook.py |
marimo: Run notebook as executable app |
marimo check notebook.py |
marimo: Validate notebook structure and syntax without execution |
marimo convert notebook.ipynb |
marimo: Convert Jupyter notebook to marimo format |
Export Commands
# marimo: Export to ipynb with code only
marimo export ipynb notebook.py -o __marimo__/notebook.ipynb
# marimo: Export to ipynb with outputs (runs notebook first)
marimo export ipynb notebook.py -o __marimo__/notebook.ipynb --include-outputs
# marimo: Export to HTML (runs notebook by default)
marimo export html notebook.py -o __marimo__/notebook.html
# marimo: Export to HTML with auto-refresh on changes (live preview)
marimo export html notebook.py -o __marimo__/notebook.html --watch
Key difference: HTML export runs the notebook by default. ipynb export does NOT - use --include-outputs to run and capture outputs.
Tip: Use __marimo__/ folder for all exports (ipynb, html). The editor can auto-save there.
Live Session (marimo-pair)
For working inside a running marimo notebook kernel — executing code, creating/editing cells, and building notebooks interactively — use the marimo-pair protocol. Full details: marimo-pair/SKILL.md.
Starting a Server
See marimo-pair/reference/finding-marimo.md for the full decision tree. Quick start:
# pixi project (our standard)
pixi run marimo edit notebook.py --no-token --watch
# uv project
uv run marimo edit notebook.py --no-token --watch
# standalone / sandbox
uvx marimo@latest edit notebook.py --no-token --watch --sandbox
Always use --watch so the server detects file edits and reloads automatically. Without it, file changes are invisible to the browser and the user sees stale content.
Always start as a background task (run_in_background) so the server doesn't block the conversation. Do NOT use --headless unless asked — let marimo open the browser.
Discovery and Execution
# Discover running servers
bash ${CLAUDE_SKILL_DIR}/marimo-pair/scripts/discover-servers.sh
# Execute code in the kernel (one-liner)
bash ${CLAUDE_SKILL_DIR}/marimo-pair/scripts/execute-code.sh -c "df.head()"
# Execute code (multiline — use heredoc to avoid shell escaping)
bash ${CLAUDE_SKILL_DIR}/marimo-pair/scripts/execute-code.sh <<'EOF'
import marimo._code_mode as cm
async with cm.get_context() as ctx:
cid = ctx.create_cell("x = 1")
ctx.run_cell(cid)
EOF
Use --port to target a specific server, --session for a specific notebook, --url for remote servers.
Key Concepts
- Scratchpad execution: Code runs in the kernel with all cell variables in scope, but nothing persists between calls. Use this to explore and validate.
- Cell mutations: Use
marimo._code_modewithasync with cm.get_context() as ctx:to create/edit/delete cells and install packages. Allctx.*methods are synchronous — do NOT await them. - Cells are not auto-executed:
create_cellandedit_cellare structural only — callctx.run_cell(cid)to execute. - Install packages via
ctx.install_packages(), notuv addorpip. - NEVER write to the
.pyfile directly while a session is running — the kernel owns it.
marimo-pair References
marimo-pair/reference/finding-marimo.md— How to find and invoke the right marimo binarymarimo-pair/reference/gotchas.md— Cached module proxies and other trapsmarimo-pair/reference/rich-representations.md— Custom anywidgets,_display_(), Arrow IPC for large datamarimo-pair/reference/notebook-improvements.md— Setup cells, lifting functions,mo.persistent_cache
Data and Visualization
- Prefer polars over pandas for performance
- Use
mo.uifor interactive widgets - SQL cells:
mo.sql(df, "SELECT * FROM df") - Display markdown:
mo.md("# Heading")
Debugging Workflow
1. Pre-execution validation:
# scripts: Validate notebook syntax and cell structure
scripts/check_notebook.sh notebook.py
Runs syntax check, marimo validation, and cell structure overview in one command.
2. Runtime errors: Export with outputs, then use notebook-debug skill:
# marimo: Export to ipynb with outputs for inspection
marimo export ipynb notebook.py -o __marimo__/notebook.ipynb --include-outputs
Common Issues
| Issue | Fix |
|---|---|
| Variable redefinition | Rename one variable or merge cells |
| Circular dependency | Break cycle by merging or restructuring |
| Missing return | Add return var, with trailing comma |
| Import not available | Ensure import cell returns the module |
Additional Resources
Reference Files
For detailed patterns and advanced techniques, consult:
references/reactivity.md- DAG execution, variable rules, dependency detection patternsreferences/debugging.md- Error patterns, runtime debugging, environment-specific issuesreferences/widgets.md- Interactive UI components and mo.ui patternsreferences/sql.md- SQL cells and database integration techniquesmarimo-pair/reference/finding-marimo.md- How to find and invoke marimo across project typesmarimo-pair/reference/gotchas.md- Cached module proxies (e.g., polars + pyarrow mid-session)marimo-pair/reference/rich-representations.md- Custom anywidgets, Arrow IPC,_display_()protocolmarimo-pair/reference/notebook-improvements.md- Setup cells, lifting functions,mo.persistent_cache
Examples
Working examples available in examples/:
examples/basic_notebook.py- Minimal marimo notebook structureexamples/data_analysis.py- Data loading, filtering, and visualization patternsexamples/interactive_widgets.py- Interactive UI component usage
Scripts
Validation and live-session utilities:
scripts/check_notebook.sh- Primary validation: syntax check, marimo validation, cell structure overviewscripts/get_cell_map.py- Extract cell metadata (invoked by check_notebook.sh)marimo-pair/scripts/discover-servers.sh- Find running marimo serversmarimo-pair/scripts/execute-code.sh- Execute code in a running marimo kernel
Related Skills
notebook-debug- Debugging executed ipynb files with tracebacks and output inspectionmarimo-pair/SKILL.md- Full marimo-pair protocol for live kernel interaction