marimo

star 16

Use when working with marimo notebooks — creating, editing, debugging, converting from Jupyter, or pairing with a running marimo server.

edwinhu By edwinhu schedule Updated 4/21/2026

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

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:

  1. VALIDATE syntax and structure: marimo check notebook.py
  2. EXECUTE with outputs: marimo export ipynb notebook.py -o __marimo__/notebook.ipynb --include-outputs
  3. VERIFY using notebook-debug skill's verification checklist
  4. 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 check validates 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 var as returning the bare value, which breaks unpacking — single returns require the trailing comma (return var,).

Red Flags — STOP If About To:

  • Edit a @app.cell decorator or def _(...) signature → STOP. Marimo manages these; edit only the function body.
  • Claim done after only marimo check → STOP. Execution with --include-outputs is 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.cell function 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: .py files, version control friendly
  • Cell structure: @app.cell decorator 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.cell functions 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") not mo.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_mode with async with cm.get_context() as ctx: to create/edit/delete cells and install packages. All ctx.* methods are synchronous — do NOT await them.
  • Cells are not auto-executed: create_cell and edit_cell are structural only — call ctx.run_cell(cid) to execute.
  • Install packages via ctx.install_packages(), not uv add or pip.
  • NEVER write to the .py file 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 binary
  • marimo-pair/reference/gotchas.md — Cached module proxies and other traps
  • marimo-pair/reference/rich-representations.md — Custom anywidgets, _display_(), Arrow IPC for large data
  • marimo-pair/reference/notebook-improvements.md — Setup cells, lifting functions, mo.persistent_cache

Data and Visualization

  • Prefer polars over pandas for performance
  • Use mo.ui for 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 patterns
  • references/debugging.md - Error patterns, runtime debugging, environment-specific issues
  • references/widgets.md - Interactive UI components and mo.ui patterns
  • references/sql.md - SQL cells and database integration techniques
  • marimo-pair/reference/finding-marimo.md - How to find and invoke marimo across project types
  • marimo-pair/reference/gotchas.md - Cached module proxies (e.g., polars + pyarrow mid-session)
  • marimo-pair/reference/rich-representations.md - Custom anywidgets, Arrow IPC, _display_() protocol
  • marimo-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 structure
  • examples/data_analysis.py - Data loading, filtering, and visualization patterns
  • examples/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 overview
  • scripts/get_cell_map.py - Extract cell metadata (invoked by check_notebook.sh)
  • marimo-pair/scripts/discover-servers.sh - Find running marimo servers
  • marimo-pair/scripts/execute-code.sh - Execute code in a running marimo kernel

Related Skills

  • notebook-debug - Debugging executed ipynb files with tracebacks and output inspection
  • marimo-pair/SKILL.md - Full marimo-pair protocol for live kernel interaction
Install via CLI
npx skills add https://github.com/edwinhu/workflows --skill marimo
Repository Details
star Stars 16
call_split Forks 5
navigation Branch main
article Path SKILL.md
More from Creator