Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion skills/marimo-pair/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.

Expand Down Expand Up @@ -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
28 changes: 25 additions & 3 deletions skills/marimo-pair/reference/gotchas.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Comment on lines 48 to 49
Expand Down
14 changes: 10 additions & 4 deletions skills/marimo-pair/reference/notebook-improvements.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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

Expand Down