diff --git a/skills/marimo-pair/SKILL.md b/skills/marimo-pair/SKILL.md index 07777ae..1d6e69f 100644 --- a/skills/marimo-pair/SKILL.md +++ b/skills/marimo-pair/SKILL.md @@ -250,6 +250,10 @@ Submit the code that belongs in the cell. - **Define public names intentionally** - use public names for values later cells should reference. Use private `_name` bindings or function locals for same-cell intermediates. +- **Define each public name once** - a public name has one owning cell. + Reassigning it in another cell fails with `Multiply-defined names`; edit the + owning cell or give the result a new name. See + [gotchas.md](reference/gotchas.md). - **Run cells deliberately** - `create_cell` and `edit_cell` change structure only. Queue `ctx.run_cell(...)` when the cell should execute. @@ -286,6 +290,6 @@ For designing custom visual or interactive output, see - [execution-context.md](reference/execution-context.md) — scripts, MCP, auth, startup, and shell quoting - [finding-marimo.md](reference/finding-marimo.md) — choosing the right marimo invocation -- [gotchas.md](reference/gotchas.md) — cached module proxies and notebook traps +- [gotchas.md](reference/gotchas.md) — name redefinition, cached module proxies, and notebook traps - [rich-representations.md](reference/rich-representations.md) — custom widgets and visualizations - [notebook-improvements.md](reference/notebook-improvements.md) — improving existing notebooks diff --git a/skills/marimo-pair/reference/gotchas.md b/skills/marimo-pair/reference/gotchas.md index d6e6a22..aee8683 100644 --- a/skills/marimo-pair/reference/gotchas.md +++ b/skills/marimo-pair/reference/gotchas.md @@ -17,11 +17,33 @@ mo.ui.table(_df) # NameError: name '_df' is not defined **Fix:** Either merge both into one cell, or use a non-private name (`df`). +## Redefining a public name across cells + +Each public name has one owning cell. Defining it again in another cell fails +with `Multiply-defined names`. This is easy to hit when building a notebook +incrementally — a second cell reassigns `df`, `results`, `data`, etc. + +```python +# Cell A +df = pd.read_csv("data.csv") + +# Cell B — FAILS: df already defined in Cell A +df = df.dropna() # Multiply-defined names: df +``` + +**Fix — pick one:** + +- **Edit the owning cell** if the step belongs there (`ctx.edit_cell`). +- **Use a new name** when later cells need the result (`clean = df.dropna()`). +- **Use a private `_` name** for a throwaway intermediate (`_clean = df.dropna()`). + +`ctx.graph.cells[cid].defs` shows what a cell already owns. + ## Duplicate public imports across cells -marimo enforces single-definition: a public name (like `pd`) can only be -defined in one cell. If two cells both `import pandas as pd`, you get a -`Multiply-defined names` error at validation. +The same single-definition rule applies to imports: a public name (like `pd`) +can only be defined in one cell. If two cells both `import pandas as pd`, you +get a `Multiply-defined names` error at validation. **Fix:** Use a `_` prefix on the second import (`import pandas as _pd`) or consolidate imports into a shared cell. diff --git a/skills/marimo-pair/reference/notebook-improvements.md b/skills/marimo-pair/reference/notebook-improvements.md index c6d8999..c57e966 100644 --- a/skills/marimo-pair/reference/notebook-improvements.md +++ b/skills/marimo-pair/reference/notebook-improvements.md @@ -18,8 +18,14 @@ cells. It's the place for module imports. Consolidating imports here keeps the notebook clean and ensures every cell can rely on those modules being available. -First check if the notebook already has a cell named `"setup"`. If not, -create one and hoist scattered imports into it: +**The setup cell cannot reference other cells' variables.** It runs first, so +it must be self-contained: imports, constants, and definitions that depend only +on each other. Reading a name defined elsewhere (e.g. `df`, a UI element) fails +with `The setup cell cannot have references`. + +First check if the notebook already has a cell named `"setup"`. If not, create +one and hoist scattered imports into it. `name="setup"` auto-positions the cell +first — no `before`/`after` needed: ```python cid = ctx.create_cell('''import polars as pl @@ -29,8 +35,8 @@ import traitlets''', name="setup") ctx.run_cell(cid) ``` -If a setup cell already exists, use `ctx.edit_cell("setup", code=...)` and -`ctx.run_cell("setup")` to modify and re-run it. +If a setup cell already exists, `create_cell(name="setup")` raises `ValueError`; +use `ctx.edit_cell("setup", code=...)` and `ctx.run_cell("setup")` instead. ## Lift reusable functions into their own cells