marimo-notebook
Skill4 starsChanged yesterdayMITView on GitHub
Write a marimo notebook in a Python file in the right format.
3 other projects use a version of this, 1 of them edited.
Adopted by
Most recently taken up by
- sshtomar/claude-skillstheir own version, first seen May 27, 2026
- CodingKaiser/kaiser-skillsedited, first seen Apr 22, 2026
- marimo-team/skillsword for word, first seen Mar 4, 2026
Other versions3 projects use a version of this.
Word for word · 1
- marimo-team/skills★ 174100% same
Edited · 1
- CodingKaiser/kaiser-skills★ 6100% same
Wrote their own version · 1
- sshtomar/claude-skills★ 0same name
How matches are found. Word for word: the exact same text. Edited: shares passages with this file (“99% same” means 99% of its five-word phrases also appear here; 10% or more counts). Their own version: similar meaning, or, weakest, the same name. We can’t tell which project had it first. Projects are counted among the 200 most-starred candidates, and mentions are links to the repository we found, up to 50 per site, so both counts are a floor.
In this repository58 other files it gives its agents.
- AGENTS.mdAGENTS.md
- CLAUDE.mdCLAUDE.md
- anywidget-generatorSkill
- brandkitSkill
- design-taste-frontendSkill
- diagram-designSkill
- docxSkill
- frontend-designSkill
- full-output-enforcementSkill
- gpt-tasteSkill
- grill-meSkill
- high-end-visual-designSkill
- imagegen-frontend-mobileSkill
- imagegen-frontend-webSkill
- image-to-codeSkill
- impeccableSkill
- implement-paper-autoSkill
- implement-paperSkill
- industrial-brutalist-uiSkill
- jupyter-to-marimoSkill
- minimalist-uiSkill
- pdfSkill
- postrboardSkill
- pptxSkill
- redesign-existing-projectsSkill
- skill-creatorSkill
- stitch-design-tasteSkill
- streamlit-to-marimoSkill
- xlsxSkill
- brandkitSkill
- design-taste-frontendSkill
- full-output-enforcementSkill
- gpt-tasteSkill
- high-end-visual-designSkill
- imagegen-frontend-mobileSkill
- imagegen-frontend-webSkill
- image-to-codeSkill
- impeccableSkill
- industrial-brutalist-uiSkill
- minimalist-uiSkill
- redesign-existing-projectsSkill
- stitch-design-tasteSkill
- network-flowSkill
- create-lib-docsSkill
- artwallbgSkill
- commentdropSkill
- newsletter-aiSkill
- prodigySkill
- scrolls-explainerSkill
- scrolls-helpSkill
- scrolls-hideSkill
- scrolls-removeSkill
- scrolls-restoreSkill
- scrolls-setupSkill
- scrolls-unhideSkill
- scrolls-updateSkill
- stata-recipesSkill
- dynamic-promo-videoSkill
The file
We split this skill into the rules it gives an agent
11 rules. About 0 are common, 6 are distinctive, and 5 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈6
Distinctive · estimate
This author's own choices. Worth a look.
5
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Very specific: line 79
Use mo.app_meta().mode == "script" to detect CLI vs interactive:
- Distinctive: line 90
Show all UI elements always: Only change the data source in script mode.
- Very specific: line 94
Don't wrap everything in if not is_script_mode conditionals
- Distinctive: line 95
Don't use try/except for normal control flow
- Distinctive: line 173
Don't wrap code in try/except blocks unless you're handling a specific, expected exception.
- Distinctive: line 194
Only use try/except when:
- Very specific: line 235
When working on a notebook it is important to check if the notebook can run.
- Distinctive: line 241
Make sure these are checked before handing a notebook back to the user.
- Distinctive: line 247
If the user specifically wants you to use a marimo function, you can locally check the docs via:
- Very specific: line 256
When the optional pytest dependency is present, marimo runs pytest on cells that consist exclusively of test code - i.e.
- Very specific: line 258
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.
≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
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_modeconditionals - 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
returnThe 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
returnPEP 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.
Important: you have a tendency to over-do variables with an underscore prefix. You should only apply this to one or two variables at most. Consider creating a new variable instead of prefixing entire cells in marimo.
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
- For marimo notebooks that run in width=columns SQL.md
- For SQL use in marimo see SQL.md
- For UI elements in marimo UI.md
- For exposing functions/classes as top level imports TOP-LEVEL-IMPORTS.md
- For exporting notebooks (PDF, HTML, markdown, etc.) EXPORTS.md
- For state management and reactivity STATE.md
- For deployment of marimo notebooks DEPLOYMENT.md
- For custom interactive widgets with anywidget ANYWIDGET.md
- For external editing and
--watchmode WATCHING.md - For expensive notebooks (caching, lazy eval, mo.stop) EXPENSIVE.md
- For configuration (pyproject.toml, marimo.toml) CONFIGURATION.md
- For reactivity model (DAG, variable scoping, mutations) REACTIVITY.md
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

