Agent Skillskoaning/gitcharts › marimo-notebook

marimo-notebook

GitHub

指导如何编写符合规范的 marimo Python 笔记本,涵盖脚本头、单元格装饰器使用及运行方式。新增关键原则:保持简单,始终展示 UI 元素,仅在脚本模式下切换数据源而非包裹条件逻辑。

.agents/skills/marimo-notebook/SKILL.md koaning/gitcharts

触发场景

用户要求创建或编写 marimo notebook 用户询问如何在 marimo 中处理交互与脚本模式

安装

npx skills add koaning/gitcharts --skill marimo-notebook -g -y
更多选项

非标准路径

npx skills add https://github.com/koaning/gitcharts/tree/main/.agents/skills/marimo-notebook -g -y

不安装直接使用

npx skills use koaning/gitcharts@marimo-notebook

指定 Agent (Claude Code)

npx skills add koaning/gitcharts --skill marimo-notebook -a claude-code -g -y

安装 repo 全部 skill

npx skills add koaning/gitcharts --all -g -y

预览 repo 内 skill

npx skills add koaning/gitcharts --list

SKILL.md

Frontmatter
{
    "name": "marimo-notebook",
    "description": "Write a marimo notebook in a Python file in the right format."
}

Notes for marimo Notebooks

marimo uses Python to create notebooks, unlike Jupyter which uses JSON. Here's an example notebook:

# /// script
# dependencies = [
#     "marimo",
#     "numpy==2.4.3",
# ]
# requires-python = ">=3.14"
# ///

import marimo

__generated_with = "0.20.4"
app = marimo.App(width="medium")


@app.cell
def _():
    import marimo as mo
    import numpy as np

    return mo, np


@app.cell
def _():
    print("hello world")
    return


@app.cell
def _(np, slider):
    np.array([1,2,3]) + slider.value
    return


@app.cell
def _(mo):
    slider = mo.ui.slider(1, 10, 1, label="number to add")
    slider
    return (slider,)


@app.cell
def _():
    return


if __name__ == "__main__":
    app.run()

Notice how the notebook is structured with functions can represent cell contents. Each cell is defined with the @app.cell decorator and the inputs/outputs of the function are the inputs/outputs of the cell. marimo usually takes care of the dependencies between cells automatically.

Running Marimo Notebooks

# Run as script (non-interactive, for testing)
uv run <notebook.py>

# Run interactively in browser
uv run marimo run <notebook.py>

# Edit interactively
uv run marimo edit <notebook.py>

Script Mode Detection

Use mo.app_meta().mode == "script" to detect CLI vs interactive:

@app.cell
def _(mo):
    is_script_mode = mo.app_meta().mode == "script"
    return (is_script_mode,)

Key Principle: Keep It Simple

Show all UI elements always. Only change the data source in script mode.

  • Sliders, buttons, widgets should always be created and displayed
  • In script mode, just use synthetic/default data instead of waiting for user input
  • Don't wrap everything in if not is_script_mode conditionals
  • Don't use try/except for normal control flow

Good Pattern

# Always show the widget
@app.cell
def _(ScatterWidget, mo):
    scatter_widget = mo.ui.anywidget(ScatterWidget())
    scatter_widget
    return (scatter_widget,)

# Only change data source based on mode
@app.cell
def _(is_script_mode, make_moons, scatter_widget, np, torch):
    if is_script_mode:
        # Use synthetic data for testing
        X, y = make_moons(n_samples=200, noise=0.2)
        X_data = torch.tensor(X, dtype=torch.float32)
        y_data = torch.tensor(y)
        data_error = None
    else:
        # Use widget data in interactive mode
        X, y = scatter_widget.widget.data_as_X_y
        # ... process data ...
    return X_data, y_data, data_error

# Always show sliders - use their .value in both modes
@app.cell
def _(mo):
    lr_slider = mo.ui.slider(start=0.001, stop=0.1, value=0.01)
    lr_slider
    return (lr_slider,)

# Auto-run in script mode, wait for button in interactive
@app.cell
def _(is_script_mode, train_button, lr_slider, run_training, X_data, y_data):
    if is_script_mode:
        # Auto-run with slider defaults
        results = run_training(X_data, y_data, lr=lr_slider.value)
    else:
        # Wait for button click
        if train_button.value:
            results = run_training(X_data, y_data, lr=lr_slider.value)
    return (results,)

State and Reactivity

Variables between cells define the reactivity of the notebook for 99% of the use-cases out there. No special state management needed. Don't mutate objects across cells (e.g., my_list.append()); create new objects instead. Avoid mo.state() unless you need bidirectional UI sync or accumulated callback state. See STATE.md for details.

Don't Guard Cells with if Statements

Marimo's reactivity means cells only run when their dependencies are ready. Don't add unnecessary guards:

# BAD - the if statement prevents the chart from showing
@app.cell
def _(plt, training_results):
    if training_results:  # WRONG - don't do this
        fig, ax = plt.subplots()
        ax.plot(training_results['losses'])
        fig
    return

# GOOD - let marimo handle the dependency
@app.cell
def _(plt, training_results):
    fig, ax = plt.subplots()
    ax.plot(training_results['losses'])
    fig
    return

The cell won't run until training_results has a value anyway.

Don't Use try/except for Control Flow

Don't wrap code in try/except blocks unless you're handling a specific, expected exception. Let errors surface naturally.

# BAD - hiding errors behind try/except
@app.cell
def _(scatter_widget, np, torch):
    try:
        X, y = scatter_widget.widget.data_as_X_y
        X = np.array(X, dtype=np.float32)
        # ...
    except Exception as e:
        return None, None, f"Error: {e}"

# GOOD - let it fail if something is wrong
@app.cell
def _(scatter_widget, np, torch):
    X, y = scatter_widget.widget.data_as_X_y
    X = np.array(X, dtype=np.float32)
    # ...

Only use try/except when:

  • You're handling a specific, known exception type
  • The exception is expected in normal operation (e.g., file not found)
  • You have a meaningful recovery action

Cell Output Rendering

Marimo only renders the final expression of a cell. Indented or conditional expressions won't render:

# BAD - indented expression won't render
@app.cell
def _(mo, condition):
    if condition:
        mo.md("This won't show!")  # WRONG - indented
    return

# GOOD - final expression renders
@app.cell
def _(mo, condition):
    result = mo.md("Shown!") if condition else mo.md("Also shown!")
    result  # This renders because it's the final expression
    return

Marimo Variable Naming

Variables in for loops that would conflict across cells need underscore prefix:

# Use _name, _model to make them cell-private
for _name, _model in items:
    ...

Hard rule: never underscore-prefix imports. If multiple cells need a module, let marimo share it via the return tuple. Only use _prefix for loop variables or temporaries that would genuinely collide with another cell's named outputs. Overdoing underscores (e.g. import re as _re, _result = ...) makes code deeply unpythonic and harder to read for zero benefit.

PEP 723 Dependencies

Notebooks created via marimo edit --sandbox have these dependencies added to the top of the file automatically but it is a good practice to make sure these exist when creating a notebook too:

# /// script
# requires-python = ">=3.12"
# dependencies = [
#     "marimo",
#     "torch>=2.0.0",
# ]
# ///

marimo check

When working on a notebook it is important to check if the notebook can run. That's why marimo provides a check command that acts as a linter to find common mistakes.

uvx marimo check <notebook.py>

Make sure these are checked before handing a notebook back to the user.

api docs

If the user specifically wants you to use a marimo function, you can locally check the docs via:

uv --with marimo run python -c "import marimo as mo; help(mo.ui.form)"

tests

By default, marimo discovers and executes tests inside your notebook. When the optional pytest dependency is present, marimo runs pytest on cells that consist exclusively of test code - i.e. functions whose names start with test_. If the user asks you to add tests, make sure to add the pytest dependency is added and that there is a cell that contains only test code.

For more information on testing with pytest see PYTEST.md

Once tests are added, you can run pytest from the commandline on the notebook to run pytest.

pytest <notebook.py>

Additional resources

版本历史

  • 69aec0c 当前 2026-07-25 11:01

同 Skill 集合

.agents/skills/marimo-batch/SKILL.md

元信息

文件数
0
版本
69aec0c
Hash
269daa27
收录时间
2026-07-25 11:01

首页 - Wiki
Copyright © 2011-2026 iteam. Current version is 2.155.2. UTC+08:00, 2026-09-03 14:25
浙ICP备14020137号-1 $访客地图$