{"owner":"marimo-team","repo":"marimo","hasSkills":true,"totalSkillsCount":55,"totalTokensCount":24362,"categories":["project-spec","anthropic-skill","root-instruction","copilot-instructions","plugin-manifest"],"hasMcp":false,"mcpConfig":null,"found":["DESIGN.md","packages/llm-info/skills/SKILL.md","AGENTS.md",".github/copilot-instructions.md","marimo/_server/ai/skills/marimo-pair/SKILL.md","development_docs/prompts.md","frontend/AGENTS.md","packages/client/TRANSPORTS.md","marimo/AGENTS.md","packages/client/README.md","packages/client/REDUCERS.md","packages/client/package.json","packages/client/tsconfig.build.json","packages/client/tsconfig.json","packages/llm-info/AGENTS.md","packages/llm-info/README.md","packages/llm-info/package.json","packages/llm-info/tsconfig.json","packages/lsp/package.json","packages/lsp/tsconfig.json","packages/lsp/turbo.json","packages/openapi/api.yaml","packages/openapi/package.json","packages/openapi/tsconfig.json","packages/pytest_changed/README.md","packages/smart-cells/README.md","packages/smart-cells/package.json","packages/smart-cells/tsconfig.json","packages/ts-config/README.md","packages/ts-config/base.json","packages/ts-config/library.json","packages/ts-config/package.json","examples/ai/tools/README.md","docs/guides/lint_rules/rules/branch_expression.md","docs/guides/lint_rules/rules/cycle_dependencies.md","docs/guides/lint_rules/rules/empty_cells.md","docs/guides/lint_rules/rules/general_formatting.md","docs/guides/lint_rules/rules/incompatible_import.md","docs/guides/lint_rules/rules/incompatible_package.md","docs/guides/lint_rules/rules/invalid_syntax.md","docs/guides/lint_rules/rules/markdown_indentation.md","docs/guides/lint_rules/rules/misc_log_capture.md","docs/guides/lint_rules/rules/multiple_definitions.md","docs/guides/lint_rules/rules/parse_stderr.md","docs/guides/lint_rules/rules/parse_stdout.md","docs/guides/lint_rules/rules/private_import_alias.md","docs/guides/lint_rules/rules/reusable_definition_order.md","docs/guides/lint_rules/rules/self_import.md","docs/guides/lint_rules/rules/setup_cell_dependencies.md","docs/guides/lint_rules/rules/sql_parse_error.md","docs/guides/lint_rules/rules/unparsable_cells.md","docs/guides/lint_rules/rules/unsafe_system_call.md","marimo/_server/ai/skills/marimo-pair/references/gotchas.md","marimo/_server/ai/skills/marimo-pair/references/notebook-improvements.md","marimo/_server/ai/skills/marimo-pair/references/rich-representations.md"],"skills":{"DESIGN.md":"---\nversion: alpha\nname: marimo\ndescription: Design system for marimo, a reactive Python notebook for reproducible, git-friendly, deployable work.\ncolors:\n  background: \"#FFFFFF\"\n  background-dark: \"#181C1A\"\n  foreground: \"#0F172A\"\n  foreground-dark: \"#ECEEED\"\n  surface-muted: \"#F1F5F9\"\n  surface-muted-dark: \"#020303\"\n  muted-foreground: \"#64748B\"\n  muted-foreground-dark: \"#AAB2AF\"\n  popover: \"#FFFFFF\"\n  popover-dark: \"#252927\"\n  popover-foreground: \"#0F172A\"\n  popover-foreground-dark: \"#AAB2AF\"\n  card: \"#FFFFFF\"\n  card-dark: \"#252927\"\n  card-foreground: \"#0F172A\"\n  card-foreground-dark: \"#C0C6C3\"\n  border: \"#E2E8F0\"\n  border-dark: \"#3B403E\"\n  input: \"#A3A3A3\"\n  input-dark: \"#474C4A\"\n  primary: \"#0880EA\"\n  primary-dark: \"#28879F\"\n  on-primary: \"#F8FAFC\"\n  on-primary-dark: \"#B6ECF7\"\n  secondary: \"#F1F5F9\"\n  secondary-dark: \"#ECEEED\"\n  on-secondary: \"#0F172A\"\n  on-secondary-dark: \"#252927\"\n  accent: \"#EDF6FF\"\n  accent-dark: \"#1D5B6A\"\n  on-accent: \"#0B68CB\"\n  on-accent-dark: \"#B6ECF7\"\n  ring: \"#94A3B8\"\n  ring-dark: \"#2870BD\"\n  destructive: \"#E5484D\"\n  destructive-dark: \"#72232D\"\n  destructive-hover: \"#DC3E42\"\n  destructive-hover-dark: \"#8C333A\"\n  destructive-border: \"#CE2C31\"\n  destructive-border-dark: \"#FF9592\"\n  on-destructive: \"#FFFCFC\"\n  on-destructive-dark: \"#FFD1D9\"\n  error: \"#E5484D\"\n  error-dark: \"#72232D\"\n  on-error: \"#FFFCFC\"\n  on-error-dark: \"#FFD1D9\"\n  success: \"#46A758\"\n  success-dark: \"#2D5736\"\n  success-hover: \"#3E9B4F\"\n  success-hover-dark: \"#366740\"\n  success-border: \"#2A7E3B\"\n  success-border-dark: \"#71D083\"\n  on-success: \"#FBFEFB\"\n  on-success-dark: \"#C2F0C2\"\n  action: \"#FFE629\"\n  action-dark: \"#524202\"\n  action-hover: \"#FFDC00\"\n  action-hover-dark: \"#665417\"\n  action-border: \"#9E6C00\"\n  action-border-dark: \"#F5E147\"\n  on-action: \"#473B1F\"\n  on-action-dark: \"#F6EEB4\"\n  link: \"#0B68CB\"\n  link-dark: \"#479BF5\"\n  link-visited: \"#8E4EC6\"\n  link-visited-dark: \"#BF9BDF\"\n  stale: \"#EBE2CC\"\n  stale-dark: \"#525342\"\n  code-background: \"#FFFFFF\"\n  code-background-dark: \"#282C34\"\n  surface: \"#FFFFFF\"\n  surface-dark: \"#252927\"\n  code-foreground: \"#000000\"\n  code-foreground-dark: \"#ABB2BF\"\n  data-grid-accent: \"#7C3AED\"\ntypography:\n  body-md:\n    fontFamily: PT Sans\n    fontSize: 1rem\n    fontWeight: \"400\"\n    lineHeight: 1.75rem\n    letterSpacing: 0em\n  body-sm:\n    fontFamily: PT Sans\n    fontSize: 0.875rem\n    fontWeight: \"400\"\n    lineHeight: 1.25rem\n    letterSpacing: 0em\n  label-md:\n    fontFamily: PT Sans\n    fontSize: 0.875rem\n    fontWeight: \"500\"\n    lineHeight: 1.25rem\n    letterSpacing: 0em\n  label-xs:\n    fontFamily: PT Sans\n    fontSize: 0.75rem\n    fontWeight: \"600\"\n    lineHeight: 1rem\n    letterSpacing: 0em\n  markdown-heading:\n    fontFamily: Lora\n    fontSize: 1.875rem\n    fontWeight: \"600\"\n    lineHeight: 2.25rem\n    letterSpacing: -0.025em\n  code-editor:\n    fontFamily: Fira Mono\n    fontSize: 14px\n    fontWeight: \"400\"\n    lineHeight: 1.25rem\n    letterSpacing: 0em\n  slide-h1:\n    fontFamily: PT Sans\n    fontSize: 4.375rem\n    fontWeight: \"600\"\n    lineHeight: \"1.2\"\n    letterSpacing: 0em\nrounded:\n  sm: 4px\n  DEFAULT: 8px\n  md: 6px\n  lg: 8px\n  cell: 10px\n  xl: 0.75rem\n  full: 9999px\nspacing:\n  unit: 0.5rem\n  xs: 0.25rem\n  sm: 0.5rem\n  md: 1rem\n  lg: 1.5rem\n  xl: 3rem\n  content-compact: 740px\n  content-medium: 1110px\n  content-wide: 1400px\n  grid-row-height: 20px\n  grid-columns: \"24\"\ncomponents:\n  app-shell:\n    backgroundColor: \"{colors.background}\"\n    textColor: \"{colors.foreground}\"\n    typography: \"{typography.body-md}\"\n  cell:\n    backgroundColor: \"{colors.surface}\"\n    textColor: \"{colors.foreground}\"\n    typography: \"{typography.body-md}\"\n    rounded: \"{rounded.cell}\"\n    width: 100%\n  output-area:\n    backgroundColor: \"{colors.surface}\"\n    textColor: \"{colors.foreground}\"\n    typography: \"{typography.body-md}\"\n    padding: 1rem\n    width: 100%\n  code-editor:\n    backgroundColor: \"{colors.code-background}\"\n    textColor: \"{colors.code-foreground}\"\n    typography: \"{typography.code-editor}\"\n    width: 100%\n  button-primary:\n    backgroundColor: \"{colors.primary}\"\n    textColor: \"{colors.on-primary}\"\n    typography: \"{typography.label-md}\"\n    rounded: \"{rounded.md}\"\n    height: 2.25rem\n  button-action:\n    backgroundColor: \"{colors.action}\"\n    textColor: \"{colors.on-action}\"\n    typography: \"{typography.label-md}\"\n    rounded: \"{rounded.md}\"\n    height: 2.25rem\n  input:\n    backgroundColor: \"{colors.background}\"\n    textColor: \"{colors.foreground}\"\n    typography: \"{typography.body-sm}\"\n    rounded: \"{rounded.sm}\"\n    height: 1.5rem\n  data-table:\n    backgroundColor: \"{colors.surface}\"\n    textColor: \"{colors.foreground}\"\n    typography: \"{typography.body-sm}\"\n    width: 100%\n---\n\n## Brand Assets\n\n- Logo SVG: https://raw.githubusercontent.com/marimo-team/marimo/main/docs/_static/marimo-logotype-thick.svg\n- Preserve the original aspect ratio.\n- Do not recolor unless explicitly requested.\n\n## Visual Character\n\n- Compact, software-native, and utilitarian.\n- White or near-black work surfaces with slate borders and muted secondary text.\n- Restrained blue for primary interaction; yellow for action, stale, or needs-run states.\n- Avoid decorative gradients, marketing-style heroes, nested cards, and one-off palettes.\n\n## Color\n\n- Use background, surface, foreground, border, and muted tokens for structure.\n- Use primary for primary actions, selection, progress, and clear focus only.\n- Use action and stale colors for manual action or freshness state, not generic warning.\n- Use destructive, error, and success colors only for their semantic states.\n- Preserve light and dark token pairs whenever a color appears in both modes.\n\n## Typography\n\n- Use PT Sans for UI and prose, Lora for authored markdown headings, and Fira Mono for code-like values.\n- Keep control text compact and legible.\n- Do not add viewport-based type scaling beyond marimo's app defaults.\n\n## Surfaces\n\n- Use borders first and subtle shadows second.\n- Cells, outputs, editors, markdown, tables, and data grids should be full-width and overflow-safe.\n- Keep data UI dense and inspectable: stable columns, predictable overflow, readable headers, and no decorative framing around tables or charts.\n- Cards are for repeated items, dialogs, or genuinely framed tools; do not style page sections as cards.\n\n## Components\n\n- Buttons should be compact, label-like, focusable, and drawn from primary, secondary, or action semantics.\n- Icon buttons should use familiar existing icons and tooltips for unclear actions.\n- Inputs, selects, and textareas should be compact, bordered, readable, and use code typography only for code-like values.\n- Tabs, menus, popovers, dialogs, and tooltips should use semantic surfaces, borders, focus states, and restrained shadow.\n- Runtime states should pair color with labels, icons, borders, position, or shape.\n\n## Motion\n\nUse short transitions for hover, focus, loading, resize, drag, and stale-output changes. Avoid decorative animation.\n","packages/llm-info/skills/SKILL.md":"---\nname: fill-model-descriptions\ndescription: Curate descriptions and provider-specific reasoning options and token limits in `packages/llm-info/data/models.yml` using models.dev, OpenRouter, and provider documentation. Use when the user asks to populate model descriptions, enrich the model catalog, or curate descriptions after running `pnpm sync-models`.\ndisable-model-invocation: true\n---\n\n# Fill Model Descriptions\n\n## Goal\n\nKeep descriptions in `packages/llm-info/data/models.yml` concise and accurate. Fill empty descriptions and refresh existing descriptions when newly added models or authoritative documentation make them obsolete. Source descriptions from OpenRouter first, then provider documentation as a fallback.\n\n## Scope and Contract\n\n- Fill every empty `description` for which a confident source is available.\n- Preserve human-curated, non-empty descriptions unless a newly added model or authoritative source makes a concrete claim obsolete. Typical obsolete claims include \"latest,\" \"most capable,\" availability, or capabilities that have demonstrably changed.\n- Do not rewrite existing descriptions only for style, tone, or consistency. When an existing description must change, make the smallest factual correction and record it in the final summary.\n- The file is a top-level YAML map keyed by provider id (`anthropic:`, `openai:`, …). Each provider's value is an array of model entries.\n- For description-only work, do not modify any other field. For metadata enrichment, refresh machine-sourced capabilities, input/output types, release dates, pricing, reasoning options, and token limits; preserve names, descriptions, and roles. Do not reorder entries or change formatting (flow-style arrays like `roles: [chat, edit]`, blank lines between entries, blank line between provider sections).\n- This skill requires network access.\n\nFor metadata-only requests, use [Reasoning Options and Token Limits](#reasoning-options-and-token-limits) and skip the description workflow.\n\n## Workflow\n\n1. **Read** `packages/llm-info/data/models.yml`. Parse it with the `yaml` library's `parseDocument` (NOT `parse`) so formatting and comments are preserved on write-back.\n\n2. **Collect and review** descriptions:\n   - Build one worklist of `{ provider, model }` pairs containing every entry where `description` is empty.\n   - Review related existing entries in the same model families for claims made obsolete by the new entries. Also review descriptions affected by a factual change found in authoritative documentation, and add every obsolete entry to the same worklist.\n\n3. **Source descriptions** in this priority order:\n\n   **a. OpenRouter** — `GET https://openrouter.ai/api/v1/models` (no auth required). Build a lookup keyed by lowercased `id`. For each `{ provider, model }`, try candidates in this order:\n   - `${vendor}/${model}` where `vendor` comes from the Vendor Map below.\n   - `${vendor}/${model.replaceAll('-', '.')}` (some OR ids use `.` separators, e.g. `claude-3.5-sonnet`).\n   - For Bedrock entries with region/alias prefixes (`us.`, `eu.`, `jp.`, `global.`, `anthropic.`, `minimax.`, `mistral.`, `zai.`, `nvidia.`), strip the prefix and retry with the appropriate vendor.\n   - For Google entries with `@default` suffix (e.g. `claude-opus-4-7@default`), strip the suffix and try `anthropic/${rest}`. These are Vertex-hosted Anthropic models — descriptions should note they are Vertex AI only (not Gemini API).\n\n   **b. Provider docs** — if no OpenRouter hit, search the canonical provider's docs page (anthropic.com/news, platform.openai.com/docs/models, ai.google.dev/gemini-api/docs/models, mistral.ai/news, x.ai/blog, etc.) for the model's one-line summary. Use the `WebSearch` or `WebFetch` tool.\n\n   **c. Skip** — if neither source has a confident answer, leave `description: \"\"` and record the `{ provider, model }` for the final summary. Empty is better than wrong.\n\n4. **Truncate** each sourced description per the rules in the \"Truncation\" section.\n\n5. **Write** the YAML back using targeted `Pair` mutations on the parsed `Document`, not text replacement. Reference implementation: `packages/llm-info/src/sync-models.ts` shows how to load a Document, mutate sequence/map nodes, and stringify with `{ lineWidth: 0, flowCollectionPadding: false }` to preserve formatting.\n\n6. **Validate** by running:\n   ```bash\n   pnpm --filter @marimo-team/llm-info test\n   ```\n   The `schema.test.ts` test will catch any structural drift.\n\n7. **Report** to the user:\n   - How many empty descriptions were filled.\n   - How many obsolete descriptions were updated, with the provider/model list and the factual reason.\n   - How many were skipped (with the provider/model list).\n\n## Reasoning Options and Token Limits\n\nWhen metadata enrichment is requested, query `https://models.dev/api.json` and\nmatch the exact provider/model offering using `PROVIDER_MAP` in\n`src/sources/merge.ts`. Google Vertex models remain separate offerings even\nthough they share the `google` catalog section. Do not use the description\nvendor map or strip aliases to obtain metadata from another hosting provider.\n\nRun `pnpm --dir packages/llm-info sync-models --metadata-only` to refresh the\ncurrent catalog without adding models. Normal sync also refreshes known metadata\non existing entries: capabilities, input/output types, release dates, pricing,\nreasoning options, and token limits. Curated names, descriptions, and roles are\npreserved. Neither mode changes runtime thinking configuration.\n\n- `reasoning_options` preserves upstream `toggle`, `effort` (with explicit\n  values), and `budget_tokens` (with optional `min`/`max`) controls. Preserve\n  `null`, `default`, and the `-1` automatic-budget sentinel when supplied.\n- `limits` maps upstream `limit.context` and `limit.output`, in tokens. Preserve\n  supplied values, including zero; omitted fields remain unknown.\n- An explicit `reasoning: false` removes the thinking capability and clears stale\n  reasoning controls. An omitted flag preserves the corresponding capability.\n  Partial pricing and limits updates preserve unspecified values.\n- Missing upstream fields or unmatched offerings do not justify inventing\n  values or removing existing metadata. Report unmatched entries. Consult the\n  exact provider's documentation if further enrichment is needed.\n- OpenRouter's normalized reasoning controls describe its gateway API. Use them\n  only for OpenRouter offerings, not as native Anthropic, OpenAI, Azure, or\n  Bedrock configuration contracts.\n\nAfter enrichment, run `pnpm --dir packages/llm-info codegen` and\n`pnpm --dir packages/llm-info test --run`. Report coverage for each metadata\nfield and unresolved provider/model matches. Generated JSON must retain the new\nfields; updating YAML alone is insufficient.\n\n## Vendor Map\n\nOpenRouter id vendor prefixes for each marimo provider:\n\n| Marimo provider | OpenRouter vendor prefix | Notes |\n|---|---|---|\n| `anthropic` | `anthropic` | Direct match in most cases |\n| `openai` | `openai` | Direct match |\n| `google` | `google` | Strip `@default` suffix if present |\n| `mistral` | `mistralai` | Note the `ai` suffix |\n| `xai` | `x-ai` | Hyphenated |\n| `azure` | `openai` | Azure mostly re-exposes OpenAI models |\n| `bedrock` | varies | Strip region prefix (`us.`/`eu.`/`jp.`/`global.`) and use the embedded vendor (`anthropic.foo` → `anthropic/foo`) |\n| `github` | varies | Ids like `openai/gpt-4.1` carry the vendor; strip the github layer |\n| `openrouter` | embedded in id | Ids like `anthropic/claude-opus-4.7-fast` already carry the vendor |\n| `wandb` | embedded in id | Ids like `deepseek-ai/DeepSeek-V3.1`; the prefix is the vendor |\n| `opencode-go` | rarely on OR | Source from provider docs |\n| `ollama` | not on OR | Source from the Ollama model card |\n\n## Truncation\n\n- **One sentence.** Split on `. ` and take the first. Strip trailing whitespace and any markdown formatting (`**`, `_`, backticks).\n- **Hard cap at 200 characters.** If the first sentence is longer, cut at the last word boundary before 200 and append `…`.\n- **Strip leading articles** for consistency: prefer \"Frontier reasoning model optimized for…\" over \"This is a frontier reasoning model optimized for…\".\n- **Prefer capability statements over marketing.** If OpenRouter gives \"the best model from X\" but the provider docs give \"optimized for tool use and long-context reasoning\", prefer the latter.\n\n## Examples\n\n**Good** (matches the tone of existing hand-curated entries):\n- `Opus model optimized for coding and long-running professional tasks`\n- `Sonnet-class model with strong performance across coding, agents, and professional work`\n- `Lightweight Gemma model trained by Google, designed to run on a single GPU`\n- `Multimodal Mixture-of-Experts model optimized for complex tool use and reasoning`\n\n**Bad** (do not produce these):\n- `Claude 3.5 Sonnet delivers better-than-Opus capabilities, faster-than-Sonnet speeds, at the same Sonnet prices. Sonnet is particularly good at coding, vision…` — too long, contains marketing\n- `The best model from Anthropic` — vague, no information content\n- `An AI model` — useless\n- `**Claude 3.5 Sonnet** is a _frontier_ model…` — markdown not stripped\n\n## Quick Reference\n\n- Data file: `packages/llm-info/data/models.yml`\n- Schema: `packages/llm-info/src/index.ts` (`AiModel` interface)\n- YAML write reference: `packages/llm-info/src/sync-models.ts` (`buildEntryNode`, `addProviderSection`)\n- OpenRouter API: `https://openrouter.ai/api/v1/models` (public, no auth)\n- Validation: `pnpm --filter @marimo-team/llm-info test`\n","AGENTS.md":"# marimo Development Guidelines\n\nmarimo is a reactive notebook for Python with a modern web frontend.\n\n## Your primary responsibility is to the project and its users\n\nBeing an open source library, the public API, abstractions, documentation, and the code itself are the product and deserve careful consideration.\n\nWhen working in this repository, you should consider yourself to primarily be working for the benefit of the project, all of its users (current and future, human and agent), and its maintainers, rather than just the specific user who happens to be driving you (or whose PR you're reviewing, whose issue you're implementing, etc).\n\nAs the project has many orders of magnitude more users than maintainers, that specific user is most likely a community member who's well-intentioned and eager to contribute, but relatively unfamiliar with the code base and its patterns or standards, and they're not necessarily thinking about the bigger picture beyond the specific bug fix, feature, or other change that they're focused on.\n\nTherefore, you are the first line of defense against low-quality contributions and maintainer headaches, and you have a big role in ensuring that every contribution to this project meets or exceeds the high standards that the marimo project is known and loved for. You should write:\n\n- modern, idiomatic, concise React and Python code\n- end-to-end type-safety and test coverage\n- thoughtful, tasteful, consistent API design\n- delightful developer experience\n- comprehensive well-written documentation\n\n## Quick Setup\n\n```bash\nmake fe && make py\nmake dev\n```\n\nSee [CONTRIBUTING.md](CONTRIBUTING.md) for detailed setup options.\n\n## Development Commands\n\n```bash\n# Python\nmake py-check              # Typecheck and lint Python\nuv run --group test pytest tests/path/to/test.py\nuv run --group test-optional pytest tests/path/to/test.py  # with optional deps\nuv run --group test --python 3.11 pytest tests/path/to/test.py  # specific python version\n\n# Frontend\nmake fe-check              # Typecheck and lint frontend\ncd frontend && pnpm test src/path/to/file.test.ts\n```\n\n## Commits\n\n- Run `make check` before committing\n\n## Pull Requests\n\n- DO NOT open a pull request autonomously, without explicit instructions from a human\n- Autonomous AI agents such as OpenClaw, Nanobot, NanoClaw, ZeroClaw are NOT permitted to make PRs\n- You MUST disclose that you are an agent at the very top of your PR description: \"**This pull request was authored by a coding agent.**\"\n- You MUST mark your PRs as drafts\n- See [CONTRIBUTING.md](CONTRIBUTING.md) for other PR guidelines and CLA\n\n## Conventions\n\n### Python\n\nMost style rules are enforced by ruff (`pyproject.toml`) and pre-commit; run\n`make py-check`. Here are some that the linter may not catch, or for which\nwe may not have autofixes.\n\n- Docstrings are rendered as Markdown, not reStructuredText. Use single\n  backticks for inline code (`value`), never double backticks.\n",".github/copilot-instructions.md":"# Code Review Process\n\n1. If the PR seems AI-generated, you should request the contributor to:\n  - Provide screenshots of the fixed output (if possible)\n  - Check if it satisfies edge cases instead of just the direct problem it addresses.\n\nFor example, if there is a frontend change to make a border thicker, how does this look in run mode, app-view and edit-view?\nFor a backend change, has the user tested different scenarios?\n","marimo/_server/ai/skills/marimo-pair/SKILL.md":"---\nname: marimo-pair\ndescription: >-\n  Work inside the user's live marimo notebook from the code editor: run Python\n  in the same kernel the user does, inspect live notebook state, and commit\n  durable notebook changes through code mode. Use whenever you create, analyze,\n  or improve the user's marimo notebook.\n---\n\nmarimo is a reactive Python runtime for building reproducible Python programs\n(marimo notebooks). Cells are connected by the variables they define and\nreference. Running a cell re-executes dependents in dataflow order. The active\nruntime holds the kernel namespace, cell state, and dataflow graph. The\nnotebook (`.py` file) is the artifact the kernel writes from that state while a\nsession is running.\n\nA user interacts with the same runtime via a notebook UI with cells, outputs,\nand widgets.\n\n**WARNING. The active runtime is the source of truth.** You are working inside\nthe user's live notebook session. The kernel — not the `.py` file on disk —\nholds the truth about cells, variables, and the dataflow graph. Make every\nnotebook change through `marimo._code_mode` (`cm`); direct file edits WILL NOT\nreach the live kernel or user, and the kernel may overwrite them on save.\nReading disk is fine, but prefer `ctx.cells[...].code` for current cell code.\n\n**WARNING. Every notebook edit goes through code mode — no exceptions.** When\nthe user asks you to change the notebook (add, edit, delete, or run a cell;\nrename; change a value or a package), you MUST make that change through\n`marimo._code_mode` (`cm`) by running it with the `execute_code` tool. There is\nno separate file-editing path — `execute_code` + `cm` is the only way to reach\nthe user's running session. Running ad-hoc Python with `execute_code` to\nexplore or test is fine; _persisting any change to the notebook_ is only ever\ndone via `cm`.\n\n## Running Code in the Kernel\n\nYou are already attached to the user's running notebook — there is nothing to\nconnect to or start. Use the `execute_code` tool to run Python in that kernel,\npassing your Python as the `code` argument. Everything you do — inspecting\nstate, testing transformations, and persisting changes via `cm` — runs through\n`execute_code` in the scratchpad (see below).\n\n## Required First Kernel Command\n\nStart every code-mode session with this dedicated `execute_code` call:\n\n```python\nimport marimo._code_mode as cm\n\nhelp(cm)\n```\n\nFollow this order for every live kernel, including read-only tasks:\n\n1. Run only the inspection command above.\n2. Wait for successful `help(cm)` output.\n3. Use `cm.get_context()` or another `cm` API in a later `execute_code` call.\n\nDo not combine the inspection with task-specific code, and do not use another\n`cm` API before the inspection succeeds. This verifies the private, unstable\nAPI exposed by the marimo version in the user's active kernel.\n\n## Scratchpad Scope\n\n`execute_code` evaluates Python in marimo's scratchpad: a temporary namespace\nwith a shallow copy of the kernel globals. Notebook variables are available by\nname, but new top-level bindings and rebindings are discarded after each call.\nIn-place mutations to notebook-owned objects can persist because those names\nstill reference live objects.\n\nEach call reports stdout and stderr from the scratchpad, plus console output\nfrom notebook cells it causes to run, including reactive descendants.\n\n### Ordinary Python\n\nUse ordinary Python in the scratchpad to inspect variables, sample data, test\ntransformations, probe APIs, check imports, and read widget state.\n\n```python\nprint(df.head())\n\nx = 10\nprint(x)\n```\n\nHere `df` comes from notebook globals, while `x` is a scratchpad-local binding.\n`x` exists for this call only and WILL NOT be added to notebook globals.\n\n### Persist with `cm`\n\nTop-level scratchpad assignments and rebindings are temporary. To persist work,\nincluding new variables, you MUST submit changes through `marimo._code_mode`\n(`cm`).\n\n`marimo._code_mode` is a PRIVATE, UNSTABLE agent API (note the leading\nunderscore). It exists for tools like this skill to drive a live kernel from\nthe scratchpad. DO NOT import it from notebook cells, library code, or\nanything a user would run — methods can change or disappear across marimo\nversions and kernels. Treat every `import marimo._code_mode as cm` as\nscratchpad-only.\n\nOpen a code-mode context to queue notebook changes.\n\n```python\nimport marimo._code_mode as cm\n\nasync with cm.get_context() as ctx:\n    cid = ctx.create_cell(\"x = df.head()\")\n    ctx.run_cell(cid)\n```\n\nThe scratchpad supports top-level async code. Use `async with` directly;\nwrapping it in `asyncio.run(...)` is unnecessary and can conflict with the\nkernel's event loop.\n\nAfter this block exits and the new cell runs, `x` is notebook state. Later\nscratchpad calls can read `x` by name. Code later in the same scratchpad call\nshould read `ctx.globals[\"x\"]`, because the scratchpad namespace was copied\nbefore the cell ran.\n\nInside the context, queued mutation methods are synchronous. Call them\ndirectly; do not `await` them. Each call queues an operation for marimo to\napply when the context exits normally. If the block raises, the queue is\ndiscarded.\n\nOn clean exit, marimo applies packages, validates and applies structural cell\nchanges, runs queued cells, then may run dependents. Validation is only\nstructural since queued cell runs can still error. `create_cell` and\n`edit_cell` change notebook structure only. Use `run_cell` to execute.\n\n`create_cell` currently defaults to `hide_code=True`, which collapses the code\neditor in the UI. Pass `hide_code=False` if the user wants created cells to\nbe visible without manually expanding them.\n\n## Marimo Rules\n\nmarimo imposes a small contract on notebook code so it can keep the notebook as\na directed acyclic graph (DAG):\n\n- **No cycles** - cells cannot depend on each other in a cycle.\n- **No public redefinitions across cells** - each name has one owning cell.\n- **No wildcard imports** - `import *` prevents static analysis of definitions.\n\nThese rules keep the kernel, UI, and saved artifact consistent.\n\nWhen `cm` submits a cell body, marimo parses its top-level definitions and\nreferences. A top-level name enters the graph unless it is private with a\nleading underscore.\n\n```python\n# Public definitions: values, total, i, value, mean\nvalues = np.array([1, 2, 3])\ntotal = 0\nfor i, value in enumerate(values):\n    total += value\nmean = total / len(values)\nmean\n```\n\n```python\n# Public definition: mean\n_values = np.array([1, 2, 3])\n_total = 0\nfor _i, _value in enumerate(_values):\n    _total += _value\nmean = _total / len(_values)\nmean\n```\n\nUse private names for intermediates that no other cell should read. Public\nnames define the notebook-level dataflow. If a `cm` edit violates the contract,\nmarimo rejects the structural change and returns the validation error.\n\n## The Notebook's Shape\n\nA notebook is an ordered collection of cells. `ctx.cells` is the document view\nand `ctx.graph` is the dataflow view.\n\n```python\nfor cell in ctx.cells:\n    cell  # .id, .code, .name, .config, .status, .errors\n\nctx.cells[\"setup\"]  # by name\nctx.cells[0]  # by position\nlist(ctx.cells.keys())  # all IDs, in notebook order\n```\n\nCell IDs are opaque strings which can be queried from the notebook or captured\nfrom `cm` return values:\n\n```python\ncid = ctx.create_cell(\"df = pd.read_csv('data.csv')\")\nprint(cid)  # e.g. 'Hbol'\n```\n\nAlternatively, cells can be assigned and referenced by `name`. The graph can be\nused to understand its role in the dataflow.\n\n```python\nfor cid, impl in ctx.graph.cells.items():\n    impl  # .defs, .refs   (sets of public names)\n\nctx.graph.descendants(cid)  # cells that re-run when this one changes\nctx.graph.ancestors(cid)  # cells this one depends on\n```\n\nIn marimo, deletes are _destructive_ so it can be useful to query the\ndescendants prior to deleting to understand it's impact.\n\n## Writing Notebook Changes\n\nThe graph contract keeps marimo able to run and save the notebook. Passing\nthose checks alone does not guarantee a useful artifact. Committed cells should\nstill be readable, rerunnable, and editable.\n\nMake durable edits that reuse the notebook's existing names, imports,\ndependencies, and UI model. Don't be lazy. Avoid one-off workarounds that pass\n`cm` validation but leave a brittle notebook.\n\n### Cell Bodies\n\nSubmit the code that belongs in the cell.\n\n- **Submit cell contents** - `create_cell` and `edit_cell` take cell contents,\n  not saved-file `@app.cell` wrappers.\n- **Read before replacing** - for now, another editor may change a cell between\n  scratchpad calls. Before `edit_cell`, read the current body from\n  `ctx.cells[...]` and submit the full replacement.\n- **Reuse notebook imports** - if `np` already exists, use it or edit the owning\n  import cell. DO NOT add `import numpy as _np` just to bypass the graph.\n- **Define public names intentionally** - use public names for values later\n  cells should reference. Use private `_name` bindings or function locals for\n  same-cell intermediates.\n- **Define each public name once** - a public name has one owning cell.\n  Reassigning it in another cell fails with `Multiply-defined names`; edit the\n  owning cell or give the result a new name. Load the `gotchas` capability for\n  more traps.\n- **Run cells deliberately** - `create_cell` and `edit_cell` change structure\n  only. Queue `ctx.run_cell(...)` when the cell should execute.\n\n### Prefer `cm`-Managed Changes\n\nUse `cm` APIs when they exist. Avoid direct file edits, shell package commands,\nand scratchpad-only state for changes that should persist.\n\n- **Persist only through `cm`** - never try to change the notebook by writing\n  the `.py` file; `execute_code` + `cm` is the only path that reaches the live\n  session. Use `ctx.edit_cell(...)` even for small changes.\n- **Manage packages through `cm`** - use `ctx.packages.add()` or\n  `ctx.packages.remove()` instead of direct `uv` or `pip`; confirm\n  non-obvious dependency changes.\n- **Avoid transient paths** - persisted cells should not depend on `/tmp/...`\n  unless the work is intentionally transient.\n- **Delete deliberately** - deleting a cell removes globals it defines. Reuse\n  empty cells when convenient and delete cells left empty after edits.\n\n### UI and Widgets\n\nInspect the object before changing it. Different UI objects update through\ndifferent paths.\n\n- **Set `mo.ui.*` through `cm`** - use `ctx.set_ui_value(element, value)` inside\n  `cm.get_context()`.\n- **Set anywidget traitlets directly** - synced traitlets are Python\n  attributes, for example `widget.value = 5`.\n\nFor designing custom visual or interactive output, load the\n`rich-representations` capability.\n\n## On-demand references\n\nLoad these with the `load_capability` tool when you need deeper guidance. Do\nnot read reference files from disk.\n\n- **`gotchas`** — name redefinition, cached module proxies, and notebook traps\n- **`rich-representations`** — custom widgets and visualizations\n- **`notebook-improvements`** — improving existing notebooks\n","development_docs/prompts.md":"# Prompts\n\n## System prompts\n\nPrompts are generated using the `Prompter` class in `marimo/_server/ai/prompts.py`.\n\n### Snapshots\n\nYou can create snapshots of the prompts using the `snapshot` function in `tests/_server/ai/test_prompts.py`. These snapshots are checked into the repo, and you can use them to verify that the prompts have not changed. To run these snapshots, run:\n\n```bash\nuv run --python 3.12 --group test-optional pytest tests/_server/ai/test_prompts.py\n```\n","frontend/AGENTS.md":"# Frontend Guidelines\n\n## Key Principles\n\n- Write clear, maintainable code over clever/short syntax\n- Use TypeScript with proper typing for all code\n- Use functional programming patterns; avoid classes\n- Favor composition over inheritance\n- Reduce code duplication, if you see code that is repeated, refactor it to a function or component. This standardizes the codebase.\n\n## Naming Conventions\n\n- **Directories**: lowercase with dashes (`components/auth-wizard/`)\n- **Components**: PascalCase (`DashboardMenu.tsx`)\n- **Variables**: descriptive with auxiliary verbs (`isLoading`, `hasError`, `canSubmit`)\n\n## Testing\n\n### Unit Tests\n\nTests live alongside source files or in `__tests__` directories.\n\n```bash\npnpm turbo --filter @marimo-team/frontend test                            # All tests\npnpm turbo --filter @marimo-team/frontend test src/__tests__/lru.test.ts  # Specific file\n```\n\nBest practices:\n- test edge cases\n- use descriptive names\n- group with `describe`\n- prefer complete assertions over individual property checks (e.g., `expect(result).toEqual(expected)` rather than checking each property separately)\n\n### E2E Tests\n\nE2E tests use Playwright. See [e2e-tests/README.md](e2e-tests/README.md) for details.\n\n## Code Quality\n\nAvoid as much as possible using type assertions as they can cause runtime errors. Instead, use type guards, type predicates and error handling.\n```typescript\ncallFunction(x as T) // Avoid this\n```\n\n- Use logNever or assertNever to handle exhaustive switch cases.\n```typescript\nswitch (value) {\n  case \"a\":\n    break;\n  default:\n    logNever(value);\n}\n```\n\n- Keep comments minimal. Comments should only explain \"why\", not \"what\".\n","packages/client/TRANSPORTS.md":"# Custom transports\n\n`Client` and `NotebookClient` send HTTP requests and read server-sent events.\nTo follow events from an existing WebSocket, message channel, or another\nsource, pass a `Transport` function to `NotebookEvents` or `CatalogEvents`.\n\nThe stream calls the transport once for each connection attempt. The\ntransport receives a cursor and an abort signal. A null cursor requests a\nsnapshot. Otherwise, the transport sends the cursor to the host to resume\nafter that position.\n\nCall `open()` when the connection is established. Call `message(event)` for\neach decoded protocol event, in order. Close the connection when the signal\nis aborted.\n\nResolve when the connection ends and another attempt makes sense. Reject\nwhen the stream should stop. The stream's `closed` promise rejects with the\nsame error. Use `StreamStopped` to describe the failure. Calls to `open()` or\n`message(event)` after the promise settles are ignored.\n\nThe stream validates events, tracks the cursor, delivers events to\nsubscribers, and reconnects. It delivers `reset` when an interrupted snapshot\nmust be discarded. The host must also send `reset` when it cannot resume\nfrom the supplied cursor.\n\nThe transport sends any filters the host needs. The stream's `types` option\nfilters delivered events locally. A notebook transport must apply `runId`\nitself. Each reconnect must use the same filters.\n\n## Build on server-sent events\n\n`sse` is the transport a stream uses for a URL. Use it directly when a host\nserves the protocol's events with a URL that changes between connections or\nwith frames of its own that end the stream.\n\n```ts\nimport { NotebookEvents, StreamStopped, sse } from \"@marimo-team/client\";\n\nconst events = new NotebookEvents(\n  sse(() => `${base}/events?session_id=${session()}`, {\n    token,\n    stop: (frame) =>\n      frame.event === \"close\"\n        ? new StreamStopped(\"The session closed\")\n        : undefined,\n  }),\n);\n```\n\nThe URL function runs before each connection. A `StreamStopped` it throws\nstops the stream.\n\nSet `parseData` to decode each frame's raw data with a custom parser. It runs\nbefore `stop` and event delivery. The default is `JSON.parse`; if the parser\nthrows, the frame keeps its original text.\n\nSee the [transport contract](src/transport/frame.ts) for the function and\nevent types.\n","marimo/AGENTS.md":"# Python Backend Guidelines\n\n## Testing\n\nTests live in `tests/` folder, mirroring `marimo/` structure.\n\n```bash\nuv run --group test pytest tests/path/to/test.py\nuv run --group test-optional pytest tests/path/to/test.py  # with optional deps\nuv run --group test --python 3.11 pytest tests/path/to/test.py  # specific python version\n```\n\nWe should utilize inline-snapshots more often to verify the outputs of objects, functions, etc.\nAvoid individual property assertions, opt for full object comparisons.\n\n```python\nfrom inline_snapshot import snapshot\nfrom dirty_equals import IsStr\n\n\ndef test_function():\n    assert func() == snapshot(\n        {\n            \"prop1\": IsStr(),\n            \"prop2\": \"some string\",\n        }\n    )\n```\n\n## Code Style\n\n- When writing comments, keep them minimal. Comments should explain \"why\", not \"what\"\n\n## Import handling\n\nGenerally, we should import at the top of the file. If there are circular imports, it means the file structure is not optimal. Refactor code to remove circular dependencies.\n\nHeavy dependencies must be imported lazily\n\n```python\ndef get_dataframe():\n    import pandas as pd  # altair, duckdb, numpy, polars, pyarrow, sqlglot, etc.\n\n    return pd.DataFrame()\n```\n","packages/client/README.md":"# @marimo-team/client\n\nConnect to a marimo host to find notebooks, read their state, and request\nedits or execution. A host serves notebooks through the\n[host protocol](../../protocols/host/spec.md). `Client` works with the host's\ncatalog. `NotebookClient` works with one notebook.\n\n## Connect to a host\n\nGive `Client` the host's API base URL and token. These can come from your\napplication's configuration or the host's\n[local discovery record](../../protocols/host/spec.md#local-discovery).\n\n```ts\nimport { Client } from \"@marimo-team/client\";\n\nconst client = new Client(\"http://127.0.0.1:2718/api/marimo/v1\", {\n  token: \"your-token\",\n});\n```\n\nRequests use HTTP and event streams use server-sent events. Pass `fetch`\nalongside `token` to customize requests.\n\n## Find notebooks\n\nThe catalog stream describes the host's notebooks, projects, runtimes, and\nattachments. It also reports the host's capabilities. This example prints\nthe notebooks the host currently knows about.\n\n```ts\nfor await (const event of client.events({ types: [\"notebook\"] })) {\n  if (event.event === \"notebook\") {\n    console.log(event.data.notebook.id, event.data.notebook.name);\n  }\n  if (event.event === \"ready\") break;\n}\n```\n\n`ready` ends the initial snapshot. Breaking out closes the stream. Projects\nmay still be indexing when `ready` arrives, so more notebooks can appear\nafterward.\n\n## Discover local hosts in Node.js\n\n`discoverHosts()` performs [local discovery](../../protocols/host/spec.md#local-discovery)\non macOS and Linux (requires `procps` on Linux). This example lists the notebooks\neach discovered host currently knows about:\n\n```ts\nimport { Client } from \"@marimo-team/client\";\nimport { discoverHosts } from \"@marimo-team/client/node\";\n\nfor await (const host of discoverHosts()) {\n  const client = new Client(host.url, { token: host.token });\n  for await (const event of client.events({ types: [\"notebook\"] })) {\n    if (event.event === \"ready\") break;\n    if (event.event === \"notebook\") {\n      console.log(event.data.notebook.id, event.data.notebook.name);\n    }\n  }\n}\n```\n\n## Work with a notebook\n\nUse an id or a notebook record from the catalog to get a `NotebookClient`.\nThis example reads the document, prints its cell count, and asks the host\nto save it. It assumes the notebook supports `notebook.save`.\n\n```ts\nimport type { DocumentOutput } from \"@marimo-team/client/protocol\";\n\nconst notebook = client.notebook(\"n1\");\nlet document: DocumentOutput | undefined;\n\nfor await (const event of notebook.events({ types: [\"document\"] })) {\n  if (event.event === \"document\") document = event.data.document;\n  if (event.event === \"reset\") document = undefined;\n  if (event.event === \"ready\") break;\n}\n\nif (document === undefined) throw new Error(\"The host did not send a document\");\nconsole.log(`${document.order.length} cells`);\n\nconst result = await notebook.save({ ifMatch: document.etag });\nif (result.ok) {\n  console.log(\"Saved\", result.data.document.etag);\n} else {\n  console.error(result.problem);\n}\n```\n\n`ifMatch` makes the document's etag a precondition. If the document changes\nbefore the save, the host returns a conflict problem. Other actions, such\nas `edit` and `run`, use the same result shape. The notebook's advertised\noperations describe which actions it permits. Invalid request data,\ninvalid responses, and connection failures throw.\n\nYou can also construct a `NotebookClient` directly when you already know\nthe notebook's URL.\n\n## Follow changes\n\nKeep iterating after `ready` to follow changes. Streams reconnect and resume\nfrom their last cursor. If they cannot resume, they deliver `reset` followed\nby a new snapshot. Discard accumulated state on `reset` before applying the\nsnapshot.\n\nTo maintain a notebook list or document state from events, see the\n[reducer guide](REDUCERS.md).\n\nTo follow events over a WebSocket or another connection, see the\n[custom transport guide](TRANSPORTS.md).\n\n## Contributing\n\nThe [host protocol](../../protocols/host/spec.md) explains the model and\nbehavior. [OpenAPI](../../protocols/host/openapi.yaml) defines the routes and\npayloads. `@marimo-team/client/protocol` exports the TypeScript types and Zod\nschemas generated from it.\n\nRun these commands from the repository root. See\n[CONTRIBUTING.md](../../CONTRIBUTING.md) for setup.\n\nThe package is consumed from `dist`. Build it once, or watch for changes\nwhile developing.\n\n```sh\npnpm --dir packages/client build\npnpm --dir packages/client build --watch\n```\n\nAfter changing OpenAPI, regenerate the protocol types, schemas, and\noperation definitions. `codegen:check` checks that generated files match\nthe specification. Generation requires `uv` as well as the Node toolchain:\nboth language generators use the same Python overlay composer. The checked-in\nclient includes experimental features, including Analysis.\n\n```sh\npnpm --dir packages/client codegen\npnpm --dir packages/client codegen:check\n```\n\nThe package commands opt into all experimental features so Turbo builds retain\nthe APIs the handwritten client consumes. Use `codegen:stable` for stable-only\nbindings, using\n`--output-dir` to keep them separate from the client's checked-in bindings. Use\n`--include-experimental=analysis` to select a feature. This selects generated\ncontracts; it does not create a separate stable build of the client package.\nSee the [host protocol tooling](../../protocols/host/README.md) for details.\n\nRun the package's tests and typecheck. Omit `--run` to watch tests while\ndeveloping.\n\n```sh\npnpm --dir packages/client test --run\npnpm --dir packages/client typecheck\n```\n","packages/client/REDUCERS.md":"# Keep state from events\n\nHost state is read over event streams. The catalog stream describes the\nhost's notebooks, projects, runtimes, and attachments. A notebook stream\ndescribes one notebook's document and execution state.\n\nA stream starts with a snapshot of the current state. A `ready` event marks\nthe end of the snapshot. Subsequent events report changes. For example, a\n`notebook` event carries the notebook's current record, and\n`notebook.removed` identifies a notebook that was removed.\n\n`CatalogEvents` and `NotebookEvents` validate incoming events and track the\ncursor used to resume after a disconnect. They deliver events through an\nasync iterator or a subscription. Your application decides which records\nto retain. If the stream cannot resume, it delivers `reset` followed by a\nnew snapshot that replaces the previous state.\n\n## Keep a notebook list\n\nTo keep a notebook list, define a resource that starts with an empty list.\nIts `notebook` handler adds or replaces an entry. Its `notebook.removed`\nhandler removes an entry by id. Each entry keeps only the notebook's id\nand name.\n\nPass the resource to `createCatalogReducer`, then apply each event with\n`reduce(state, event)`. The resulting list is in `state.resources.notebooks`.\nThis example stops at `ready` and prints the list from the snapshot.\n\n```ts\nimport type { NotebookOutput } from \"@marimo-team/client/protocol\";\nimport {\n  Client,\n  createCatalogReducer,\n  type CatalogResource,\n} from \"@marimo-team/client\";\n\ntype NotebookSummary = Pick<NotebookOutput, \"id\" | \"name\">;\n\nconst notebooks: CatalogResource<readonly NotebookSummary[], \"notebook\"> = {\n  initial: [],\n  on: {\n    notebook: (state, { data }) => [\n      ...state.filter((entry) => entry.id !== data.notebook.id),\n      { id: data.notebook.id, name: data.notebook.name },\n    ],\n    \"notebook.removed\": (state, { data }) =>\n      state.filter((entry) => entry.id !== data.id),\n  },\n};\n\nconst reducer = createCatalogReducer({ notebooks });\nconst client = new Client(\"http://127.0.0.1:2718/api/marimo/v1\", {\n  token: \"your-token\",\n});\nlet state = reducer.initial;\n\nfor await (const event of client.events({ types: [\"notebook\"] })) {\n  state = reducer.reduce(state, event);\n  if (event.event === \"ready\") break;\n}\n\nconsole.log(state.resources.notebooks);\n```\n\nThe reducer handles the stream's lifecycle. `ready` changes `state.phase`\nfrom `snapshot` to `live`. `reset` returns the phase to `snapshot` and each\nresource to its initial value. Resources can handle `ready` to finish\nassembling a snapshot. The handler's third argument contains the phase\nbefore the event is applied. It is `snapshot` for the initial `ready` and\n`live` for a `ready` that follows a resumed connection.\n\nHandlers return a new value when state changes and the existing value\notherwise. They must not modify the previous value or perform side effects.\n\nFor a notebook stream, define a `NotebookResource` and pass it to\n`createNotebookReducer`. This reducer also keeps the notebook's record and\nidentity in `notebook` and `notebookId`. It handles `notebook` and\n`notebook.removed` itself. Removing the notebook clears its record and\nresources. A `reset` also clears its identity.\n\n## Follow changes in React\n\nTo keep a notebook list updated in a UI, subscribe to the stream and pass\neach event to the reducer through your store's state update function. This\nhook uses React state. It removes the subscription and closes the stream\nwhen the effect is cleaned up.\n\n```tsx\nimport { useEffect, useState } from \"react\";\n\nfunction useNotebooks(client: Client) {\n  const [state, setState] = useState(reducer.initial);\n\n  useEffect(() => {\n    setState(reducer.initial);\n    const events = client.events({ types: [\"notebook\"] });\n    const unsubscribe = events.subscribe((event) => {\n      setState((current) => reducer.reduce(current, event));\n    });\n    return () => {\n      unsubscribe();\n      events.close();\n    };\n  }, [client]);\n\n  return state;\n}\n```\n\nKeep the client instance stable across renders. Temporary disconnects preserve\nstate while the stream resumes. A `reset` rebuilds it. Pass a second function\nto `subscribe` to surface connection failures in your application. It\nreceives the error when the stream stops.\n\nIf you persist state for a later connection, save its matching cursor and\nreuse the same host, stream, and filter. The stream's cursor tracks received\nevents. When state updates are queued, as in React, it can be ahead of the\nstate you have applied. Resume needs both state and its matching cursor.\n","packages/client/package.json":"# Client Skill\n\nPath: `packages/client/package.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/marimo-team/marimo/HEAD/packages/client/package.json)","packages/client/tsconfig.build.json":"# Client Skill\n\nPath: `packages/client/tsconfig.build.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/marimo-team/marimo/HEAD/packages/client/tsconfig.build.json)","packages/client/tsconfig.json":"# Client Skill\n\nPath: `packages/client/tsconfig.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/marimo-team/marimo/HEAD/packages/client/tsconfig.json)","packages/llm-info/AGENTS.md":"# Llm-info Skill\n\nPath: `packages/llm-info/AGENTS.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/marimo-team/marimo/HEAD/packages/llm-info/AGENTS.md)","packages/llm-info/README.md":"# llm-info Documentation\n\nPath: `packages/llm-info/README.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/marimo-team/marimo/HEAD/packages/llm-info/README.md)","packages/llm-info/package.json":"# Llm-info Skill\n\nPath: `packages/llm-info/package.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/marimo-team/marimo/HEAD/packages/llm-info/package.json)","packages/llm-info/tsconfig.json":"# Llm-info Skill\n\nPath: `packages/llm-info/tsconfig.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/marimo-team/marimo/HEAD/packages/llm-info/tsconfig.json)","packages/lsp/package.json":"# Lsp Skill\n\nPath: `packages/lsp/package.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/marimo-team/marimo/HEAD/packages/lsp/package.json)","packages/lsp/tsconfig.json":"# Lsp Skill\n\nPath: `packages/lsp/tsconfig.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/marimo-team/marimo/HEAD/packages/lsp/tsconfig.json)","packages/lsp/turbo.json":"# Lsp Skill\n\nPath: `packages/lsp/turbo.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/marimo-team/marimo/HEAD/packages/lsp/turbo.json)","packages/openapi/api.yaml":"# Openapi Skill\n\nPath: `packages/openapi/api.yaml`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/marimo-team/marimo/HEAD/packages/openapi/api.yaml)","packages/openapi/package.json":"# Openapi Skill\n\nPath: `packages/openapi/package.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/marimo-team/marimo/HEAD/packages/openapi/package.json)","packages/openapi/tsconfig.json":"# Openapi Skill\n\nPath: `packages/openapi/tsconfig.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/marimo-team/marimo/HEAD/packages/openapi/tsconfig.json)","packages/pytest_changed/README.md":"# pytest_changed Documentation\n\nPath: `packages/pytest_changed/README.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/marimo-team/marimo/HEAD/packages/pytest_changed/README.md)","packages/smart-cells/README.md":"# smart-cells Documentation\n\nPath: `packages/smart-cells/README.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/marimo-team/marimo/HEAD/packages/smart-cells/README.md)","packages/smart-cells/package.json":"# Smart-cells Skill\n\nPath: `packages/smart-cells/package.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/marimo-team/marimo/HEAD/packages/smart-cells/package.json)","packages/smart-cells/tsconfig.json":"# Smart-cells Skill\n\nPath: `packages/smart-cells/tsconfig.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/marimo-team/marimo/HEAD/packages/smart-cells/tsconfig.json)","packages/ts-config/README.md":"# ts-config Documentation\n\nPath: `packages/ts-config/README.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/marimo-team/marimo/HEAD/packages/ts-config/README.md)","packages/ts-config/base.json":"# Ts-config Skill\n\nPath: `packages/ts-config/base.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/marimo-team/marimo/HEAD/packages/ts-config/base.json)","packages/ts-config/library.json":"# Ts-config Skill\n\nPath: `packages/ts-config/library.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/marimo-team/marimo/HEAD/packages/ts-config/library.json)","packages/ts-config/package.json":"# Ts-config Skill\n\nPath: `packages/ts-config/package.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/marimo-team/marimo/HEAD/packages/ts-config/package.json)","examples/ai/tools/README.md":"# tools Documentation\n\nPath: `examples/ai/tools/README.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/marimo-team/marimo/HEAD/examples/ai/tools/README.md)","docs/guides/lint_rules/rules/branch_expression.md":"# Rules Skill\n\nPath: `docs/guides/lint_rules/rules/branch_expression.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/marimo-team/marimo/HEAD/docs/guides/lint_rules/rules/branch_expression.md)","docs/guides/lint_rules/rules/cycle_dependencies.md":"# Rules Skill\n\nPath: `docs/guides/lint_rules/rules/cycle_dependencies.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/marimo-team/marimo/HEAD/docs/guides/lint_rules/rules/cycle_dependencies.md)","docs/guides/lint_rules/rules/empty_cells.md":"# Rules Skill\n\nPath: `docs/guides/lint_rules/rules/empty_cells.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/marimo-team/marimo/HEAD/docs/guides/lint_rules/rules/empty_cells.md)","docs/guides/lint_rules/rules/general_formatting.md":"# Rules Skill\n\nPath: `docs/guides/lint_rules/rules/general_formatting.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/marimo-team/marimo/HEAD/docs/guides/lint_rules/rules/general_formatting.md)","docs/guides/lint_rules/rules/incompatible_import.md":"# Rules Skill\n\nPath: `docs/guides/lint_rules/rules/incompatible_import.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/marimo-team/marimo/HEAD/docs/guides/lint_rules/rules/incompatible_import.md)","docs/guides/lint_rules/rules/incompatible_package.md":"# Rules Skill\n\nPath: `docs/guides/lint_rules/rules/incompatible_package.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/marimo-team/marimo/HEAD/docs/guides/lint_rules/rules/incompatible_package.md)","docs/guides/lint_rules/rules/invalid_syntax.md":"# Rules Skill\n\nPath: `docs/guides/lint_rules/rules/invalid_syntax.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/marimo-team/marimo/HEAD/docs/guides/lint_rules/rules/invalid_syntax.md)","docs/guides/lint_rules/rules/markdown_indentation.md":"# Rules Skill\n\nPath: `docs/guides/lint_rules/rules/markdown_indentation.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/marimo-team/marimo/HEAD/docs/guides/lint_rules/rules/markdown_indentation.md)","docs/guides/lint_rules/rules/misc_log_capture.md":"# Rules Skill\n\nPath: `docs/guides/lint_rules/rules/misc_log_capture.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/marimo-team/marimo/HEAD/docs/guides/lint_rules/rules/misc_log_capture.md)","docs/guides/lint_rules/rules/multiple_definitions.md":"# Rules Skill\n\nPath: `docs/guides/lint_rules/rules/multiple_definitions.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/marimo-team/marimo/HEAD/docs/guides/lint_rules/rules/multiple_definitions.md)","docs/guides/lint_rules/rules/parse_stderr.md":"# Rules Skill\n\nPath: `docs/guides/lint_rules/rules/parse_stderr.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/marimo-team/marimo/HEAD/docs/guides/lint_rules/rules/parse_stderr.md)","docs/guides/lint_rules/rules/parse_stdout.md":"# Rules Skill\n\nPath: `docs/guides/lint_rules/rules/parse_stdout.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/marimo-team/marimo/HEAD/docs/guides/lint_rules/rules/parse_stdout.md)","docs/guides/lint_rules/rules/private_import_alias.md":"# Rules Skill\n\nPath: `docs/guides/lint_rules/rules/private_import_alias.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/marimo-team/marimo/HEAD/docs/guides/lint_rules/rules/private_import_alias.md)","docs/guides/lint_rules/rules/reusable_definition_order.md":"# Rules Skill\n\nPath: `docs/guides/lint_rules/rules/reusable_definition_order.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/marimo-team/marimo/HEAD/docs/guides/lint_rules/rules/reusable_definition_order.md)","docs/guides/lint_rules/rules/self_import.md":"# Rules Skill\n\nPath: `docs/guides/lint_rules/rules/self_import.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/marimo-team/marimo/HEAD/docs/guides/lint_rules/rules/self_import.md)","docs/guides/lint_rules/rules/setup_cell_dependencies.md":"# Rules Skill\n\nPath: `docs/guides/lint_rules/rules/setup_cell_dependencies.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/marimo-team/marimo/HEAD/docs/guides/lint_rules/rules/setup_cell_dependencies.md)","docs/guides/lint_rules/rules/sql_parse_error.md":"# Rules Skill\n\nPath: `docs/guides/lint_rules/rules/sql_parse_error.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/marimo-team/marimo/HEAD/docs/guides/lint_rules/rules/sql_parse_error.md)","docs/guides/lint_rules/rules/unparsable_cells.md":"# Rules Skill\n\nPath: `docs/guides/lint_rules/rules/unparsable_cells.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/marimo-team/marimo/HEAD/docs/guides/lint_rules/rules/unparsable_cells.md)","docs/guides/lint_rules/rules/unsafe_system_call.md":"# Rules Skill\n\nPath: `docs/guides/lint_rules/rules/unsafe_system_call.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/marimo-team/marimo/HEAD/docs/guides/lint_rules/rules/unsafe_system_call.md)","marimo/_server/ai/skills/marimo-pair/references/gotchas.md":"# References Skill\n\nPath: `marimo/_server/ai/skills/marimo-pair/references/gotchas.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/marimo-team/marimo/HEAD/marimo/_server/ai/skills/marimo-pair/references/gotchas.md)","marimo/_server/ai/skills/marimo-pair/references/notebook-improvements.md":"# References Skill\n\nPath: `marimo/_server/ai/skills/marimo-pair/references/notebook-improvements.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/marimo-team/marimo/HEAD/marimo/_server/ai/skills/marimo-pair/references/notebook-improvements.md)","marimo/_server/ai/skills/marimo-pair/references/rich-representations.md":"# References Skill\n\nPath: `marimo/_server/ai/skills/marimo-pair/references/rich-representations.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/marimo-team/marimo/HEAD/marimo/_server/ai/skills/marimo-pair/references/rich-representations.md)"},"files":{"DESIGN.md":"---\nversion: alpha\nname: marimo\ndescription: Design system for marimo, a reactive Python notebook for reproducible, git-friendly, deployable work.\ncolors:\n  background: \"#FFFFFF\"\n  background-dark: \"#181C1A\"\n  foreground: \"#0F172A\"\n  foreground-dark: \"#ECEEED\"\n  surface-muted: \"#F1F5F9\"\n  surface-muted-dark: \"#020303\"\n  muted-foreground: \"#64748B\"\n  muted-foreground-dark: \"#AAB2AF\"\n  popover: \"#FFFFFF\"\n  popover-dark: \"#252927\"\n  popover-foreground: \"#0F172A\"\n  popover-foreground-dark: \"#AAB2AF\"\n  card: \"#FFFFFF\"\n  card-dark: \"#252927\"\n  card-foreground: \"#0F172A\"\n  card-foreground-dark: \"#C0C6C3\"\n  border: \"#E2E8F0\"\n  border-dark: \"#3B403E\"\n  input: \"#A3A3A3\"\n  input-dark: \"#474C4A\"\n  primary: \"#0880EA\"\n  primary-dark: \"#28879F\"\n  on-primary: \"#F8FAFC\"\n  on-primary-dark: \"#B6ECF7\"\n  secondary: \"#F1F5F9\"\n  secondary-dark: \"#ECEEED\"\n  on-secondary: \"#0F172A\"\n  on-secondary-dark: \"#252927\"\n  accent: \"#EDF6FF\"\n  accent-dark: \"#1D5B6A\"\n  on-accent: \"#0B68CB\"\n  on-accent-dark: \"#B6ECF7\"\n  ring: \"#94A3B8\"\n  ring-dark: \"#2870BD\"\n  destructive: \"#E5484D\"\n  destructive-dark: \"#72232D\"\n  destructive-hover: \"#DC3E42\"\n  destructive-hover-dark: \"#8C333A\"\n  destructive-border: \"#CE2C31\"\n  destructive-border-dark: \"#FF9592\"\n  on-destructive: \"#FFFCFC\"\n  on-destructive-dark: \"#FFD1D9\"\n  error: \"#E5484D\"\n  error-dark: \"#72232D\"\n  on-error: \"#FFFCFC\"\n  on-error-dark: \"#FFD1D9\"\n  success: \"#46A758\"\n  success-dark: \"#2D5736\"\n  success-hover: \"#3E9B4F\"\n  success-hover-dark: \"#366740\"\n  success-border: \"#2A7E3B\"\n  success-border-dark: \"#71D083\"\n  on-success: \"#FBFEFB\"\n  on-success-dark: \"#C2F0C2\"\n  action: \"#FFE629\"\n  action-dark: \"#524202\"\n  action-hover: \"#FFDC00\"\n  action-hover-dark: \"#665417\"\n  action-border: \"#9E6C00\"\n  action-border-dark: \"#F5E147\"\n  on-action: \"#473B1F\"\n  on-action-dark: \"#F6EEB4\"\n  link: \"#0B68CB\"\n  link-dark: \"#479BF5\"\n  link-visited: \"#8E4EC6\"\n  link-visited-dark: \"#BF9BDF\"\n  stale: \"#EBE2CC\"\n  stale-dark: \"#525342\"\n  code-background: \"#FFFFFF\"\n  code-background-dark: \"#282C34\"\n  surface: \"#FFFFFF\"\n  surface-dark: \"#252927\"\n  code-foreground: \"#000000\"\n  code-foreground-dark: \"#ABB2BF\"\n  data-grid-accent: \"#7C3AED\"\ntypography:\n  body-md:\n    fontFamily: PT Sans\n    fontSize: 1rem\n    fontWeight: \"400\"\n    lineHeight: 1.75rem\n    letterSpacing: 0em\n  body-sm:\n    fontFamily: PT Sans\n    fontSize: 0.875rem\n    fontWeight: \"400\"\n    lineHeight: 1.25rem\n    letterSpacing: 0em\n  label-md:\n    fontFamily: PT Sans\n    fontSize: 0.875rem\n    fontWeight: \"500\"\n    lineHeight: 1.25rem\n    letterSpacing: 0em\n  label-xs:\n    fontFamily: PT Sans\n    fontSize: 0.75rem\n    fontWeight: \"600\"\n    lineHeight: 1rem\n    letterSpacing: 0em\n  markdown-heading:\n    fontFamily: Lora\n    fontSize: 1.875rem\n    fontWeight: \"600\"\n    lineHeight: 2.25rem\n    letterSpacing: -0.025em\n  code-editor:\n    fontFamily: Fira Mono\n    fontSize: 14px\n    fontWeight: \"400\"\n    lineHeight: 1.25rem\n    letterSpacing: 0em\n  slide-h1:\n    fontFamily: PT Sans\n    fontSize: 4.375rem\n    fontWeight: \"600\"\n    lineHeight: \"1.2\"\n    letterSpacing: 0em\nrounded:\n  sm: 4px\n  DEFAULT: 8px\n  md: 6px\n  lg: 8px\n  cell: 10px\n  xl: 0.75rem\n  full: 9999px\nspacing:\n  unit: 0.5rem\n  xs: 0.25rem\n  sm: 0.5rem\n  md: 1rem\n  lg: 1.5rem\n  xl: 3rem\n  content-compact: 740px\n  content-medium: 1110px\n  content-wide: 1400px\n  grid-row-height: 20px\n  grid-columns: \"24\"\ncomponents:\n  app-shell:\n    backgroundColor: \"{colors.background}\"\n    textColor: \"{colors.foreground}\"\n    typography: \"{typography.body-md}\"\n  cell:\n    backgroundColor: \"{colors.surface}\"\n    textColor: \"{colors.foreground}\"\n    typography: \"{typography.body-md}\"\n    rounded: \"{rounded.cell}\"\n    width: 100%\n  output-area:\n    backgroundColor: \"{colors.surface}\"\n    textColor: \"{colors.foreground}\"\n    typography: \"{typography.body-md}\"\n    padding: 1rem\n    width: 100%\n  code-editor:\n    backgroundColor: \"{colors.code-background}\"\n    textColor: \"{colors.code-foreground}\"\n    typography: \"{typography.code-editor}\"\n    width: 100%\n  button-primary:\n    backgroundColor: \"{colors.primary}\"\n    textColor: \"{colors.on-primary}\"\n    typography: \"{typography.label-md}\"\n    rounded: \"{rounded.md}\"\n    height: 2.25rem\n  button-action:\n    backgroundColor: \"{colors.action}\"\n    textColor: \"{colors.on-action}\"\n    typography: \"{typography.label-md}\"\n    rounded: \"{rounded.md}\"\n    height: 2.25rem\n  input:\n    backgroundColor: \"{colors.background}\"\n    textColor: \"{colors.foreground}\"\n    typography: \"{typography.body-sm}\"\n    rounded: \"{rounded.sm}\"\n    height: 1.5rem\n  data-table:\n    backgroundColor: \"{colors.surface}\"\n    textColor: \"{colors.foreground}\"\n    typography: \"{typography.body-sm}\"\n    width: 100%\n---\n\n## Brand Assets\n\n- Logo SVG: https://raw.githubusercontent.com/marimo-team/marimo/main/docs/_static/marimo-logotype-thick.svg\n- Preserve the original aspect ratio.\n- Do not recolor unless explicitly requested.\n\n## Visual Character\n\n- Compact, software-native, and utilitarian.\n- White or near-black work surfaces with slate borders and muted secondary text.\n- Restrained blue for primary interaction; yellow for action, stale, or needs-run states.\n- Avoid decorative gradients, marketing-style heroes, nested cards, and one-off palettes.\n\n## Color\n\n- Use background, surface, foreground, border, and muted tokens for structure.\n- Use primary for primary actions, selection, progress, and clear focus only.\n- Use action and stale colors for manual action or freshness state, not generic warning.\n- Use destructive, error, and success colors only for their semantic states.\n- Preserve light and dark token pairs whenever a color appears in both modes.\n\n## Typography\n\n- Use PT Sans for UI and prose, Lora for authored markdown headings, and Fira Mono for code-like values.\n- Keep control text compact and legible.\n- Do not add viewport-based type scaling beyond marimo's app defaults.\n\n## Surfaces\n\n- Use borders first and subtle shadows second.\n- Cells, outputs, editors, markdown, tables, and data grids should be full-width and overflow-safe.\n- Keep data UI dense and inspectable: stable columns, predictable overflow, readable headers, and no decorative framing around tables or charts.\n- Cards are for repeated items, dialogs, or genuinely framed tools; do not style page sections as cards.\n\n## Components\n\n- Buttons should be compact, label-like, focusable, and drawn from primary, secondary, or action semantics.\n- Icon buttons should use familiar existing icons and tooltips for unclear actions.\n- Inputs, selects, and textareas should be compact, bordered, readable, and use code typography only for code-like values.\n- Tabs, menus, popovers, dialogs, and tooltips should use semantic surfaces, borders, focus states, and restrained shadow.\n- Runtime states should pair color with labels, icons, borders, position, or shape.\n\n## Motion\n\nUse short transitions for hover, focus, loading, resize, drag, and stale-output changes. Avoid decorative animation.\n","packages/llm-info/skills/SKILL.md":"---\nname: fill-model-descriptions\ndescription: Curate descriptions and provider-specific reasoning options and token limits in `packages/llm-info/data/models.yml` using models.dev, OpenRouter, and provider documentation. Use when the user asks to populate model descriptions, enrich the model catalog, or curate descriptions after running `pnpm sync-models`.\ndisable-model-invocation: true\n---\n\n# Fill Model Descriptions\n\n## Goal\n\nKeep descriptions in `packages/llm-info/data/models.yml` concise and accurate. Fill empty descriptions and refresh existing descriptions when newly added models or authoritative documentation make them obsolete. Source descriptions from OpenRouter first, then provider documentation as a fallback.\n\n## Scope and Contract\n\n- Fill every empty `description` for which a confident source is available.\n- Preserve human-curated, non-empty descriptions unless a newly added model or authoritative source makes a concrete claim obsolete. Typical obsolete claims include \"latest,\" \"most capable,\" availability, or capabilities that have demonstrably changed.\n- Do not rewrite existing descriptions only for style, tone, or consistency. When an existing description must change, make the smallest factual correction and record it in the final summary.\n- The file is a top-level YAML map keyed by provider id (`anthropic:`, `openai:`, …). Each provider's value is an array of model entries.\n- For description-only work, do not modify any other field. For metadata enrichment, refresh machine-sourced capabilities, input/output types, release dates, pricing, reasoning options, and token limits; preserve names, descriptions, and roles. Do not reorder entries or change formatting (flow-style arrays like `roles: [chat, edit]`, blank lines between entries, blank line between provider sections).\n- This skill requires network access.\n\nFor metadata-only requests, use [Reasoning Options and Token Limits](#reasoning-options-and-token-limits) and skip the description workflow.\n\n## Workflow\n\n1. **Read** `packages/llm-info/data/models.yml`. Parse it with the `yaml` library's `parseDocument` (NOT `parse`) so formatting and comments are preserved on write-back.\n\n2. **Collect and review** descriptions:\n   - Build one worklist of `{ provider, model }` pairs containing every entry where `description` is empty.\n   - Review related existing entries in the same model families for claims made obsolete by the new entries. Also review descriptions affected by a factual change found in authoritative documentation, and add every obsolete entry to the same worklist.\n\n3. **Source descriptions** in this priority order:\n\n   **a. OpenRouter** — `GET https://openrouter.ai/api/v1/models` (no auth required). Build a lookup keyed by lowercased `id`. For each `{ provider, model }`, try candidates in this order:\n   - `${vendor}/${model}` where `vendor` comes from the Vendor Map below.\n   - `${vendor}/${model.replaceAll('-', '.')}` (some OR ids use `.` separators, e.g. `claude-3.5-sonnet`).\n   - For Bedrock entries with region/alias prefixes (`us.`, `eu.`, `jp.`, `global.`, `anthropic.`, `minimax.`, `mistral.`, `zai.`, `nvidia.`), strip the prefix and retry with the appropriate vendor.\n   - For Google entries with `@default` suffix (e.g. `claude-opus-4-7@default`), strip the suffix and try `anthropic/${rest}`. These are Vertex-hosted Anthropic models — descriptions should note they are Vertex AI only (not Gemini API).\n\n   **b. Provider docs** — if no OpenRouter hit, search the canonical provider's docs page (anthropic.com/news, platform.openai.com/docs/models, ai.google.dev/gemini-api/docs/models, mistral.ai/news, x.ai/blog, etc.) for the model's one-line summary. Use the `WebSearch` or `WebFetch` tool.\n\n   **c. Skip** — if neither source has a confident answer, leave `description: \"\"` and record the `{ provider, model }` for the final summary. Empty is better than wrong.\n\n4. **Truncate** each sourced description per the rules in the \"Truncation\" section.\n\n5. **Write** the YAML back using targeted `Pair` mutations on the parsed `Document`, not text replacement. Reference implementation: `packages/llm-info/src/sync-models.ts` shows how to load a Document, mutate sequence/map nodes, and stringify with `{ lineWidth: 0, flowCollectionPadding: false }` to preserve formatting.\n\n6. **Validate** by running:\n   ```bash\n   pnpm --filter @marimo-team/llm-info test\n   ```\n   The `schema.test.ts` test will catch any structural drift.\n\n7. **Report** to the user:\n   - How many empty descriptions were filled.\n   - How many obsolete descriptions were updated, with the provider/model list and the factual reason.\n   - How many were skipped (with the provider/model list).\n\n## Reasoning Options and Token Limits\n\nWhen metadata enrichment is requested, query `https://models.dev/api.json` and\nmatch the exact provider/model offering using `PROVIDER_MAP` in\n`src/sources/merge.ts`. Google Vertex models remain separate offerings even\nthough they share the `google` catalog section. Do not use the description\nvendor map or strip aliases to obtain metadata from another hosting provider.\n\nRun `pnpm --dir packages/llm-info sync-models --metadata-only` to refresh the\ncurrent catalog without adding models. Normal sync also refreshes known metadata\non existing entries: capabilities, input/output types, release dates, pricing,\nreasoning options, and token limits. Curated names, descriptions, and roles are\npreserved. Neither mode changes runtime thinking configuration.\n\n- `reasoning_options` preserves upstream `toggle`, `effort` (with explicit\n  values), and `budget_tokens` (with optional `min`/`max`) controls. Preserve\n  `null`, `default`, and the `-1` automatic-budget sentinel when supplied.\n- `limits` maps upstream `limit.context` and `limit.output`, in tokens. Preserve\n  supplied values, including zero; omitted fields remain unknown.\n- An explicit `reasoning: false` removes the thinking capability and clears stale\n  reasoning controls. An omitted flag preserves the corresponding capability.\n  Partial pricing and limits updates preserve unspecified values.\n- Missing upstream fields or unmatched offerings do not justify inventing\n  values or removing existing metadata. Report unmatched entries. Consult the\n  exact provider's documentation if further enrichment is needed.\n- OpenRouter's normalized reasoning controls describe its gateway API. Use them\n  only for OpenRouter offerings, not as native Anthropic, OpenAI, Azure, or\n  Bedrock configuration contracts.\n\nAfter enrichment, run `pnpm --dir packages/llm-info codegen` and\n`pnpm --dir packages/llm-info test --run`. Report coverage for each metadata\nfield and unresolved provider/model matches. Generated JSON must retain the new\nfields; updating YAML alone is insufficient.\n\n## Vendor Map\n\nOpenRouter id vendor prefixes for each marimo provider:\n\n| Marimo provider | OpenRouter vendor prefix | Notes |\n|---|---|---|\n| `anthropic` | `anthropic` | Direct match in most cases |\n| `openai` | `openai` | Direct match |\n| `google` | `google` | Strip `@default` suffix if present |\n| `mistral` | `mistralai` | Note the `ai` suffix |\n| `xai` | `x-ai` | Hyphenated |\n| `azure` | `openai` | Azure mostly re-exposes OpenAI models |\n| `bedrock` | varies | Strip region prefix (`us.`/`eu.`/`jp.`/`global.`) and use the embedded vendor (`anthropic.foo` → `anthropic/foo`) |\n| `github` | varies | Ids like `openai/gpt-4.1` carry the vendor; strip the github layer |\n| `openrouter` | embedded in id | Ids like `anthropic/claude-opus-4.7-fast` already carry the vendor |\n| `wandb` | embedded in id | Ids like `deepseek-ai/DeepSeek-V3.1`; the prefix is the vendor |\n| `opencode-go` | rarely on OR | Source from provider docs |\n| `ollama` | not on OR | Source from the Ollama model card |\n\n## Truncation\n\n- **One sentence.** Split on `. ` and take the first. Strip trailing whitespace and any markdown formatting (`**`, `_`, backticks).\n- **Hard cap at 200 characters.** If the first sentence is longer, cut at the last word boundary before 200 and append `…`.\n- **Strip leading articles** for consistency: prefer \"Frontier reasoning model optimized for…\" over \"This is a frontier reasoning model optimized for…\".\n- **Prefer capability statements over marketing.** If OpenRouter gives \"the best model from X\" but the provider docs give \"optimized for tool use and long-context reasoning\", prefer the latter.\n\n## Examples\n\n**Good** (matches the tone of existing hand-curated entries):\n- `Opus model optimized for coding and long-running professional tasks`\n- `Sonnet-class model with strong performance across coding, agents, and professional work`\n- `Lightweight Gemma model trained by Google, designed to run on a single GPU`\n- `Multimodal Mixture-of-Experts model optimized for complex tool use and reasoning`\n\n**Bad** (do not produce these):\n- `Claude 3.5 Sonnet delivers better-than-Opus capabilities, faster-than-Sonnet speeds, at the same Sonnet prices. Sonnet is particularly good at coding, vision…` — too long, contains marketing\n- `The best model from Anthropic` — vague, no information content\n- `An AI model` — useless\n- `**Claude 3.5 Sonnet** is a _frontier_ model…` — markdown not stripped\n\n## Quick Reference\n\n- Data file: `packages/llm-info/data/models.yml`\n- Schema: `packages/llm-info/src/index.ts` (`AiModel` interface)\n- YAML write reference: `packages/llm-info/src/sync-models.ts` (`buildEntryNode`, `addProviderSection`)\n- OpenRouter API: `https://openrouter.ai/api/v1/models` (public, no auth)\n- Validation: `pnpm --filter @marimo-team/llm-info test`\n","AGENTS.md":"# marimo Development Guidelines\n\nmarimo is a reactive notebook for Python with a modern web frontend.\n\n## Your primary responsibility is to the project and its users\n\nBeing an open source library, the public API, abstractions, documentation, and the code itself are the product and deserve careful consideration.\n\nWhen working in this repository, you should consider yourself to primarily be working for the benefit of the project, all of its users (current and future, human and agent), and its maintainers, rather than just the specific user who happens to be driving you (or whose PR you're reviewing, whose issue you're implementing, etc).\n\nAs the project has many orders of magnitude more users than maintainers, that specific user is most likely a community member who's well-intentioned and eager to contribute, but relatively unfamiliar with the code base and its patterns or standards, and they're not necessarily thinking about the bigger picture beyond the specific bug fix, feature, or other change that they're focused on.\n\nTherefore, you are the first line of defense against low-quality contributions and maintainer headaches, and you have a big role in ensuring that every contribution to this project meets or exceeds the high standards that the marimo project is known and loved for. You should write:\n\n- modern, idiomatic, concise React and Python code\n- end-to-end type-safety and test coverage\n- thoughtful, tasteful, consistent API design\n- delightful developer experience\n- comprehensive well-written documentation\n\n## Quick Setup\n\n```bash\nmake fe && make py\nmake dev\n```\n\nSee [CONTRIBUTING.md](CONTRIBUTING.md) for detailed setup options.\n\n## Development Commands\n\n```bash\n# Python\nmake py-check              # Typecheck and lint Python\nuv run --group test pytest tests/path/to/test.py\nuv run --group test-optional pytest tests/path/to/test.py  # with optional deps\nuv run --group test --python 3.11 pytest tests/path/to/test.py  # specific python version\n\n# Frontend\nmake fe-check              # Typecheck and lint frontend\ncd frontend && pnpm test src/path/to/file.test.ts\n```\n\n## Commits\n\n- Run `make check` before committing\n\n## Pull Requests\n\n- DO NOT open a pull request autonomously, without explicit instructions from a human\n- Autonomous AI agents such as OpenClaw, Nanobot, NanoClaw, ZeroClaw are NOT permitted to make PRs\n- You MUST disclose that you are an agent at the very top of your PR description: \"**This pull request was authored by a coding agent.**\"\n- You MUST mark your PRs as drafts\n- See [CONTRIBUTING.md](CONTRIBUTING.md) for other PR guidelines and CLA\n\n## Conventions\n\n### Python\n\nMost style rules are enforced by ruff (`pyproject.toml`) and pre-commit; run\n`make py-check`. Here are some that the linter may not catch, or for which\nwe may not have autofixes.\n\n- Docstrings are rendered as Markdown, not reStructuredText. Use single\n  backticks for inline code (`value`), never double backticks.\n",".github/copilot-instructions.md":"# Code Review Process\n\n1. If the PR seems AI-generated, you should request the contributor to:\n  - Provide screenshots of the fixed output (if possible)\n  - Check if it satisfies edge cases instead of just the direct problem it addresses.\n\nFor example, if there is a frontend change to make a border thicker, how does this look in run mode, app-view and edit-view?\nFor a backend change, has the user tested different scenarios?\n","marimo/_server/ai/skills/marimo-pair/SKILL.md":"---\nname: marimo-pair\ndescription: >-\n  Work inside the user's live marimo notebook from the code editor: run Python\n  in the same kernel the user does, inspect live notebook state, and commit\n  durable notebook changes through code mode. Use whenever you create, analyze,\n  or improve the user's marimo notebook.\n---\n\nmarimo is a reactive Python runtime for building reproducible Python programs\n(marimo notebooks). Cells are connected by the variables they define and\nreference. Running a cell re-executes dependents in dataflow order. The active\nruntime holds the kernel namespace, cell state, and dataflow graph. The\nnotebook (`.py` file) is the artifact the kernel writes from that state while a\nsession is running.\n\nA user interacts with the same runtime via a notebook UI with cells, outputs,\nand widgets.\n\n**WARNING. The active runtime is the source of truth.** You are working inside\nthe user's live notebook session. The kernel — not the `.py` file on disk —\nholds the truth about cells, variables, and the dataflow graph. Make every\nnotebook change through `marimo._code_mode` (`cm`); direct file edits WILL NOT\nreach the live kernel or user, and the kernel may overwrite them on save.\nReading disk is fine, but prefer `ctx.cells[...].code` for current cell code.\n\n**WARNING. Every notebook edit goes through code mode — no exceptions.** When\nthe user asks you to change the notebook (add, edit, delete, or run a cell;\nrename; change a value or a package), you MUST make that change through\n`marimo._code_mode` (`cm`) by running it with the `execute_code` tool. There is\nno separate file-editing path — `execute_code` + `cm` is the only way to reach\nthe user's running session. Running ad-hoc Python with `execute_code` to\nexplore or test is fine; _persisting any change to the notebook_ is only ever\ndone via `cm`.\n\n## Running Code in the Kernel\n\nYou are already attached to the user's running notebook — there is nothing to\nconnect to or start. Use the `execute_code` tool to run Python in that kernel,\npassing your Python as the `code` argument. Everything you do — inspecting\nstate, testing transformations, and persisting changes via `cm` — runs through\n`execute_code` in the scratchpad (see below).\n\n## Required First Kernel Command\n\nStart every code-mode session with this dedicated `execute_code` call:\n\n```python\nimport marimo._code_mode as cm\n\nhelp(cm)\n```\n\nFollow this order for every live kernel, including read-only tasks:\n\n1. Run only the inspection command above.\n2. Wait for successful `help(cm)` output.\n3. Use `cm.get_context()` or another `cm` API in a later `execute_code` call.\n\nDo not combine the inspection with task-specific code, and do not use another\n`cm` API before the inspection succeeds. This verifies the private, unstable\nAPI exposed by the marimo version in the user's active kernel.\n\n## Scratchpad Scope\n\n`execute_code` evaluates Python in marimo's scratchpad: a temporary namespace\nwith a shallow copy of the kernel globals. Notebook variables are available by\nname, but new top-level bindings and rebindings are discarded after each call.\nIn-place mutations to notebook-owned objects can persist because those names\nstill reference live objects.\n\nEach call reports stdout and stderr from the scratchpad, plus console output\nfrom notebook cells it causes to run, including reactive descendants.\n\n### Ordinary Python\n\nUse ordinary Python in the scratchpad to inspect variables, sample data, test\ntransformations, probe APIs, check imports, and read widget state.\n\n```python\nprint(df.head())\n\nx = 10\nprint(x)\n```\n\nHere `df` comes from notebook globals, while `x` is a scratchpad-local binding.\n`x` exists for this call only and WILL NOT be added to notebook globals.\n\n### Persist with `cm`\n\nTop-level scratchpad assignments and rebindings are temporary. To persist work,\nincluding new variables, you MUST submit changes through `marimo._code_mode`\n(`cm`).\n\n`marimo._code_mode` is a PRIVATE, UNSTABLE agent API (note the leading\nunderscore). It exists for tools like this skill to drive a live kernel from\nthe scratchpad. DO NOT import it from notebook cells, library code, or\nanything a user would run — methods can change or disappear across marimo\nversions and kernels. Treat every `import marimo._code_mode as cm` as\nscratchpad-only.\n\nOpen a code-mode context to queue notebook changes.\n\n```python\nimport marimo._code_mode as cm\n\nasync with cm.get_context() as ctx:\n    cid = ctx.create_cell(\"x = df.head()\")\n    ctx.run_cell(cid)\n```\n\nThe scratchpad supports top-level async code. Use `async with` directly;\nwrapping it in `asyncio.run(...)` is unnecessary and can conflict with the\nkernel's event loop.\n\nAfter this block exits and the new cell runs, `x` is notebook state. Later\nscratchpad calls can read `x` by name. Code later in the same scratchpad call\nshould read `ctx.globals[\"x\"]`, because the scratchpad namespace was copied\nbefore the cell ran.\n\nInside the context, queued mutation methods are synchronous. Call them\ndirectly; do not `await` them. Each call queues an operation for marimo to\napply when the context exits normally. If the block raises, the queue is\ndiscarded.\n\nOn clean exit, marimo applies packages, validates and applies structural cell\nchanges, runs queued cells, then may run dependents. Validation is only\nstructural since queued cell runs can still error. `create_cell` and\n`edit_cell` change notebook structure only. Use `run_cell` to execute.\n\n`create_cell` currently defaults to `hide_code=True`, which collapses the code\neditor in the UI. Pass `hide_code=False` if the user wants created cells to\nbe visible without manually expanding them.\n\n## Marimo Rules\n\nmarimo imposes a small contract on notebook code so it can keep the notebook as\na directed acyclic graph (DAG):\n\n- **No cycles** - cells cannot depend on each other in a cycle.\n- **No public redefinitions across cells** - each name has one owning cell.\n- **No wildcard imports** - `import *` prevents static analysis of definitions.\n\nThese rules keep the kernel, UI, and saved artifact consistent.\n\nWhen `cm` submits a cell body, marimo parses its top-level definitions and\nreferences. A top-level name enters the graph unless it is private with a\nleading underscore.\n\n```python\n# Public definitions: values, total, i, value, mean\nvalues = np.array([1, 2, 3])\ntotal = 0\nfor i, value in enumerate(values):\n    total += value\nmean = total / len(values)\nmean\n```\n\n```python\n# Public definition: mean\n_values = np.array([1, 2, 3])\n_total = 0\nfor _i, _value in enumerate(_values):\n    _total += _value\nmean = _total / len(_values)\nmean\n```\n\nUse private names for intermediates that no other cell should read. Public\nnames define the notebook-level dataflow. If a `cm` edit violates the contract,\nmarimo rejects the structural change and returns the validation error.\n\n## The Notebook's Shape\n\nA notebook is an ordered collection of cells. `ctx.cells` is the document view\nand `ctx.graph` is the dataflow view.\n\n```python\nfor cell in ctx.cells:\n    cell  # .id, .code, .name, .config, .status, .errors\n\nctx.cells[\"setup\"]  # by name\nctx.cells[0]  # by position\nlist(ctx.cells.keys())  # all IDs, in notebook order\n```\n\nCell IDs are opaque strings which can be queried from the notebook or captured\nfrom `cm` return values:\n\n```python\ncid = ctx.create_cell(\"df = pd.read_csv('data.csv')\")\nprint(cid)  # e.g. 'Hbol'\n```\n\nAlternatively, cells can be assigned and referenced by `name`. The graph can be\nused to understand its role in the dataflow.\n\n```python\nfor cid, impl in ctx.graph.cells.items():\n    impl  # .defs, .refs   (sets of public names)\n\nctx.graph.descendants(cid)  # cells that re-run when this one changes\nctx.graph.ancestors(cid)  # cells this one depends on\n```\n\nIn marimo, deletes are _destructive_ so it can be useful to query the\ndescendants prior to deleting to understand it's impact.\n\n## Writing Notebook Changes\n\nThe graph contract keeps marimo able to run and save the notebook. Passing\nthose checks alone does not guarantee a useful artifact. Committed cells should\nstill be readable, rerunnable, and editable.\n\nMake durable edits that reuse the notebook's existing names, imports,\ndependencies, and UI model. Don't be lazy. Avoid one-off workarounds that pass\n`cm` validation but leave a brittle notebook.\n\n### Cell Bodies\n\nSubmit the code that belongs in the cell.\n\n- **Submit cell contents** - `create_cell` and `edit_cell` take cell contents,\n  not saved-file `@app.cell` wrappers.\n- **Read before replacing** - for now, another editor may change a cell between\n  scratchpad calls. Before `edit_cell`, read the current body from\n  `ctx.cells[...]` and submit the full replacement.\n- **Reuse notebook imports** - if `np` already exists, use it or edit the owning\n  import cell. DO NOT add `import numpy as _np` just to bypass the graph.\n- **Define public names intentionally** - use public names for values later\n  cells should reference. Use private `_name` bindings or function locals for\n  same-cell intermediates.\n- **Define each public name once** - a public name has one owning cell.\n  Reassigning it in another cell fails with `Multiply-defined names`; edit the\n  owning cell or give the result a new name. Load the `gotchas` capability for\n  more traps.\n- **Run cells deliberately** - `create_cell` and `edit_cell` change structure\n  only. Queue `ctx.run_cell(...)` when the cell should execute.\n\n### Prefer `cm`-Managed Changes\n\nUse `cm` APIs when they exist. Avoid direct file edits, shell package commands,\nand scratchpad-only state for changes that should persist.\n\n- **Persist only through `cm`** - never try to change the notebook by writing\n  the `.py` file; `execute_code` + `cm` is the only path that reaches the live\n  session. Use `ctx.edit_cell(...)` even for small changes.\n- **Manage packages through `cm`** - use `ctx.packages.add()` or\n  `ctx.packages.remove()` instead of direct `uv` or `pip`; confirm\n  non-obvious dependency changes.\n- **Avoid transient paths** - persisted cells should not depend on `/tmp/...`\n  unless the work is intentionally transient.\n- **Delete deliberately** - deleting a cell removes globals it defines. Reuse\n  empty cells when convenient and delete cells left empty after edits.\n\n### UI and Widgets\n\nInspect the object before changing it. Different UI objects update through\ndifferent paths.\n\n- **Set `mo.ui.*` through `cm`** - use `ctx.set_ui_value(element, value)` inside\n  `cm.get_context()`.\n- **Set anywidget traitlets directly** - synced traitlets are Python\n  attributes, for example `widget.value = 5`.\n\nFor designing custom visual or interactive output, load the\n`rich-representations` capability.\n\n## On-demand references\n\nLoad these with the `load_capability` tool when you need deeper guidance. Do\nnot read reference files from disk.\n\n- **`gotchas`** — name redefinition, cached module proxies, and notebook traps\n- **`rich-representations`** — custom widgets and visualizations\n- **`notebook-improvements`** — improving existing notebooks\n","development_docs/prompts.md":"# Prompts\n\n## System prompts\n\nPrompts are generated using the `Prompter` class in `marimo/_server/ai/prompts.py`.\n\n### Snapshots\n\nYou can create snapshots of the prompts using the `snapshot` function in `tests/_server/ai/test_prompts.py`. These snapshots are checked into the repo, and you can use them to verify that the prompts have not changed. To run these snapshots, run:\n\n```bash\nuv run --python 3.12 --group test-optional pytest tests/_server/ai/test_prompts.py\n```\n","frontend/AGENTS.md":"# Frontend Guidelines\n\n## Key Principles\n\n- Write clear, maintainable code over clever/short syntax\n- Use TypeScript with proper typing for all code\n- Use functional programming patterns; avoid classes\n- Favor composition over inheritance\n- Reduce code duplication, if you see code that is repeated, refactor it to a function or component. This standardizes the codebase.\n\n## Naming Conventions\n\n- **Directories**: lowercase with dashes (`components/auth-wizard/`)\n- **Components**: PascalCase (`DashboardMenu.tsx`)\n- **Variables**: descriptive with auxiliary verbs (`isLoading`, `hasError`, `canSubmit`)\n\n## Testing\n\n### Unit Tests\n\nTests live alongside source files or in `__tests__` directories.\n\n```bash\npnpm turbo --filter @marimo-team/frontend test                            # All tests\npnpm turbo --filter @marimo-team/frontend test src/__tests__/lru.test.ts  # Specific file\n```\n\nBest practices:\n- test edge cases\n- use descriptive names\n- group with `describe`\n- prefer complete assertions over individual property checks (e.g., `expect(result).toEqual(expected)` rather than checking each property separately)\n\n### E2E Tests\n\nE2E tests use Playwright. See [e2e-tests/README.md](e2e-tests/README.md) for details.\n\n## Code Quality\n\nAvoid as much as possible using type assertions as they can cause runtime errors. Instead, use type guards, type predicates and error handling.\n```typescript\ncallFunction(x as T) // Avoid this\n```\n\n- Use logNever or assertNever to handle exhaustive switch cases.\n```typescript\nswitch (value) {\n  case \"a\":\n    break;\n  default:\n    logNever(value);\n}\n```\n\n- Keep comments minimal. Comments should only explain \"why\", not \"what\".\n","packages/client/TRANSPORTS.md":"# Custom transports\n\n`Client` and `NotebookClient` send HTTP requests and read server-sent events.\nTo follow events from an existing WebSocket, message channel, or another\nsource, pass a `Transport` function to `NotebookEvents` or `CatalogEvents`.\n\nThe stream calls the transport once for each connection attempt. The\ntransport receives a cursor and an abort signal. A null cursor requests a\nsnapshot. Otherwise, the transport sends the cursor to the host to resume\nafter that position.\n\nCall `open()` when the connection is established. Call `message(event)` for\neach decoded protocol event, in order. Close the connection when the signal\nis aborted.\n\nResolve when the connection ends and another attempt makes sense. Reject\nwhen the stream should stop. The stream's `closed` promise rejects with the\nsame error. Use `StreamStopped` to describe the failure. Calls to `open()` or\n`message(event)` after the promise settles are ignored.\n\nThe stream validates events, tracks the cursor, delivers events to\nsubscribers, and reconnects. It delivers `reset` when an interrupted snapshot\nmust be discarded. The host must also send `reset` when it cannot resume\nfrom the supplied cursor.\n\nThe transport sends any filters the host needs. The stream's `types` option\nfilters delivered events locally. A notebook transport must apply `runId`\nitself. Each reconnect must use the same filters.\n\n## Build on server-sent events\n\n`sse` is the transport a stream uses for a URL. Use it directly when a host\nserves the protocol's events with a URL that changes between connections or\nwith frames of its own that end the stream.\n\n```ts\nimport { NotebookEvents, StreamStopped, sse } from \"@marimo-team/client\";\n\nconst events = new NotebookEvents(\n  sse(() => `${base}/events?session_id=${session()}`, {\n    token,\n    stop: (frame) =>\n      frame.event === \"close\"\n        ? new StreamStopped(\"The session closed\")\n        : undefined,\n  }),\n);\n```\n\nThe URL function runs before each connection. A `StreamStopped` it throws\nstops the stream.\n\nSet `parseData` to decode each frame's raw data with a custom parser. It runs\nbefore `stop` and event delivery. The default is `JSON.parse`; if the parser\nthrows, the frame keeps its original text.\n\nSee the [transport contract](src/transport/frame.ts) for the function and\nevent types.\n","marimo/AGENTS.md":"# Python Backend Guidelines\n\n## Testing\n\nTests live in `tests/` folder, mirroring `marimo/` structure.\n\n```bash\nuv run --group test pytest tests/path/to/test.py\nuv run --group test-optional pytest tests/path/to/test.py  # with optional deps\nuv run --group test --python 3.11 pytest tests/path/to/test.py  # specific python version\n```\n\nWe should utilize inline-snapshots more often to verify the outputs of objects, functions, etc.\nAvoid individual property assertions, opt for full object comparisons.\n\n```python\nfrom inline_snapshot import snapshot\nfrom dirty_equals import IsStr\n\n\ndef test_function():\n    assert func() == snapshot(\n        {\n            \"prop1\": IsStr(),\n            \"prop2\": \"some string\",\n        }\n    )\n```\n\n## Code Style\n\n- When writing comments, keep them minimal. Comments should explain \"why\", not \"what\"\n\n## Import handling\n\nGenerally, we should import at the top of the file. If there are circular imports, it means the file structure is not optimal. Refactor code to remove circular dependencies.\n\nHeavy dependencies must be imported lazily\n\n```python\ndef get_dataframe():\n    import pandas as pd  # altair, duckdb, numpy, polars, pyarrow, sqlglot, etc.\n\n    return pd.DataFrame()\n```\n","packages/client/README.md":"# @marimo-team/client\n\nConnect to a marimo host to find notebooks, read their state, and request\nedits or execution. A host serves notebooks through the\n[host protocol](../../protocols/host/spec.md). `Client` works with the host's\ncatalog. `NotebookClient` works with one notebook.\n\n## Connect to a host\n\nGive `Client` the host's API base URL and token. These can come from your\napplication's configuration or the host's\n[local discovery record](../../protocols/host/spec.md#local-discovery).\n\n```ts\nimport { Client } from \"@marimo-team/client\";\n\nconst client = new Client(\"http://127.0.0.1:2718/api/marimo/v1\", {\n  token: \"your-token\",\n});\n```\n\nRequests use HTTP and event streams use server-sent events. Pass `fetch`\nalongside `token` to customize requests.\n\n## Find notebooks\n\nThe catalog stream describes the host's notebooks, projects, runtimes, and\nattachments. It also reports the host's capabilities. This example prints\nthe notebooks the host currently knows about.\n\n```ts\nfor await (const event of client.events({ types: [\"notebook\"] })) {\n  if (event.event === \"notebook\") {\n    console.log(event.data.notebook.id, event.data.notebook.name);\n  }\n  if (event.event === \"ready\") break;\n}\n```\n\n`ready` ends the initial snapshot. Breaking out closes the stream. Projects\nmay still be indexing when `ready` arrives, so more notebooks can appear\nafterward.\n\n## Discover local hosts in Node.js\n\n`discoverHosts()` performs [local discovery](../../protocols/host/spec.md#local-discovery)\non macOS and Linux (requires `procps` on Linux). This example lists the notebooks\neach discovered host currently knows about:\n\n```ts\nimport { Client } from \"@marimo-team/client\";\nimport { discoverHosts } from \"@marimo-team/client/node\";\n\nfor await (const host of discoverHosts()) {\n  const client = new Client(host.url, { token: host.token });\n  for await (const event of client.events({ types: [\"notebook\"] })) {\n    if (event.event === \"ready\") break;\n    if (event.event === \"notebook\") {\n      console.log(event.data.notebook.id, event.data.notebook.name);\n    }\n  }\n}\n```\n\n## Work with a notebook\n\nUse an id or a notebook record from the catalog to get a `NotebookClient`.\nThis example reads the document, prints its cell count, and asks the host\nto save it. It assumes the notebook supports `notebook.save`.\n\n```ts\nimport type { DocumentOutput } from \"@marimo-team/client/protocol\";\n\nconst notebook = client.notebook(\"n1\");\nlet document: DocumentOutput | undefined;\n\nfor await (const event of notebook.events({ types: [\"document\"] })) {\n  if (event.event === \"document\") document = event.data.document;\n  if (event.event === \"reset\") document = undefined;\n  if (event.event === \"ready\") break;\n}\n\nif (document === undefined) throw new Error(\"The host did not send a document\");\nconsole.log(`${document.order.length} cells`);\n\nconst result = await notebook.save({ ifMatch: document.etag });\nif (result.ok) {\n  console.log(\"Saved\", result.data.document.etag);\n} else {\n  console.error(result.problem);\n}\n```\n\n`ifMatch` makes the document's etag a precondition. If the document changes\nbefore the save, the host returns a conflict problem. Other actions, such\nas `edit` and `run`, use the same result shape. The notebook's advertised\noperations describe which actions it permits. Invalid request data,\ninvalid responses, and connection failures throw.\n\nYou can also construct a `NotebookClient` directly when you already know\nthe notebook's URL.\n\n## Follow changes\n\nKeep iterating after `ready` to follow changes. Streams reconnect and resume\nfrom their last cursor. If they cannot resume, they deliver `reset` followed\nby a new snapshot. Discard accumulated state on `reset` before applying the\nsnapshot.\n\nTo maintain a notebook list or document state from events, see the\n[reducer guide](REDUCERS.md).\n\nTo follow events over a WebSocket or another connection, see the\n[custom transport guide](TRANSPORTS.md).\n\n## Contributing\n\nThe [host protocol](../../protocols/host/spec.md) explains the model and\nbehavior. [OpenAPI](../../protocols/host/openapi.yaml) defines the routes and\npayloads. `@marimo-team/client/protocol` exports the TypeScript types and Zod\nschemas generated from it.\n\nRun these commands from the repository root. See\n[CONTRIBUTING.md](../../CONTRIBUTING.md) for setup.\n\nThe package is consumed from `dist`. Build it once, or watch for changes\nwhile developing.\n\n```sh\npnpm --dir packages/client build\npnpm --dir packages/client build --watch\n```\n\nAfter changing OpenAPI, regenerate the protocol types, schemas, and\noperation definitions. `codegen:check` checks that generated files match\nthe specification. Generation requires `uv` as well as the Node toolchain:\nboth language generators use the same Python overlay composer. The checked-in\nclient includes experimental features, including Analysis.\n\n```sh\npnpm --dir packages/client codegen\npnpm --dir packages/client codegen:check\n```\n\nThe package commands opt into all experimental features so Turbo builds retain\nthe APIs the handwritten client consumes. Use `codegen:stable` for stable-only\nbindings, using\n`--output-dir` to keep them separate from the client's checked-in bindings. Use\n`--include-experimental=analysis` to select a feature. This selects generated\ncontracts; it does not create a separate stable build of the client package.\nSee the [host protocol tooling](../../protocols/host/README.md) for details.\n\nRun the package's tests and typecheck. Omit `--run` to watch tests while\ndeveloping.\n\n```sh\npnpm --dir packages/client test --run\npnpm --dir packages/client typecheck\n```\n","packages/client/REDUCERS.md":"# Keep state from events\n\nHost state is read over event streams. The catalog stream describes the\nhost's notebooks, projects, runtimes, and attachments. A notebook stream\ndescribes one notebook's document and execution state.\n\nA stream starts with a snapshot of the current state. A `ready` event marks\nthe end of the snapshot. Subsequent events report changes. For example, a\n`notebook` event carries the notebook's current record, and\n`notebook.removed` identifies a notebook that was removed.\n\n`CatalogEvents` and `NotebookEvents` validate incoming events and track the\ncursor used to resume after a disconnect. They deliver events through an\nasync iterator or a subscription. Your application decides which records\nto retain. If the stream cannot resume, it delivers `reset` followed by a\nnew snapshot that replaces the previous state.\n\n## Keep a notebook list\n\nTo keep a notebook list, define a resource that starts with an empty list.\nIts `notebook` handler adds or replaces an entry. Its `notebook.removed`\nhandler removes an entry by id. Each entry keeps only the notebook's id\nand name.\n\nPass the resource to `createCatalogReducer`, then apply each event with\n`reduce(state, event)`. The resulting list is in `state.resources.notebooks`.\nThis example stops at `ready` and prints the list from the snapshot.\n\n```ts\nimport type { NotebookOutput } from \"@marimo-team/client/protocol\";\nimport {\n  Client,\n  createCatalogReducer,\n  type CatalogResource,\n} from \"@marimo-team/client\";\n\ntype NotebookSummary = Pick<NotebookOutput, \"id\" | \"name\">;\n\nconst notebooks: CatalogResource<readonly NotebookSummary[], \"notebook\"> = {\n  initial: [],\n  on: {\n    notebook: (state, { data }) => [\n      ...state.filter((entry) => entry.id !== data.notebook.id),\n      { id: data.notebook.id, name: data.notebook.name },\n    ],\n    \"notebook.removed\": (state, { data }) =>\n      state.filter((entry) => entry.id !== data.id),\n  },\n};\n\nconst reducer = createCatalogReducer({ notebooks });\nconst client = new Client(\"http://127.0.0.1:2718/api/marimo/v1\", {\n  token: \"your-token\",\n});\nlet state = reducer.initial;\n\nfor await (const event of client.events({ types: [\"notebook\"] })) {\n  state = reducer.reduce(state, event);\n  if (event.event === \"ready\") break;\n}\n\nconsole.log(state.resources.notebooks);\n```\n\nThe reducer handles the stream's lifecycle. `ready` changes `state.phase`\nfrom `snapshot` to `live`. `reset` returns the phase to `snapshot` and each\nresource to its initial value. Resources can handle `ready` to finish\nassembling a snapshot. The handler's third argument contains the phase\nbefore the event is applied. It is `snapshot` for the initial `ready` and\n`live` for a `ready` that follows a resumed connection.\n\nHandlers return a new value when state changes and the existing value\notherwise. They must not modify the previous value or perform side effects.\n\nFor a notebook stream, define a `NotebookResource` and pass it to\n`createNotebookReducer`. This reducer also keeps the notebook's record and\nidentity in `notebook` and `notebookId`. It handles `notebook` and\n`notebook.removed` itself. Removing the notebook clears its record and\nresources. A `reset` also clears its identity.\n\n## Follow changes in React\n\nTo keep a notebook list updated in a UI, subscribe to the stream and pass\neach event to the reducer through your store's state update function. This\nhook uses React state. It removes the subscription and closes the stream\nwhen the effect is cleaned up.\n\n```tsx\nimport { useEffect, useState } from \"react\";\n\nfunction useNotebooks(client: Client) {\n  const [state, setState] = useState(reducer.initial);\n\n  useEffect(() => {\n    setState(reducer.initial);\n    const events = client.events({ types: [\"notebook\"] });\n    const unsubscribe = events.subscribe((event) => {\n      setState((current) => reducer.reduce(current, event));\n    });\n    return () => {\n      unsubscribe();\n      events.close();\n    };\n  }, [client]);\n\n  return state;\n}\n```\n\nKeep the client instance stable across renders. Temporary disconnects preserve\nstate while the stream resumes. A `reset` rebuilds it. Pass a second function\nto `subscribe` to surface connection failures in your application. It\nreceives the error when the stream stops.\n\nIf you persist state for a later connection, save its matching cursor and\nreuse the same host, stream, and filter. The stream's cursor tracks received\nevents. When state updates are queued, as in React, it can be ahead of the\nstate you have applied. Resume needs both state and its matching cursor.\n","packages/client/package.json":"# Client Skill\n\nPath: `packages/client/package.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/marimo-team/marimo/HEAD/packages/client/package.json)","packages/client/tsconfig.build.json":"# Client Skill\n\nPath: `packages/client/tsconfig.build.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/marimo-team/marimo/HEAD/packages/client/tsconfig.build.json)","packages/client/tsconfig.json":"# Client Skill\n\nPath: `packages/client/tsconfig.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/marimo-team/marimo/HEAD/packages/client/tsconfig.json)","packages/llm-info/AGENTS.md":"# Llm-info Skill\n\nPath: `packages/llm-info/AGENTS.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/marimo-team/marimo/HEAD/packages/llm-info/AGENTS.md)","packages/llm-info/README.md":"# llm-info Documentation\n\nPath: `packages/llm-info/README.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/marimo-team/marimo/HEAD/packages/llm-info/README.md)","packages/llm-info/package.json":"# Llm-info Skill\n\nPath: `packages/llm-info/package.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/marimo-team/marimo/HEAD/packages/llm-info/package.json)","packages/llm-info/tsconfig.json":"# Llm-info Skill\n\nPath: `packages/llm-info/tsconfig.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/marimo-team/marimo/HEAD/packages/llm-info/tsconfig.json)","packages/lsp/package.json":"# Lsp Skill\n\nPath: `packages/lsp/package.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/marimo-team/marimo/HEAD/packages/lsp/package.json)","packages/lsp/tsconfig.json":"# Lsp Skill\n\nPath: `packages/lsp/tsconfig.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/marimo-team/marimo/HEAD/packages/lsp/tsconfig.json)","packages/lsp/turbo.json":"# Lsp Skill\n\nPath: `packages/lsp/turbo.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/marimo-team/marimo/HEAD/packages/lsp/turbo.json)","packages/openapi/api.yaml":"# Openapi Skill\n\nPath: `packages/openapi/api.yaml`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/marimo-team/marimo/HEAD/packages/openapi/api.yaml)","packages/openapi/package.json":"# Openapi Skill\n\nPath: `packages/openapi/package.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/marimo-team/marimo/HEAD/packages/openapi/package.json)","packages/openapi/tsconfig.json":"# Openapi Skill\n\nPath: `packages/openapi/tsconfig.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/marimo-team/marimo/HEAD/packages/openapi/tsconfig.json)","packages/pytest_changed/README.md":"# pytest_changed Documentation\n\nPath: `packages/pytest_changed/README.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/marimo-team/marimo/HEAD/packages/pytest_changed/README.md)","packages/smart-cells/README.md":"# smart-cells Documentation\n\nPath: `packages/smart-cells/README.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/marimo-team/marimo/HEAD/packages/smart-cells/README.md)","packages/smart-cells/package.json":"# Smart-cells Skill\n\nPath: `packages/smart-cells/package.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/marimo-team/marimo/HEAD/packages/smart-cells/package.json)","packages/smart-cells/tsconfig.json":"# Smart-cells Skill\n\nPath: `packages/smart-cells/tsconfig.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/marimo-team/marimo/HEAD/packages/smart-cells/tsconfig.json)","packages/ts-config/README.md":"# ts-config Documentation\n\nPath: `packages/ts-config/README.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/marimo-team/marimo/HEAD/packages/ts-config/README.md)","packages/ts-config/base.json":"# Ts-config Skill\n\nPath: `packages/ts-config/base.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/marimo-team/marimo/HEAD/packages/ts-config/base.json)","packages/ts-config/library.json":"# Ts-config Skill\n\nPath: `packages/ts-config/library.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/marimo-team/marimo/HEAD/packages/ts-config/library.json)","packages/ts-config/package.json":"# Ts-config Skill\n\nPath: `packages/ts-config/package.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/marimo-team/marimo/HEAD/packages/ts-config/package.json)","examples/ai/tools/README.md":"# tools Documentation\n\nPath: `examples/ai/tools/README.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/marimo-team/marimo/HEAD/examples/ai/tools/README.md)","docs/guides/lint_rules/rules/branch_expression.md":"# Rules Skill\n\nPath: `docs/guides/lint_rules/rules/branch_expression.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/marimo-team/marimo/HEAD/docs/guides/lint_rules/rules/branch_expression.md)","docs/guides/lint_rules/rules/cycle_dependencies.md":"# Rules Skill\n\nPath: `docs/guides/lint_rules/rules/cycle_dependencies.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/marimo-team/marimo/HEAD/docs/guides/lint_rules/rules/cycle_dependencies.md)","docs/guides/lint_rules/rules/empty_cells.md":"# Rules Skill\n\nPath: `docs/guides/lint_rules/rules/empty_cells.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/marimo-team/marimo/HEAD/docs/guides/lint_rules/rules/empty_cells.md)","docs/guides/lint_rules/rules/general_formatting.md":"# Rules Skill\n\nPath: `docs/guides/lint_rules/rules/general_formatting.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/marimo-team/marimo/HEAD/docs/guides/lint_rules/rules/general_formatting.md)","docs/guides/lint_rules/rules/incompatible_import.md":"# Rules Skill\n\nPath: `docs/guides/lint_rules/rules/incompatible_import.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/marimo-team/marimo/HEAD/docs/guides/lint_rules/rules/incompatible_import.md)","docs/guides/lint_rules/rules/incompatible_package.md":"# Rules Skill\n\nPath: `docs/guides/lint_rules/rules/incompatible_package.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/marimo-team/marimo/HEAD/docs/guides/lint_rules/rules/incompatible_package.md)","docs/guides/lint_rules/rules/invalid_syntax.md":"# Rules Skill\n\nPath: `docs/guides/lint_rules/rules/invalid_syntax.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/marimo-team/marimo/HEAD/docs/guides/lint_rules/rules/invalid_syntax.md)","docs/guides/lint_rules/rules/markdown_indentation.md":"# Rules Skill\n\nPath: `docs/guides/lint_rules/rules/markdown_indentation.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/marimo-team/marimo/HEAD/docs/guides/lint_rules/rules/markdown_indentation.md)","docs/guides/lint_rules/rules/misc_log_capture.md":"# Rules Skill\n\nPath: `docs/guides/lint_rules/rules/misc_log_capture.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/marimo-team/marimo/HEAD/docs/guides/lint_rules/rules/misc_log_capture.md)","docs/guides/lint_rules/rules/multiple_definitions.md":"# Rules Skill\n\nPath: `docs/guides/lint_rules/rules/multiple_definitions.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/marimo-team/marimo/HEAD/docs/guides/lint_rules/rules/multiple_definitions.md)","docs/guides/lint_rules/rules/parse_stderr.md":"# Rules Skill\n\nPath: `docs/guides/lint_rules/rules/parse_stderr.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/marimo-team/marimo/HEAD/docs/guides/lint_rules/rules/parse_stderr.md)","docs/guides/lint_rules/rules/parse_stdout.md":"# Rules Skill\n\nPath: `docs/guides/lint_rules/rules/parse_stdout.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/marimo-team/marimo/HEAD/docs/guides/lint_rules/rules/parse_stdout.md)","docs/guides/lint_rules/rules/private_import_alias.md":"# Rules Skill\n\nPath: `docs/guides/lint_rules/rules/private_import_alias.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/marimo-team/marimo/HEAD/docs/guides/lint_rules/rules/private_import_alias.md)","docs/guides/lint_rules/rules/reusable_definition_order.md":"# Rules Skill\n\nPath: `docs/guides/lint_rules/rules/reusable_definition_order.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/marimo-team/marimo/HEAD/docs/guides/lint_rules/rules/reusable_definition_order.md)","docs/guides/lint_rules/rules/self_import.md":"# Rules Skill\n\nPath: `docs/guides/lint_rules/rules/self_import.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/marimo-team/marimo/HEAD/docs/guides/lint_rules/rules/self_import.md)","docs/guides/lint_rules/rules/setup_cell_dependencies.md":"# Rules Skill\n\nPath: `docs/guides/lint_rules/rules/setup_cell_dependencies.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/marimo-team/marimo/HEAD/docs/guides/lint_rules/rules/setup_cell_dependencies.md)","docs/guides/lint_rules/rules/sql_parse_error.md":"# Rules Skill\n\nPath: `docs/guides/lint_rules/rules/sql_parse_error.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/marimo-team/marimo/HEAD/docs/guides/lint_rules/rules/sql_parse_error.md)","docs/guides/lint_rules/rules/unparsable_cells.md":"# Rules Skill\n\nPath: `docs/guides/lint_rules/rules/unparsable_cells.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/marimo-team/marimo/HEAD/docs/guides/lint_rules/rules/unparsable_cells.md)","docs/guides/lint_rules/rules/unsafe_system_call.md":"# Rules Skill\n\nPath: `docs/guides/lint_rules/rules/unsafe_system_call.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/marimo-team/marimo/HEAD/docs/guides/lint_rules/rules/unsafe_system_call.md)","marimo/_server/ai/skills/marimo-pair/references/gotchas.md":"# References Skill\n\nPath: `marimo/_server/ai/skills/marimo-pair/references/gotchas.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/marimo-team/marimo/HEAD/marimo/_server/ai/skills/marimo-pair/references/gotchas.md)","marimo/_server/ai/skills/marimo-pair/references/notebook-improvements.md":"# References Skill\n\nPath: `marimo/_server/ai/skills/marimo-pair/references/notebook-improvements.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/marimo-team/marimo/HEAD/marimo/_server/ai/skills/marimo-pair/references/notebook-improvements.md)","marimo/_server/ai/skills/marimo-pair/references/rich-representations.md":"# References Skill\n\nPath: `marimo/_server/ai/skills/marimo-pair/references/rich-representations.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/marimo-team/marimo/HEAD/marimo/_server/ai/skills/marimo-pair/references/rich-representations.md)"},"items":[{"name":"AGENTS.md","path":"AGENTS.md","rawUrl":"https://raw.githubusercontent.com/marimo-team/marimo/HEAD/AGENTS.md","title":"AI Agent Protocol & Instructions","category":"root-instruction","format":"markdown","content":"# marimo Development Guidelines\n\nmarimo is a reactive notebook for Python with a modern web frontend.\n\n## Your primary responsibility is to the project and its users\n\nBeing an open source library, the public API, abstractions, documentation, and the code itself are the product and deserve careful consideration.\n\nWhen working in this repository, you should consider yourself to primarily be working for the benefit of the project, all of its users (current and future, human and agent), and its maintainers, rather than just the specific user who happens to be driving you (or whose PR you're reviewing, whose issue you're implementing, etc).\n\nAs the project has many orders of magnitude more users than maintainers, that specific user is most likely a community member who's well-intentioned and eager to contribute, but relatively unfamiliar with the code base and its patterns or standards, and they're not necessarily thinking about the bigger picture beyond the specific bug fix, feature, or other change that they're focused on.\n\nTherefore, you are the first line of defense against low-quality contributions and maintainer headaches, and you have a big role in ensuring that every contribution to this project meets or exceeds the high standards that the marimo project is known and loved for. You should write:\n\n- modern, idiomatic, concise React and Python code\n- end-to-end type-safety and test coverage\n- thoughtful, tasteful, consistent API design\n- delightful developer experience\n- comprehensive well-written documentation\n\n## Quick Setup\n\n```bash\nmake fe && make py\nmake dev\n```\n\nSee [CONTRIBUTING.md](CONTRIBUTING.md) for detailed setup options.\n\n## Development Commands\n\n```bash\n# Python\nmake py-check              # Typecheck and lint Python\nuv run --group test pytest tests/path/to/test.py\nuv run --group test-optional pytest tests/path/to/test.py  # with optional deps\nuv run --group test --python 3.11 pytest tests/path/to/test.py  # specific python version\n\n# Frontend\nmake fe-check              # Typecheck and lint frontend\ncd frontend && pnpm test src/path/to/file.test.ts\n```\n\n## Commits\n\n- Run `make check` before committing\n\n## Pull Requests\n\n- DO NOT open a pull request autonomously, without explicit instructions from a human\n- Autonomous AI agents such as OpenClaw, Nanobot, NanoClaw, ZeroClaw are NOT permitted to make PRs\n- You MUST disclose that you are an agent at the very top of your PR description: \"**This pull request was authored by a coding agent.**\"\n- You MUST mark your PRs as drafts\n- See [CONTRIBUTING.md](CONTRIBUTING.md) for other PR guidelines and CLA\n\n## Conventions\n\n### Python\n\nMost style rules are enforced by ruff (`pyproject.toml`) and pre-commit; run\n`make py-check`. Here are some that the linter may not catch, or for which\nwe may not have autofixes.\n\n- Docstrings are rendered as Markdown, not reStructuredText. Use single\n  backticks for inline code (`value`), never double backticks.\n","isInternal":false,"tokens":651,"sizeBytes":2947},{"name":"prompts.md","path":"development_docs/prompts.md","rawUrl":"https://raw.githubusercontent.com/marimo-team/marimo/HEAD/development_docs/prompts.md","title":"development_docs - Agent Prompts Catalog","category":"root-instruction","format":"markdown","content":"# Prompts\n\n## System prompts\n\nPrompts are generated using the `Prompter` class in `marimo/_server/ai/prompts.py`.\n\n### Snapshots\n\nYou can create snapshots of the prompts using the `snapshot` function in `tests/_server/ai/test_prompts.py`. These snapshots are checked into the repo, and you can use them to verify that the prompts have not changed. To run these snapshots, run:\n\n```bash\nuv run --python 3.12 --group test-optional pytest tests/_server/ai/test_prompts.py\n```\n","isInternal":false,"tokens":118,"sizeBytes":473},{"name":"AGENTS.md","path":"frontend/AGENTS.md","rawUrl":"https://raw.githubusercontent.com/marimo-team/marimo/HEAD/frontend/AGENTS.md","title":"frontend - AI Agent Protocol & Instructions","category":"root-instruction","format":"markdown","content":"# Frontend Guidelines\n\n## Key Principles\n\n- Write clear, maintainable code over clever/short syntax\n- Use TypeScript with proper typing for all code\n- Use functional programming patterns; avoid classes\n- Favor composition over inheritance\n- Reduce code duplication, if you see code that is repeated, refactor it to a function or component. This standardizes the codebase.\n\n## Naming Conventions\n\n- **Directories**: lowercase with dashes (`components/auth-wizard/`)\n- **Components**: PascalCase (`DashboardMenu.tsx`)\n- **Variables**: descriptive with auxiliary verbs (`isLoading`, `hasError`, `canSubmit`)\n\n## Testing\n\n### Unit Tests\n\nTests live alongside source files or in `__tests__` directories.\n\n```bash\npnpm turbo --filter @marimo-team/frontend test                            # All tests\npnpm turbo --filter @marimo-team/frontend test src/__tests__/lru.test.ts  # Specific file\n```\n\nBest practices:\n- test edge cases\n- use descriptive names\n- group with `describe`\n- prefer complete assertions over individual property checks (e.g., `expect(result).toEqual(expected)` rather than checking each property separately)\n\n### E2E Tests\n\nE2E tests use Playwright. See [e2e-tests/README.md](e2e-tests/README.md) for details.\n\n## Code Quality\n\nAvoid as much as possible using type assertions as they can cause runtime errors. Instead, use type guards, type predicates and error handling.\n```typescript\ncallFunction(x as T) // Avoid this\n```\n\n- Use logNever or assertNever to handle exhaustive switch cases.\n```typescript\nswitch (value) {\n  case \"a\":\n    break;\n  default:\n    logNever(value);\n}\n```\n\n- Keep comments minimal. Comments should only explain \"why\", not \"what\".\n","isInternal":false,"tokens":374,"sizeBytes":1670},{"name":"AGENTS.md","path":"marimo/AGENTS.md","rawUrl":"https://raw.githubusercontent.com/marimo-team/marimo/HEAD/marimo/AGENTS.md","title":"marimo - AI Agent Protocol & Instructions","category":"root-instruction","format":"markdown","content":"# Python Backend Guidelines\n\n## Testing\n\nTests live in `tests/` folder, mirroring `marimo/` structure.\n\n```bash\nuv run --group test pytest tests/path/to/test.py\nuv run --group test-optional pytest tests/path/to/test.py  # with optional deps\nuv run --group test --python 3.11 pytest tests/path/to/test.py  # specific python version\n```\n\nWe should utilize inline-snapshots more often to verify the outputs of objects, functions, etc.\nAvoid individual property assertions, opt for full object comparisons.\n\n```python\nfrom inline_snapshot import snapshot\nfrom dirty_equals import IsStr\n\n\ndef test_function():\n    assert func() == snapshot(\n        {\n            \"prop1\": IsStr(),\n            \"prop2\": \"some string\",\n        }\n    )\n```\n\n## Code Style\n\n- When writing comments, keep them minimal. Comments should explain \"why\", not \"what\"\n\n## Import handling\n\nGenerally, we should import at the top of the file. If there are circular imports, it means the file structure is not optimal. Refactor code to remove circular dependencies.\n\nHeavy dependencies must be imported lazily\n\n```python\ndef get_dataframe():\n    import pandas as pd  # altair, duckdb, numpy, polars, pyarrow, sqlglot, etc.\n\n    return pd.DataFrame()\n```\n","isInternal":false,"tokens":279,"sizeBytes":1217},{"name":"DESIGN.md","path":"DESIGN.md","rawUrl":"https://raw.githubusercontent.com/marimo-team/marimo/HEAD/DESIGN.md","title":"marimo","category":"project-spec","format":"markdown","content":"---\nversion: alpha\nname: marimo\ndescription: Design system for marimo, a reactive Python notebook for reproducible, git-friendly, deployable work.\ncolors:\n  background: \"#FFFFFF\"\n  background-dark: \"#181C1A\"\n  foreground: \"#0F172A\"\n  foreground-dark: \"#ECEEED\"\n  surface-muted: \"#F1F5F9\"\n  surface-muted-dark: \"#020303\"\n  muted-foreground: \"#64748B\"\n  muted-foreground-dark: \"#AAB2AF\"\n  popover: \"#FFFFFF\"\n  popover-dark: \"#252927\"\n  popover-foreground: \"#0F172A\"\n  popover-foreground-dark: \"#AAB2AF\"\n  card: \"#FFFFFF\"\n  card-dark: \"#252927\"\n  card-foreground: \"#0F172A\"\n  card-foreground-dark: \"#C0C6C3\"\n  border: \"#E2E8F0\"\n  border-dark: \"#3B403E\"\n  input: \"#A3A3A3\"\n  input-dark: \"#474C4A\"\n  primary: \"#0880EA\"\n  primary-dark: \"#28879F\"\n  on-primary: \"#F8FAFC\"\n  on-primary-dark: \"#B6ECF7\"\n  secondary: \"#F1F5F9\"\n  secondary-dark: \"#ECEEED\"\n  on-secondary: \"#0F172A\"\n  on-secondary-dark: \"#252927\"\n  accent: \"#EDF6FF\"\n  accent-dark: \"#1D5B6A\"\n  on-accent: \"#0B68CB\"\n  on-accent-dark: \"#B6ECF7\"\n  ring: \"#94A3B8\"\n  ring-dark: \"#2870BD\"\n  destructive: \"#E5484D\"\n  destructive-dark: \"#72232D\"\n  destructive-hover: \"#DC3E42\"\n  destructive-hover-dark: \"#8C333A\"\n  destructive-border: \"#CE2C31\"\n  destructive-border-dark: \"#FF9592\"\n  on-destructive: \"#FFFCFC\"\n  on-destructive-dark: \"#FFD1D9\"\n  error: \"#E5484D\"\n  error-dark: \"#72232D\"\n  on-error: \"#FFFCFC\"\n  on-error-dark: \"#FFD1D9\"\n  success: \"#46A758\"\n  success-dark: \"#2D5736\"\n  success-hover: \"#3E9B4F\"\n  success-hover-dark: \"#366740\"\n  success-border: \"#2A7E3B\"\n  success-border-dark: \"#71D083\"\n  on-success: \"#FBFEFB\"\n  on-success-dark: \"#C2F0C2\"\n  action: \"#FFE629\"\n  action-dark: \"#524202\"\n  action-hover: \"#FFDC00\"\n  action-hover-dark: \"#665417\"\n  action-border: \"#9E6C00\"\n  action-border-dark: \"#F5E147\"\n  on-action: \"#473B1F\"\n  on-action-dark: \"#F6EEB4\"\n  link: \"#0B68CB\"\n  link-dark: \"#479BF5\"\n  link-visited: \"#8E4EC6\"\n  link-visited-dark: \"#BF9BDF\"\n  stale: \"#EBE2CC\"\n  stale-dark: \"#525342\"\n  code-background: \"#FFFFFF\"\n  code-background-dark: \"#282C34\"\n  surface: \"#FFFFFF\"\n  surface-dark: \"#252927\"\n  code-foreground: \"#000000\"\n  code-foreground-dark: \"#ABB2BF\"\n  data-grid-accent: \"#7C3AED\"\ntypography:\n  body-md:\n    fontFamily: PT Sans\n    fontSize: 1rem\n    fontWeight: \"400\"\n    lineHeight: 1.75rem\n    letterSpacing: 0em\n  body-sm:\n    fontFamily: PT Sans\n    fontSize: 0.875rem\n    fontWeight: \"400\"\n    lineHeight: 1.25rem\n    letterSpacing: 0em\n  label-md:\n    fontFamily: PT Sans\n    fontSize: 0.875rem\n    fontWeight: \"500\"\n    lineHeight: 1.25rem\n    letterSpacing: 0em\n  label-xs:\n    fontFamily: PT Sans\n    fontSize: 0.75rem\n    fontWeight: \"600\"\n    lineHeight: 1rem\n    letterSpacing: 0em\n  markdown-heading:\n    fontFamily: Lora\n    fontSize: 1.875rem\n    fontWeight: \"600\"\n    lineHeight: 2.25rem\n    letterSpacing: -0.025em\n  code-editor:\n    fontFamily: Fira Mono\n    fontSize: 14px\n    fontWeight: \"400\"\n    lineHeight: 1.25rem\n    letterSpacing: 0em\n  slide-h1:\n    fontFamily: PT Sans\n    fontSize: 4.375rem\n    fontWeight: \"600\"\n    lineHeight: \"1.2\"\n    letterSpacing: 0em\nrounded:\n  sm: 4px\n  DEFAULT: 8px\n  md: 6px\n  lg: 8px\n  cell: 10px\n  xl: 0.75rem\n  full: 9999px\nspacing:\n  unit: 0.5rem\n  xs: 0.25rem\n  sm: 0.5rem\n  md: 1rem\n  lg: 1.5rem\n  xl: 3rem\n  content-compact: 740px\n  content-medium: 1110px\n  content-wide: 1400px\n  grid-row-height: 20px\n  grid-columns: \"24\"\ncomponents:\n  app-shell:\n    backgroundColor: \"{colors.background}\"\n    textColor: \"{colors.foreground}\"\n    typography: \"{typography.body-md}\"\n  cell:\n    backgroundColor: \"{colors.surface}\"\n    textColor: \"{colors.foreground}\"\n    typography: \"{typography.body-md}\"\n    rounded: \"{rounded.cell}\"\n    width: 100%\n  output-area:\n    backgroundColor: \"{colors.surface}\"\n    textColor: \"{colors.foreground}\"\n    typography: \"{typography.body-md}\"\n    padding: 1rem\n    width: 100%\n  code-editor:\n    backgroundColor: \"{colors.code-background}\"\n    textColor: \"{colors.code-foreground}\"\n    typography: \"{typography.code-editor}\"\n    width: 100%\n  button-primary:\n    backgroundColor: \"{colors.primary}\"\n    textColor: \"{colors.on-primary}\"\n    typography: \"{typography.label-md}\"\n    rounded: \"{rounded.md}\"\n    height: 2.25rem\n  button-action:\n    backgroundColor: \"{colors.action}\"\n    textColor: \"{colors.on-action}\"\n    typography: \"{typography.label-md}\"\n    rounded: \"{rounded.md}\"\n    height: 2.25rem\n  input:\n    backgroundColor: \"{colors.background}\"\n    textColor: \"{colors.foreground}\"\n    typography: \"{typography.body-sm}\"\n    rounded: \"{rounded.sm}\"\n    height: 1.5rem\n  data-table:\n    backgroundColor: \"{colors.surface}\"\n    textColor: \"{colors.foreground}\"\n    typography: \"{typography.body-sm}\"\n    width: 100%\n---\n\n## Brand Assets\n\n- Logo SVG: https://raw.githubusercontent.com/marimo-team/marimo/main/docs/_static/marimo-logotype-thick.svg\n- Preserve the original aspect ratio.\n- Do not recolor unless explicitly requested.\n\n## Visual Character\n\n- Compact, software-native, and utilitarian.\n- White or near-black work surfaces with slate borders and muted secondary text.\n- Restrained blue for primary interaction; yellow for action, stale, or needs-run states.\n- Avoid decorative gradients, marketing-style heroes, nested cards, and one-off palettes.\n\n## Color\n\n- Use background, surface, foreground, border, and muted tokens for structure.\n- Use primary for primary actions, selection, progress, and clear focus only.\n- Use action and stale colors for manual action or freshness state, not generic warning.\n- Use destructive, error, and success colors only for their semantic states.\n- Preserve light and dark token pairs whenever a color appears in both modes.\n\n## Typography\n\n- Use PT Sans for UI and prose, Lora for authored markdown headings, and Fira Mono for code-like values.\n- Keep control text compact and legible.\n- Do not add viewport-based type scaling beyond marimo's app defaults.\n\n## Surfaces\n\n- Use borders first and subtle shadows second.\n- Cells, outputs, editors, markdown, tables, and data grids should be full-width and overflow-safe.\n- Keep data UI dense and inspectable: stable columns, predictable overflow, readable headers, and no decorative framing around tables or charts.\n- Cards are for repeated items, dialogs, or genuinely framed tools; do not style page sections as cards.\n\n## Components\n\n- Buttons should be compact, label-like, focusable, and drawn from primary, secondary, or action semantics.\n- Icon buttons should use familiar existing icons and tooltips for unclear actions.\n- Inputs, selects, and textareas should be compact, bordered, readable, and use code typography only for code-like values.\n- Tabs, menus, popovers, dialogs, and tooltips should use semantic surfaces, borders, focus states, and restrained shadow.\n- Runtime states should pair color with labels, icons, borders, position, or shape.\n\n## Motion\n\nUse short transitions for hover, focus, loading, resize, drag, and stale-output changes. Avoid decorative animation.\n","frontmatter":{"version":"alpha","name":"marimo","description":"Design system for marimo, a reactive Python notebook for reproducible, git-friendly, deployable work.","colors":{"background":"#FFFFFF","background-dark":"#181C1A","foreground":"#0F172A","foreground-dark":"#ECEEED","surface-muted":"#F1F5F9","surface-muted-dark":"#020303","muted-foreground":"#64748B","muted-foreground-dark":"#AAB2AF","popover":"#FFFFFF","popover-dark":"#252927","popover-foreground":"#0F172A","popover-foreground-dark":"#AAB2AF","card":"#FFFFFF","card-dark":"#252927","card-foreground":"#0F172A","card-foreground-dark":"#C0C6C3","border":"#E2E8F0","border-dark":"#3B403E","input":"#A3A3A3","input-dark":"#474C4A","primary":"#0880EA","primary-dark":"#28879F","on-primary":"#F8FAFC","on-primary-dark":"#B6ECF7","secondary":"#F1F5F9","secondary-dark":"#ECEEED","on-secondary":"#0F172A","on-secondary-dark":"#252927","accent":"#EDF6FF","accent-dark":"#1D5B6A","on-accent":"#0B68CB","on-accent-dark":"#B6ECF7","ring":"#94A3B8","ring-dark":"#2870BD","destructive":"#E5484D","destructive-dark":"#72232D","destructive-hover":"#DC3E42","destructive-hover-dark":"#8C333A","destructive-border":"#CE2C31","destructive-border-dark":"#FF9592","on-destructive":"#FFFCFC","on-destructive-dark":"#FFD1D9","error":"#E5484D","error-dark":"#72232D","on-error":"#FFFCFC","on-error-dark":"#FFD1D9","success":"#46A758","success-dark":"#2D5736","success-hover":"#3E9B4F","success-hover-dark":"#366740","success-border":"#2A7E3B","success-border-dark":"#71D083","on-success":"#FBFEFB","on-success-dark":"#C2F0C2","action":"#FFE629","action-dark":"#524202","action-hover":"#FFDC00","action-hover-dark":"#665417","action-border":"#9E6C00","action-border-dark":"#F5E147","on-action":"#473B1F","on-action-dark":"#F6EEB4","link":"#0B68CB","link-dark":"#479BF5","link-visited":"#8E4EC6","link-visited-dark":"#BF9BDF","stale":"#EBE2CC","stale-dark":"#525342","code-background":"#FFFFFF","code-background-dark":"#282C34","surface":"#FFFFFF","surface-dark":"#252927","code-foreground":"#000000","code-foreground-dark":"#ABB2BF","data-grid-accent":"#7C3AED"},"typography":{"body-md":{"fontFamily":"PT Sans","fontSize":"1rem","fontWeight":"400","lineHeight":"1.75rem","letterSpacing":"0em"},"body-sm":{"fontFamily":"PT Sans","fontSize":"0.875rem","fontWeight":"400","lineHeight":"1.25rem","letterSpacing":"0em"},"label-md":{"fontFamily":"PT Sans","fontSize":"0.875rem","fontWeight":"500","lineHeight":"1.25rem","letterSpacing":"0em"},"label-xs":{"fontFamily":"PT Sans","fontSize":"0.75rem","fontWeight":"600","lineHeight":"1rem","letterSpacing":"0em"},"markdown-heading":{"fontFamily":"Lora","fontSize":"1.875rem","fontWeight":"600","lineHeight":"2.25rem","letterSpacing":"-0.025em"},"code-editor":{"fontFamily":"Fira Mono","fontSize":"14px","fontWeight":"400","lineHeight":"1.25rem","letterSpacing":"0em"},"slide-h1":{"fontFamily":"PT Sans","fontSize":"4.375rem","fontWeight":"600","lineHeight":"1.2","letterSpacing":"0em"}},"rounded":{"sm":"4px","DEFAULT":"8px","md":"6px","lg":"8px","cell":"10px","xl":"0.75rem","full":"9999px"},"spacing":{"unit":"0.5rem","xs":"0.25rem","sm":"0.5rem","md":"1rem","lg":"1.5rem","xl":"3rem","content-compact":"740px","content-medium":"1110px","content-wide":"1400px","grid-row-height":"20px","grid-columns":"24"},"components":{"app-shell":{"backgroundColor":"{colors.background}","textColor":"{colors.foreground}","typography":"{typography.body-md}"},"cell":{"backgroundColor":"{colors.surface}","textColor":"{colors.foreground}","typography":"{typography.body-md}","rounded":"{rounded.cell}","width":"100%"},"output-area":{"backgroundColor":"{colors.surface}","textColor":"{colors.foreground}","typography":"{typography.body-md}","padding":"1rem","width":"100%"},"code-editor":{"backgroundColor":"{colors.code-background}","textColor":"{colors.code-foreground}","typography":"{typography.code-editor}","width":"100%"},"button-primary":{"backgroundColor":"{colors.primary}","textColor":"{colors.on-primary}","typography":"{typography.label-md}","rounded":"{rounded.md}","height":"2.25rem"},"button-action":{"backgroundColor":"{colors.action}","textColor":"{colors.on-action}","typography":"{typography.label-md}","rounded":"{rounded.md}","height":"2.25rem"},"input":{"backgroundColor":"{colors.background}","textColor":"{colors.foreground}","typography":"{typography.body-sm}","rounded":"{rounded.sm}","height":"1.5rem"},"data-table":{"backgroundColor":"{colors.surface}","textColor":"{colors.foreground}","typography":"{typography.body-sm}","width":"100%"}}},"isInternal":false,"tokens":1994,"sizeBytes":6958},{"name":"branch_expression.md","path":"docs/guides/lint_rules/rules/branch_expression.md","rawUrl":"https://raw.githubusercontent.com/marimo-team/marimo/HEAD/docs/guides/lint_rules/rules/branch_expression.md","title":"Rules Skill","category":"anthropic-skill","format":"markdown","content":"# Rules Skill\n\nPath: `docs/guides/lint_rules/rules/branch_expression.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/marimo-team/marimo/HEAD/docs/guides/lint_rules/rules/branch_expression.md)","tokens":300,"sizeBytes":211},{"name":"cycle_dependencies.md","path":"docs/guides/lint_rules/rules/cycle_dependencies.md","rawUrl":"https://raw.githubusercontent.com/marimo-team/marimo/HEAD/docs/guides/lint_rules/rules/cycle_dependencies.md","title":"Rules Skill","category":"anthropic-skill","format":"markdown","content":"# Rules Skill\n\nPath: `docs/guides/lint_rules/rules/cycle_dependencies.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/marimo-team/marimo/HEAD/docs/guides/lint_rules/rules/cycle_dependencies.md)","tokens":300,"sizeBytes":213},{"name":"empty_cells.md","path":"docs/guides/lint_rules/rules/empty_cells.md","rawUrl":"https://raw.githubusercontent.com/marimo-team/marimo/HEAD/docs/guides/lint_rules/rules/empty_cells.md","title":"Rules Skill","category":"anthropic-skill","format":"markdown","content":"# Rules Skill\n\nPath: `docs/guides/lint_rules/rules/empty_cells.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/marimo-team/marimo/HEAD/docs/guides/lint_rules/rules/empty_cells.md)","tokens":300,"sizeBytes":199},{"name":"general_formatting.md","path":"docs/guides/lint_rules/rules/general_formatting.md","rawUrl":"https://raw.githubusercontent.com/marimo-team/marimo/HEAD/docs/guides/lint_rules/rules/general_formatting.md","title":"Rules Skill","category":"anthropic-skill","format":"markdown","content":"# Rules Skill\n\nPath: `docs/guides/lint_rules/rules/general_formatting.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/marimo-team/marimo/HEAD/docs/guides/lint_rules/rules/general_formatting.md)","tokens":300,"sizeBytes":213},{"name":"incompatible_import.md","path":"docs/guides/lint_rules/rules/incompatible_import.md","rawUrl":"https://raw.githubusercontent.com/marimo-team/marimo/HEAD/docs/guides/lint_rules/rules/incompatible_import.md","title":"Rules Skill","category":"anthropic-skill","format":"markdown","content":"# Rules Skill\n\nPath: `docs/guides/lint_rules/rules/incompatible_import.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/marimo-team/marimo/HEAD/docs/guides/lint_rules/rules/incompatible_import.md)","tokens":300,"sizeBytes":215},{"name":"incompatible_package.md","path":"docs/guides/lint_rules/rules/incompatible_package.md","rawUrl":"https://raw.githubusercontent.com/marimo-team/marimo/HEAD/docs/guides/lint_rules/rules/incompatible_package.md","title":"Rules Skill","category":"anthropic-skill","format":"markdown","content":"# Rules Skill\n\nPath: `docs/guides/lint_rules/rules/incompatible_package.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/marimo-team/marimo/HEAD/docs/guides/lint_rules/rules/incompatible_package.md)","tokens":300,"sizeBytes":217},{"name":"invalid_syntax.md","path":"docs/guides/lint_rules/rules/invalid_syntax.md","rawUrl":"https://raw.githubusercontent.com/marimo-team/marimo/HEAD/docs/guides/lint_rules/rules/invalid_syntax.md","title":"Rules Skill","category":"anthropic-skill","format":"markdown","content":"# Rules Skill\n\nPath: `docs/guides/lint_rules/rules/invalid_syntax.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/marimo-team/marimo/HEAD/docs/guides/lint_rules/rules/invalid_syntax.md)","tokens":300,"sizeBytes":205},{"name":"markdown_indentation.md","path":"docs/guides/lint_rules/rules/markdown_indentation.md","rawUrl":"https://raw.githubusercontent.com/marimo-team/marimo/HEAD/docs/guides/lint_rules/rules/markdown_indentation.md","title":"Rules Skill","category":"anthropic-skill","format":"markdown","content":"# Rules Skill\n\nPath: `docs/guides/lint_rules/rules/markdown_indentation.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/marimo-team/marimo/HEAD/docs/guides/lint_rules/rules/markdown_indentation.md)","tokens":300,"sizeBytes":217},{"name":"misc_log_capture.md","path":"docs/guides/lint_rules/rules/misc_log_capture.md","rawUrl":"https://raw.githubusercontent.com/marimo-team/marimo/HEAD/docs/guides/lint_rules/rules/misc_log_capture.md","title":"Rules Skill","category":"anthropic-skill","format":"markdown","content":"# Rules Skill\n\nPath: `docs/guides/lint_rules/rules/misc_log_capture.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/marimo-team/marimo/HEAD/docs/guides/lint_rules/rules/misc_log_capture.md)","tokens":300,"sizeBytes":209},{"name":"multiple_definitions.md","path":"docs/guides/lint_rules/rules/multiple_definitions.md","rawUrl":"https://raw.githubusercontent.com/marimo-team/marimo/HEAD/docs/guides/lint_rules/rules/multiple_definitions.md","title":"Rules Skill","category":"anthropic-skill","format":"markdown","content":"# Rules Skill\n\nPath: `docs/guides/lint_rules/rules/multiple_definitions.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/marimo-team/marimo/HEAD/docs/guides/lint_rules/rules/multiple_definitions.md)","tokens":300,"sizeBytes":217},{"name":"parse_stderr.md","path":"docs/guides/lint_rules/rules/parse_stderr.md","rawUrl":"https://raw.githubusercontent.com/marimo-team/marimo/HEAD/docs/guides/lint_rules/rules/parse_stderr.md","title":"Rules Skill","category":"anthropic-skill","format":"markdown","content":"# Rules Skill\n\nPath: `docs/guides/lint_rules/rules/parse_stderr.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/marimo-team/marimo/HEAD/docs/guides/lint_rules/rules/parse_stderr.md)","tokens":300,"sizeBytes":201},{"name":"parse_stdout.md","path":"docs/guides/lint_rules/rules/parse_stdout.md","rawUrl":"https://raw.githubusercontent.com/marimo-team/marimo/HEAD/docs/guides/lint_rules/rules/parse_stdout.md","title":"Rules Skill","category":"anthropic-skill","format":"markdown","content":"# Rules Skill\n\nPath: `docs/guides/lint_rules/rules/parse_stdout.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/marimo-team/marimo/HEAD/docs/guides/lint_rules/rules/parse_stdout.md)","tokens":300,"sizeBytes":201},{"name":"private_import_alias.md","path":"docs/guides/lint_rules/rules/private_import_alias.md","rawUrl":"https://raw.githubusercontent.com/marimo-team/marimo/HEAD/docs/guides/lint_rules/rules/private_import_alias.md","title":"Rules Skill","category":"anthropic-skill","format":"markdown","content":"# Rules Skill\n\nPath: `docs/guides/lint_rules/rules/private_import_alias.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/marimo-team/marimo/HEAD/docs/guides/lint_rules/rules/private_import_alias.md)","tokens":300,"sizeBytes":217},{"name":"reusable_definition_order.md","path":"docs/guides/lint_rules/rules/reusable_definition_order.md","rawUrl":"https://raw.githubusercontent.com/marimo-team/marimo/HEAD/docs/guides/lint_rules/rules/reusable_definition_order.md","title":"Rules Skill","category":"anthropic-skill","format":"markdown","content":"# Rules Skill\n\nPath: `docs/guides/lint_rules/rules/reusable_definition_order.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/marimo-team/marimo/HEAD/docs/guides/lint_rules/rules/reusable_definition_order.md)","tokens":300,"sizeBytes":227},{"name":"self_import.md","path":"docs/guides/lint_rules/rules/self_import.md","rawUrl":"https://raw.githubusercontent.com/marimo-team/marimo/HEAD/docs/guides/lint_rules/rules/self_import.md","title":"Rules Skill","category":"anthropic-skill","format":"markdown","content":"# Rules Skill\n\nPath: `docs/guides/lint_rules/rules/self_import.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/marimo-team/marimo/HEAD/docs/guides/lint_rules/rules/self_import.md)","tokens":300,"sizeBytes":199},{"name":"setup_cell_dependencies.md","path":"docs/guides/lint_rules/rules/setup_cell_dependencies.md","rawUrl":"https://raw.githubusercontent.com/marimo-team/marimo/HEAD/docs/guides/lint_rules/rules/setup_cell_dependencies.md","title":"Rules Skill","category":"anthropic-skill","format":"markdown","content":"# Rules Skill\n\nPath: `docs/guides/lint_rules/rules/setup_cell_dependencies.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/marimo-team/marimo/HEAD/docs/guides/lint_rules/rules/setup_cell_dependencies.md)","tokens":300,"sizeBytes":223},{"name":"sql_parse_error.md","path":"docs/guides/lint_rules/rules/sql_parse_error.md","rawUrl":"https://raw.githubusercontent.com/marimo-team/marimo/HEAD/docs/guides/lint_rules/rules/sql_parse_error.md","title":"Rules Skill","category":"anthropic-skill","format":"markdown","content":"# Rules Skill\n\nPath: `docs/guides/lint_rules/rules/sql_parse_error.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/marimo-team/marimo/HEAD/docs/guides/lint_rules/rules/sql_parse_error.md)","tokens":300,"sizeBytes":207},{"name":"unparsable_cells.md","path":"docs/guides/lint_rules/rules/unparsable_cells.md","rawUrl":"https://raw.githubusercontent.com/marimo-team/marimo/HEAD/docs/guides/lint_rules/rules/unparsable_cells.md","title":"Rules Skill","category":"anthropic-skill","format":"markdown","content":"# Rules Skill\n\nPath: `docs/guides/lint_rules/rules/unparsable_cells.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/marimo-team/marimo/HEAD/docs/guides/lint_rules/rules/unparsable_cells.md)","tokens":300,"sizeBytes":209},{"name":"unsafe_system_call.md","path":"docs/guides/lint_rules/rules/unsafe_system_call.md","rawUrl":"https://raw.githubusercontent.com/marimo-team/marimo/HEAD/docs/guides/lint_rules/rules/unsafe_system_call.md","title":"Rules Skill","category":"anthropic-skill","format":"markdown","content":"# Rules Skill\n\nPath: `docs/guides/lint_rules/rules/unsafe_system_call.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/marimo-team/marimo/HEAD/docs/guides/lint_rules/rules/unsafe_system_call.md)","tokens":300,"sizeBytes":213},{"name":"gotchas.md","path":"marimo/_server/ai/skills/marimo-pair/references/gotchas.md","rawUrl":"https://raw.githubusercontent.com/marimo-team/marimo/HEAD/marimo/_server/ai/skills/marimo-pair/references/gotchas.md","title":"References Skill","category":"anthropic-skill","format":"markdown","content":"# References Skill\n\nPath: `marimo/_server/ai/skills/marimo-pair/references/gotchas.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/marimo-team/marimo/HEAD/marimo/_server/ai/skills/marimo-pair/references/gotchas.md)","tokens":300,"sizeBytes":234},{"name":"notebook-improvements.md","path":"marimo/_server/ai/skills/marimo-pair/references/notebook-improvements.md","rawUrl":"https://raw.githubusercontent.com/marimo-team/marimo/HEAD/marimo/_server/ai/skills/marimo-pair/references/notebook-improvements.md","title":"References Skill","category":"anthropic-skill","format":"markdown","content":"# References Skill\n\nPath: `marimo/_server/ai/skills/marimo-pair/references/notebook-improvements.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/marimo-team/marimo/HEAD/marimo/_server/ai/skills/marimo-pair/references/notebook-improvements.md)","tokens":300,"sizeBytes":262},{"name":"rich-representations.md","path":"marimo/_server/ai/skills/marimo-pair/references/rich-representations.md","rawUrl":"https://raw.githubusercontent.com/marimo-team/marimo/HEAD/marimo/_server/ai/skills/marimo-pair/references/rich-representations.md","title":"References Skill","category":"anthropic-skill","format":"markdown","content":"# References Skill\n\nPath: `marimo/_server/ai/skills/marimo-pair/references/rich-representations.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/marimo-team/marimo/HEAD/marimo/_server/ai/skills/marimo-pair/references/rich-representations.md)","tokens":300,"sizeBytes":260},{"name":"SKILL.md","path":"marimo/_server/ai/skills/marimo-pair/SKILL.md","rawUrl":"https://raw.githubusercontent.com/marimo-team/marimo/HEAD/marimo/_server/ai/skills/marimo-pair/SKILL.md","title":"marimo-pair","category":"anthropic-skill","format":"markdown","content":"---\nname: marimo-pair\ndescription: >-\n  Work inside the user's live marimo notebook from the code editor: run Python\n  in the same kernel the user does, inspect live notebook state, and commit\n  durable notebook changes through code mode. Use whenever you create, analyze,\n  or improve the user's marimo notebook.\n---\n\nmarimo is a reactive Python runtime for building reproducible Python programs\n(marimo notebooks). Cells are connected by the variables they define and\nreference. Running a cell re-executes dependents in dataflow order. The active\nruntime holds the kernel namespace, cell state, and dataflow graph. The\nnotebook (`.py` file) is the artifact the kernel writes from that state while a\nsession is running.\n\nA user interacts with the same runtime via a notebook UI with cells, outputs,\nand widgets.\n\n**WARNING. The active runtime is the source of truth.** You are working inside\nthe user's live notebook session. The kernel — not the `.py` file on disk —\nholds the truth about cells, variables, and the dataflow graph. Make every\nnotebook change through `marimo._code_mode` (`cm`); direct file edits WILL NOT\nreach the live kernel or user, and the kernel may overwrite them on save.\nReading disk is fine, but prefer `ctx.cells[...].code` for current cell code.\n\n**WARNING. Every notebook edit goes through code mode — no exceptions.** When\nthe user asks you to change the notebook (add, edit, delete, or run a cell;\nrename; change a value or a package), you MUST make that change through\n`marimo._code_mode` (`cm`) by running it with the `execute_code` tool. There is\nno separate file-editing path — `execute_code` + `cm` is the only way to reach\nthe user's running session. Running ad-hoc Python with `execute_code` to\nexplore or test is fine; _persisting any change to the notebook_ is only ever\ndone via `cm`.\n\n## Running Code in the Kernel\n\nYou are already attached to the user's running notebook — there is nothing to\nconnect to or start. Use the `execute_code` tool to run Python in that kernel,\npassing your Python as the `code` argument. Everything you do — inspecting\nstate, testing transformations, and persisting changes via `cm` — runs through\n`execute_code` in the scratchpad (see below).\n\n## Required First Kernel Command\n\nStart every code-mode session with this dedicated `execute_code` call:\n\n```python\nimport marimo._code_mode as cm\n\nhelp(cm)\n```\n\nFollow this order for every live kernel, including read-only tasks:\n\n1. Run only the inspection command above.\n2. Wait for successful `help(cm)` output.\n3. Use `cm.get_context()` or another `cm` API in a later `execute_code` call.\n\nDo not combine the inspection with task-specific code, and do not use another\n`cm` API before the inspection succeeds. This verifies the private, unstable\nAPI exposed by the marimo version in the user's active kernel.\n\n## Scratchpad Scope\n\n`execute_code` evaluates Python in marimo's scratchpad: a temporary namespace\nwith a shallow copy of the kernel globals. Notebook variables are available by\nname, but new top-level bindings and rebindings are discarded after each call.\nIn-place mutations to notebook-owned objects can persist because those names\nstill reference live objects.\n\nEach call reports stdout and stderr from the scratchpad, plus console output\nfrom notebook cells it causes to run, including reactive descendants.\n\n### Ordinary Python\n\nUse ordinary Python in the scratchpad to inspect variables, sample data, test\ntransformations, probe APIs, check imports, and read widget state.\n\n```python\nprint(df.head())\n\nx = 10\nprint(x)\n```\n\nHere `df` comes from notebook globals, while `x` is a scratchpad-local binding.\n`x` exists for this call only and WILL NOT be added to notebook globals.\n\n### Persist with `cm`\n\nTop-level scratchpad assignments and rebindings are temporary. To persist work,\nincluding new variables, you MUST submit changes through `marimo._code_mode`\n(`cm`).\n\n`marimo._code_mode` is a PRIVATE, UNSTABLE agent API (note the leading\nunderscore). It exists for tools like this skill to drive a live kernel from\nthe scratchpad. DO NOT import it from notebook cells, library code, or\nanything a user would run — methods can change or disappear across marimo\nversions and kernels. Treat every `import marimo._code_mode as cm` as\nscratchpad-only.\n\nOpen a code-mode context to queue notebook changes.\n\n```python\nimport marimo._code_mode as cm\n\nasync with cm.get_context() as ctx:\n    cid = ctx.create_cell(\"x = df.head()\")\n    ctx.run_cell(cid)\n```\n\nThe scratchpad supports top-level async code. Use `async with` directly;\nwrapping it in `asyncio.run(...)` is unnecessary and can conflict with the\nkernel's event loop.\n\nAfter this block exits and the new cell runs, `x` is notebook state. Later\nscratchpad calls can read `x` by name. Code later in the same scratchpad call\nshould read `ctx.globals[\"x\"]`, because the scratchpad namespace was copied\nbefore the cell ran.\n\nInside the context, queued mutation methods are synchronous. Call them\ndirectly; do not `await` them. Each call queues an operation for marimo to\napply when the context exits normally. If the block raises, the queue is\ndiscarded.\n\nOn clean exit, marimo applies packages, validates and applies structural cell\nchanges, runs queued cells, then may run dependents. Validation is only\nstructural since queued cell runs can still error. `create_cell` and\n`edit_cell` change notebook structure only. Use `run_cell` to execute.\n\n`create_cell` currently defaults to `hide_code=True`, which collapses the code\neditor in the UI. Pass `hide_code=False` if the user wants created cells to\nbe visible without manually expanding them.\n\n## Marimo Rules\n\nmarimo imposes a small contract on notebook code so it can keep the notebook as\na directed acyclic graph (DAG):\n\n- **No cycles** - cells cannot depend on each other in a cycle.\n- **No public redefinitions across cells** - each name has one owning cell.\n- **No wildcard imports** - `import *` prevents static analysis of definitions.\n\nThese rules keep the kernel, UI, and saved artifact consistent.\n\nWhen `cm` submits a cell body, marimo parses its top-level definitions and\nreferences. A top-level name enters the graph unless it is private with a\nleading underscore.\n\n```python\n# Public definitions: values, total, i, value, mean\nvalues = np.array([1, 2, 3])\ntotal = 0\nfor i, value in enumerate(values):\n    total += value\nmean = total / len(values)\nmean\n```\n\n```python\n# Public definition: mean\n_values = np.array([1, 2, 3])\n_total = 0\nfor _i, _value in enumerate(_values):\n    _total += _value\nmean = _total / len(_values)\nmean\n```\n\nUse private names for intermediates that no other cell should read. Public\nnames define the notebook-level dataflow. If a `cm` edit violates the contract,\nmarimo rejects the structural change and returns the validation error.\n\n## The Notebook's Shape\n\nA notebook is an ordered collection of cells. `ctx.cells` is the document view\nand `ctx.graph` is the dataflow view.\n\n```python\nfor cell in ctx.cells:\n    cell  # .id, .code, .name, .config, .status, .errors\n\nctx.cells[\"setup\"]  # by name\nctx.cells[0]  # by position\nlist(ctx.cells.keys())  # all IDs, in notebook order\n```\n\nCell IDs are opaque strings which can be queried from the notebook or captured\nfrom `cm` return values:\n\n```python\ncid = ctx.create_cell(\"df = pd.read_csv('data.csv')\")\nprint(cid)  # e.g. 'Hbol'\n```\n\nAlternatively, cells can be assigned and referenced by `name`. The graph can be\nused to understand its role in the dataflow.\n\n```python\nfor cid, impl in ctx.graph.cells.items():\n    impl  # .defs, .refs   (sets of public names)\n\nctx.graph.descendants(cid)  # cells that re-run when this one changes\nctx.graph.ancestors(cid)  # cells this one depends on\n```\n\nIn marimo, deletes are _destructive_ so it can be useful to query the\ndescendants prior to deleting to understand it's impact.\n\n## Writing Notebook Changes\n\nThe graph contract keeps marimo able to run and save the notebook. Passing\nthose checks alone does not guarantee a useful artifact. Committed cells should\nstill be readable, rerunnable, and editable.\n\nMake durable edits that reuse the notebook's existing names, imports,\ndependencies, and UI model. Don't be lazy. Avoid one-off workarounds that pass\n`cm` validation but leave a brittle notebook.\n\n### Cell Bodies\n\nSubmit the code that belongs in the cell.\n\n- **Submit cell contents** - `create_cell` and `edit_cell` take cell contents,\n  not saved-file `@app.cell` wrappers.\n- **Read before replacing** - for now, another editor may change a cell between\n  scratchpad calls. Before `edit_cell`, read the current body from\n  `ctx.cells[...]` and submit the full replacement.\n- **Reuse notebook imports** - if `np` already exists, use it or edit the owning\n  import cell. DO NOT add `import numpy as _np` just to bypass the graph.\n- **Define public names intentionally** - use public names for values later\n  cells should reference. Use private `_name` bindings or function locals for\n  same-cell intermediates.\n- **Define each public name once** - a public name has one owning cell.\n  Reassigning it in another cell fails with `Multiply-defined names`; edit the\n  owning cell or give the result a new name. Load the `gotchas` capability for\n  more traps.\n- **Run cells deliberately** - `create_cell` and `edit_cell` change structure\n  only. Queue `ctx.run_cell(...)` when the cell should execute.\n\n### Prefer `cm`-Managed Changes\n\nUse `cm` APIs when they exist. Avoid direct file edits, shell package commands,\nand scratchpad-only state for changes that should persist.\n\n- **Persist only through `cm`** - never try to change the notebook by writing\n  the `.py` file; `execute_code` + `cm` is the only path that reaches the live\n  session. Use `ctx.edit_cell(...)` even for small changes.\n- **Manage packages through `cm`** - use `ctx.packages.add()` or\n  `ctx.packages.remove()` instead of direct `uv` or `pip`; confirm\n  non-obvious dependency changes.\n- **Avoid transient paths** - persisted cells should not depend on `/tmp/...`\n  unless the work is intentionally transient.\n- **Delete deliberately** - deleting a cell removes globals it defines. Reuse\n  empty cells when convenient and delete cells left empty after edits.\n\n### UI and Widgets\n\nInspect the object before changing it. Different UI objects update through\ndifferent paths.\n\n- **Set `mo.ui.*` through `cm`** - use `ctx.set_ui_value(element, value)` inside\n  `cm.get_context()`.\n- **Set anywidget traitlets directly** - synced traitlets are Python\n  attributes, for example `widget.value = 5`.\n\nFor designing custom visual or interactive output, load the\n`rich-representations` capability.\n\n## On-demand references\n\nLoad these with the `load_capability` tool when you need deeper guidance. Do\nnot read reference files from disk.\n\n- **`gotchas`** — name redefinition, cached module proxies, and notebook traps\n- **`rich-representations`** — custom widgets and visualizations\n- **`notebook-improvements`** — improving existing notebooks\n","frontmatter":{"name":"marimo-pair","description":"Work inside the user's live marimo notebook from the code editor: run Python in the same kernel the user does, inspect live notebook state, and commit durable notebook changes through code mode. Use whenever you create, analyze, or improve the user's marimo notebook."},"isInternal":false,"tokens":2591,"sizeBytes":10993},{"name":"package.json","path":"packages/client/package.json","rawUrl":"https://raw.githubusercontent.com/marimo-team/marimo/HEAD/packages/client/package.json","title":"Client Skill","category":"anthropic-skill","format":"json","content":"# Client Skill\n\nPath: `packages/client/package.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/marimo-team/marimo/HEAD/packages/client/package.json)","tokens":300,"sizeBytes":170},{"name":"REDUCERS.md","path":"packages/client/REDUCERS.md","rawUrl":"https://raw.githubusercontent.com/marimo-team/marimo/HEAD/packages/client/REDUCERS.md","title":"Client Skill","category":"anthropic-skill","format":"markdown","content":"# Keep state from events\n\nHost state is read over event streams. The catalog stream describes the\nhost's notebooks, projects, runtimes, and attachments. A notebook stream\ndescribes one notebook's document and execution state.\n\nA stream starts with a snapshot of the current state. A `ready` event marks\nthe end of the snapshot. Subsequent events report changes. For example, a\n`notebook` event carries the notebook's current record, and\n`notebook.removed` identifies a notebook that was removed.\n\n`CatalogEvents` and `NotebookEvents` validate incoming events and track the\ncursor used to resume after a disconnect. They deliver events through an\nasync iterator or a subscription. Your application decides which records\nto retain. If the stream cannot resume, it delivers `reset` followed by a\nnew snapshot that replaces the previous state.\n\n## Keep a notebook list\n\nTo keep a notebook list, define a resource that starts with an empty list.\nIts `notebook` handler adds or replaces an entry. Its `notebook.removed`\nhandler removes an entry by id. Each entry keeps only the notebook's id\nand name.\n\nPass the resource to `createCatalogReducer`, then apply each event with\n`reduce(state, event)`. The resulting list is in `state.resources.notebooks`.\nThis example stops at `ready` and prints the list from the snapshot.\n\n```ts\nimport type { NotebookOutput } from \"@marimo-team/client/protocol\";\nimport {\n  Client,\n  createCatalogReducer,\n  type CatalogResource,\n} from \"@marimo-team/client\";\n\ntype NotebookSummary = Pick<NotebookOutput, \"id\" | \"name\">;\n\nconst notebooks: CatalogResource<readonly NotebookSummary[], \"notebook\"> = {\n  initial: [],\n  on: {\n    notebook: (state, { data }) => [\n      ...state.filter((entry) => entry.id !== data.notebook.id),\n      { id: data.notebook.id, name: data.notebook.name },\n    ],\n    \"notebook.removed\": (state, { data }) =>\n      state.filter((entry) => entry.id !== data.id),\n  },\n};\n\nconst reducer = createCatalogReducer({ notebooks });\nconst client = new Client(\"http://127.0.0.1:2718/api/marimo/v1\", {\n  token: \"your-token\",\n});\nlet state = reducer.initial;\n\nfor await (const event of client.events({ types: [\"notebook\"] })) {\n  state = reducer.reduce(state, event);\n  if (event.event === \"ready\") break;\n}\n\nconsole.log(state.resources.notebooks);\n```\n\nThe reducer handles the stream's lifecycle. `ready` changes `state.phase`\nfrom `snapshot` to `live`. `reset` returns the phase to `snapshot` and each\nresource to its initial value. Resources can handle `ready` to finish\nassembling a snapshot. The handler's third argument contains the phase\nbefore the event is applied. It is `snapshot` for the initial `ready` and\n`live` for a `ready` that follows a resumed connection.\n\nHandlers return a new value when state changes and the existing value\notherwise. They must not modify the previous value or perform side effects.\n\nFor a notebook stream, define a `NotebookResource` and pass it to\n`createNotebookReducer`. This reducer also keeps the notebook's record and\nidentity in `notebook` and `notebookId`. It handles `notebook` and\n`notebook.removed` itself. Removing the notebook clears its record and\nresources. A `reset` also clears its identity.\n\n## Follow changes in React\n\nTo keep a notebook list updated in a UI, subscribe to the stream and pass\neach event to the reducer through your store's state update function. This\nhook uses React state. It removes the subscription and closes the stream\nwhen the effect is cleaned up.\n\n```tsx\nimport { useEffect, useState } from \"react\";\n\nfunction useNotebooks(client: Client) {\n  const [state, setState] = useState(reducer.initial);\n\n  useEffect(() => {\n    setState(reducer.initial);\n    const events = client.events({ types: [\"notebook\"] });\n    const unsubscribe = events.subscribe((event) => {\n      setState((current) => reducer.reduce(current, event));\n    });\n    return () => {\n      unsubscribe();\n      events.close();\n    };\n  }, [client]);\n\n  return state;\n}\n```\n\nKeep the client instance stable across renders. Temporary disconnects preserve\nstate while the stream resumes. A `reset` rebuilds it. Pass a second function\nto `subscribe` to surface connection failures in your application. It\nreceives the error when the stream stops.\n\nIf you persist state for a later connection, save its matching cursor and\nreuse the same host, stream, and filter. The stream's cursor tracks received\nevents. When state updates are queued, as in React, it can be ahead of the\nstate you have applied. Resume needs both state and its matching cursor.\n","isInternal":false,"tokens":1035,"sizeBytes":4533},{"name":"TRANSPORTS.md","path":"packages/client/TRANSPORTS.md","rawUrl":"https://raw.githubusercontent.com/marimo-team/marimo/HEAD/packages/client/TRANSPORTS.md","title":"Client Skill","category":"anthropic-skill","format":"markdown","content":"# Custom transports\n\n`Client` and `NotebookClient` send HTTP requests and read server-sent events.\nTo follow events from an existing WebSocket, message channel, or another\nsource, pass a `Transport` function to `NotebookEvents` or `CatalogEvents`.\n\nThe stream calls the transport once for each connection attempt. The\ntransport receives a cursor and an abort signal. A null cursor requests a\nsnapshot. Otherwise, the transport sends the cursor to the host to resume\nafter that position.\n\nCall `open()` when the connection is established. Call `message(event)` for\neach decoded protocol event, in order. Close the connection when the signal\nis aborted.\n\nResolve when the connection ends and another attempt makes sense. Reject\nwhen the stream should stop. The stream's `closed` promise rejects with the\nsame error. Use `StreamStopped` to describe the failure. Calls to `open()` or\n`message(event)` after the promise settles are ignored.\n\nThe stream validates events, tracks the cursor, delivers events to\nsubscribers, and reconnects. It delivers `reset` when an interrupted snapshot\nmust be discarded. The host must also send `reset` when it cannot resume\nfrom the supplied cursor.\n\nThe transport sends any filters the host needs. The stream's `types` option\nfilters delivered events locally. A notebook transport must apply `runId`\nitself. Each reconnect must use the same filters.\n\n## Build on server-sent events\n\n`sse` is the transport a stream uses for a URL. Use it directly when a host\nserves the protocol's events with a URL that changes between connections or\nwith frames of its own that end the stream.\n\n```ts\nimport { NotebookEvents, StreamStopped, sse } from \"@marimo-team/client\";\n\nconst events = new NotebookEvents(\n  sse(() => `${base}/events?session_id=${session()}`, {\n    token,\n    stop: (frame) =>\n      frame.event === \"close\"\n        ? new StreamStopped(\"The session closed\")\n        : undefined,\n  }),\n);\n```\n\nThe URL function runs before each connection. A `StreamStopped` it throws\nstops the stream.\n\nSet `parseData` to decode each frame's raw data with a custom parser. It runs\nbefore `stop` and event delivery. The default is `JSON.parse`; if the parser\nthrows, the frame keeps its original text.\n\nSee the [transport contract](src/transport/frame.ts) for the function and\nevent types.\n","isInternal":false,"tokens":515,"sizeBytes":2310},{"name":"tsconfig.build.json","path":"packages/client/tsconfig.build.json","rawUrl":"https://raw.githubusercontent.com/marimo-team/marimo/HEAD/packages/client/tsconfig.build.json","title":"Client Skill","category":"anthropic-skill","format":"json","content":"# Client Skill\n\nPath: `packages/client/tsconfig.build.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/marimo-team/marimo/HEAD/packages/client/tsconfig.build.json)","tokens":300,"sizeBytes":184},{"name":"tsconfig.json","path":"packages/client/tsconfig.json","rawUrl":"https://raw.githubusercontent.com/marimo-team/marimo/HEAD/packages/client/tsconfig.json","title":"Client Skill","category":"anthropic-skill","format":"json","content":"# Client Skill\n\nPath: `packages/client/tsconfig.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/marimo-team/marimo/HEAD/packages/client/tsconfig.json)","tokens":300,"sizeBytes":172},{"name":"AGENTS.md","path":"packages/llm-info/AGENTS.md","rawUrl":"https://raw.githubusercontent.com/marimo-team/marimo/HEAD/packages/llm-info/AGENTS.md","title":"Llm-info Skill","category":"anthropic-skill","format":"markdown","content":"# Llm-info Skill\n\nPath: `packages/llm-info/AGENTS.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/marimo-team/marimo/HEAD/packages/llm-info/AGENTS.md)","tokens":300,"sizeBytes":170},{"name":"package.json","path":"packages/llm-info/package.json","rawUrl":"https://raw.githubusercontent.com/marimo-team/marimo/HEAD/packages/llm-info/package.json","title":"Llm-info Skill","category":"anthropic-skill","format":"json","content":"# Llm-info Skill\n\nPath: `packages/llm-info/package.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/marimo-team/marimo/HEAD/packages/llm-info/package.json)","tokens":300,"sizeBytes":176},{"name":"SKILL.md","path":"packages/llm-info/skills/SKILL.md","rawUrl":"https://raw.githubusercontent.com/marimo-team/marimo/HEAD/packages/llm-info/skills/SKILL.md","title":"fill-model-descriptions","category":"anthropic-skill","format":"markdown","content":"---\nname: fill-model-descriptions\ndescription: Curate descriptions and provider-specific reasoning options and token limits in `packages/llm-info/data/models.yml` using models.dev, OpenRouter, and provider documentation. Use when the user asks to populate model descriptions, enrich the model catalog, or curate descriptions after running `pnpm sync-models`.\ndisable-model-invocation: true\n---\n\n# Fill Model Descriptions\n\n## Goal\n\nKeep descriptions in `packages/llm-info/data/models.yml` concise and accurate. Fill empty descriptions and refresh existing descriptions when newly added models or authoritative documentation make them obsolete. Source descriptions from OpenRouter first, then provider documentation as a fallback.\n\n## Scope and Contract\n\n- Fill every empty `description` for which a confident source is available.\n- Preserve human-curated, non-empty descriptions unless a newly added model or authoritative source makes a concrete claim obsolete. Typical obsolete claims include \"latest,\" \"most capable,\" availability, or capabilities that have demonstrably changed.\n- Do not rewrite existing descriptions only for style, tone, or consistency. When an existing description must change, make the smallest factual correction and record it in the final summary.\n- The file is a top-level YAML map keyed by provider id (`anthropic:`, `openai:`, …). Each provider's value is an array of model entries.\n- For description-only work, do not modify any other field. For metadata enrichment, refresh machine-sourced capabilities, input/output types, release dates, pricing, reasoning options, and token limits; preserve names, descriptions, and roles. Do not reorder entries or change formatting (flow-style arrays like `roles: [chat, edit]`, blank lines between entries, blank line between provider sections).\n- This skill requires network access.\n\nFor metadata-only requests, use [Reasoning Options and Token Limits](#reasoning-options-and-token-limits) and skip the description workflow.\n\n## Workflow\n\n1. **Read** `packages/llm-info/data/models.yml`. Parse it with the `yaml` library's `parseDocument` (NOT `parse`) so formatting and comments are preserved on write-back.\n\n2. **Collect and review** descriptions:\n   - Build one worklist of `{ provider, model }` pairs containing every entry where `description` is empty.\n   - Review related existing entries in the same model families for claims made obsolete by the new entries. Also review descriptions affected by a factual change found in authoritative documentation, and add every obsolete entry to the same worklist.\n\n3. **Source descriptions** in this priority order:\n\n   **a. OpenRouter** — `GET https://openrouter.ai/api/v1/models` (no auth required). Build a lookup keyed by lowercased `id`. For each `{ provider, model }`, try candidates in this order:\n   - `${vendor}/${model}` where `vendor` comes from the Vendor Map below.\n   - `${vendor}/${model.replaceAll('-', '.')}` (some OR ids use `.` separators, e.g. `claude-3.5-sonnet`).\n   - For Bedrock entries with region/alias prefixes (`us.`, `eu.`, `jp.`, `global.`, `anthropic.`, `minimax.`, `mistral.`, `zai.`, `nvidia.`), strip the prefix and retry with the appropriate vendor.\n   - For Google entries with `@default` suffix (e.g. `claude-opus-4-7@default`), strip the suffix and try `anthropic/${rest}`. These are Vertex-hosted Anthropic models — descriptions should note they are Vertex AI only (not Gemini API).\n\n   **b. Provider docs** — if no OpenRouter hit, search the canonical provider's docs page (anthropic.com/news, platform.openai.com/docs/models, ai.google.dev/gemini-api/docs/models, mistral.ai/news, x.ai/blog, etc.) for the model's one-line summary. Use the `WebSearch` or `WebFetch` tool.\n\n   **c. Skip** — if neither source has a confident answer, leave `description: \"\"` and record the `{ provider, model }` for the final summary. Empty is better than wrong.\n\n4. **Truncate** each sourced description per the rules in the \"Truncation\" section.\n\n5. **Write** the YAML back using targeted `Pair` mutations on the parsed `Document`, not text replacement. Reference implementation: `packages/llm-info/src/sync-models.ts` shows how to load a Document, mutate sequence/map nodes, and stringify with `{ lineWidth: 0, flowCollectionPadding: false }` to preserve formatting.\n\n6. **Validate** by running:\n   ```bash\n   pnpm --filter @marimo-team/llm-info test\n   ```\n   The `schema.test.ts` test will catch any structural drift.\n\n7. **Report** to the user:\n   - How many empty descriptions were filled.\n   - How many obsolete descriptions were updated, with the provider/model list and the factual reason.\n   - How many were skipped (with the provider/model list).\n\n## Reasoning Options and Token Limits\n\nWhen metadata enrichment is requested, query `https://models.dev/api.json` and\nmatch the exact provider/model offering using `PROVIDER_MAP` in\n`src/sources/merge.ts`. Google Vertex models remain separate offerings even\nthough they share the `google` catalog section. Do not use the description\nvendor map or strip aliases to obtain metadata from another hosting provider.\n\nRun `pnpm --dir packages/llm-info sync-models --metadata-only` to refresh the\ncurrent catalog without adding models. Normal sync also refreshes known metadata\non existing entries: capabilities, input/output types, release dates, pricing,\nreasoning options, and token limits. Curated names, descriptions, and roles are\npreserved. Neither mode changes runtime thinking configuration.\n\n- `reasoning_options` preserves upstream `toggle`, `effort` (with explicit\n  values), and `budget_tokens` (with optional `min`/`max`) controls. Preserve\n  `null`, `default`, and the `-1` automatic-budget sentinel when supplied.\n- `limits` maps upstream `limit.context` and `limit.output`, in tokens. Preserve\n  supplied values, including zero; omitted fields remain unknown.\n- An explicit `reasoning: false` removes the thinking capability and clears stale\n  reasoning controls. An omitted flag preserves the corresponding capability.\n  Partial pricing and limits updates preserve unspecified values.\n- Missing upstream fields or unmatched offerings do not justify inventing\n  values or removing existing metadata. Report unmatched entries. Consult the\n  exact provider's documentation if further enrichment is needed.\n- OpenRouter's normalized reasoning controls describe its gateway API. Use them\n  only for OpenRouter offerings, not as native Anthropic, OpenAI, Azure, or\n  Bedrock configuration contracts.\n\nAfter enrichment, run `pnpm --dir packages/llm-info codegen` and\n`pnpm --dir packages/llm-info test --run`. Report coverage for each metadata\nfield and unresolved provider/model matches. Generated JSON must retain the new\nfields; updating YAML alone is insufficient.\n\n## Vendor Map\n\nOpenRouter id vendor prefixes for each marimo provider:\n\n| Marimo provider | OpenRouter vendor prefix | Notes |\n|---|---|---|\n| `anthropic` | `anthropic` | Direct match in most cases |\n| `openai` | `openai` | Direct match |\n| `google` | `google` | Strip `@default` suffix if present |\n| `mistral` | `mistralai` | Note the `ai` suffix |\n| `xai` | `x-ai` | Hyphenated |\n| `azure` | `openai` | Azure mostly re-exposes OpenAI models |\n| `bedrock` | varies | Strip region prefix (`us.`/`eu.`/`jp.`/`global.`) and use the embedded vendor (`anthropic.foo` → `anthropic/foo`) |\n| `github` | varies | Ids like `openai/gpt-4.1` carry the vendor; strip the github layer |\n| `openrouter` | embedded in id | Ids like `anthropic/claude-opus-4.7-fast` already carry the vendor |\n| `wandb` | embedded in id | Ids like `deepseek-ai/DeepSeek-V3.1`; the prefix is the vendor |\n| `opencode-go` | rarely on OR | Source from provider docs |\n| `ollama` | not on OR | Source from the Ollama model card |\n\n## Truncation\n\n- **One sentence.** Split on `. ` and take the first. Strip trailing whitespace and any markdown formatting (`**`, `_`, backticks).\n- **Hard cap at 200 characters.** If the first sentence is longer, cut at the last word boundary before 200 and append `…`.\n- **Strip leading articles** for consistency: prefer \"Frontier reasoning model optimized for…\" over \"This is a frontier reasoning model optimized for…\".\n- **Prefer capability statements over marketing.** If OpenRouter gives \"the best model from X\" but the provider docs give \"optimized for tool use and long-context reasoning\", prefer the latter.\n\n## Examples\n\n**Good** (matches the tone of existing hand-curated entries):\n- `Opus model optimized for coding and long-running professional tasks`\n- `Sonnet-class model with strong performance across coding, agents, and professional work`\n- `Lightweight Gemma model trained by Google, designed to run on a single GPU`\n- `Multimodal Mixture-of-Experts model optimized for complex tool use and reasoning`\n\n**Bad** (do not produce these):\n- `Claude 3.5 Sonnet delivers better-than-Opus capabilities, faster-than-Sonnet speeds, at the same Sonnet prices. Sonnet is particularly good at coding, vision…` — too long, contains marketing\n- `The best model from Anthropic` — vague, no information content\n- `An AI model` — useless\n- `**Claude 3.5 Sonnet** is a _frontier_ model…` — markdown not stripped\n\n## Quick Reference\n\n- Data file: `packages/llm-info/data/models.yml`\n- Schema: `packages/llm-info/src/index.ts` (`AiModel` interface)\n- YAML write reference: `packages/llm-info/src/sync-models.ts` (`buildEntryNode`, `addProviderSection`)\n- OpenRouter API: `https://openrouter.ai/api/v1/models` (public, no auth)\n- Validation: `pnpm --filter @marimo-team/llm-info test`\n","frontmatter":{"name":"fill-model-descriptions","description":"Curate descriptions and provider-specific reasoning options and token limits in `packages/llm-info/data/models.yml` using models.dev, OpenRouter, and provider documentation. Use when the user asks to populate model descriptions, enrich the model catalog, or curate descriptions after running `pnpm sync-models`.","disable-model-invocation":true,"disableModelInvocation":true},"isInternal":false,"tokens":2229,"sizeBytes":9583},{"name":"tsconfig.json","path":"packages/llm-info/tsconfig.json","rawUrl":"https://raw.githubusercontent.com/marimo-team/marimo/HEAD/packages/llm-info/tsconfig.json","title":"Llm-info Skill","category":"anthropic-skill","format":"json","content":"# Llm-info Skill\n\nPath: `packages/llm-info/tsconfig.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/marimo-team/marimo/HEAD/packages/llm-info/tsconfig.json)","tokens":300,"sizeBytes":178},{"name":"package.json","path":"packages/lsp/package.json","rawUrl":"https://raw.githubusercontent.com/marimo-team/marimo/HEAD/packages/lsp/package.json","title":"Lsp Skill","category":"anthropic-skill","format":"json","content":"# Lsp Skill\n\nPath: `packages/lsp/package.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/marimo-team/marimo/HEAD/packages/lsp/package.json)","tokens":300,"sizeBytes":161},{"name":"tsconfig.json","path":"packages/lsp/tsconfig.json","rawUrl":"https://raw.githubusercontent.com/marimo-team/marimo/HEAD/packages/lsp/tsconfig.json","title":"Lsp Skill","category":"anthropic-skill","format":"json","content":"# Lsp Skill\n\nPath: `packages/lsp/tsconfig.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/marimo-team/marimo/HEAD/packages/lsp/tsconfig.json)","tokens":300,"sizeBytes":163},{"name":"turbo.json","path":"packages/lsp/turbo.json","rawUrl":"https://raw.githubusercontent.com/marimo-team/marimo/HEAD/packages/lsp/turbo.json","title":"Lsp Skill","category":"anthropic-skill","format":"json","content":"# Lsp Skill\n\nPath: `packages/lsp/turbo.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/marimo-team/marimo/HEAD/packages/lsp/turbo.json)","tokens":300,"sizeBytes":157},{"name":"api.yaml","path":"packages/openapi/api.yaml","rawUrl":"https://raw.githubusercontent.com/marimo-team/marimo/HEAD/packages/openapi/api.yaml","title":"Openapi Skill","category":"anthropic-skill","format":"yaml","content":"# Openapi Skill\n\nPath: `packages/openapi/api.yaml`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/marimo-team/marimo/HEAD/packages/openapi/api.yaml)","tokens":300,"sizeBytes":165},{"name":"package.json","path":"packages/openapi/package.json","rawUrl":"https://raw.githubusercontent.com/marimo-team/marimo/HEAD/packages/openapi/package.json","title":"Openapi Skill","category":"anthropic-skill","format":"json","content":"# Openapi Skill\n\nPath: `packages/openapi/package.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/marimo-team/marimo/HEAD/packages/openapi/package.json)","tokens":300,"sizeBytes":173},{"name":"tsconfig.json","path":"packages/openapi/tsconfig.json","rawUrl":"https://raw.githubusercontent.com/marimo-team/marimo/HEAD/packages/openapi/tsconfig.json","title":"Openapi Skill","category":"anthropic-skill","format":"json","content":"# Openapi Skill\n\nPath: `packages/openapi/tsconfig.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/marimo-team/marimo/HEAD/packages/openapi/tsconfig.json)","tokens":300,"sizeBytes":175},{"name":"package.json","path":"packages/smart-cells/package.json","rawUrl":"https://raw.githubusercontent.com/marimo-team/marimo/HEAD/packages/smart-cells/package.json","title":"Smart-cells Skill","category":"anthropic-skill","format":"json","content":"# Smart-cells Skill\n\nPath: `packages/smart-cells/package.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/marimo-team/marimo/HEAD/packages/smart-cells/package.json)","tokens":300,"sizeBytes":185},{"name":"tsconfig.json","path":"packages/smart-cells/tsconfig.json","rawUrl":"https://raw.githubusercontent.com/marimo-team/marimo/HEAD/packages/smart-cells/tsconfig.json","title":"Smart-cells Skill","category":"anthropic-skill","format":"json","content":"# Smart-cells Skill\n\nPath: `packages/smart-cells/tsconfig.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/marimo-team/marimo/HEAD/packages/smart-cells/tsconfig.json)","tokens":300,"sizeBytes":187},{"name":"base.json","path":"packages/ts-config/base.json","rawUrl":"https://raw.githubusercontent.com/marimo-team/marimo/HEAD/packages/ts-config/base.json","title":"Ts-config Skill","category":"anthropic-skill","format":"json","content":"# Ts-config Skill\n\nPath: `packages/ts-config/base.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/marimo-team/marimo/HEAD/packages/ts-config/base.json)","tokens":300,"sizeBytes":173},{"name":"library.json","path":"packages/ts-config/library.json","rawUrl":"https://raw.githubusercontent.com/marimo-team/marimo/HEAD/packages/ts-config/library.json","title":"Ts-config Skill","category":"anthropic-skill","format":"json","content":"# Ts-config Skill\n\nPath: `packages/ts-config/library.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/marimo-team/marimo/HEAD/packages/ts-config/library.json)","tokens":300,"sizeBytes":179},{"name":"package.json","path":"packages/ts-config/package.json","rawUrl":"https://raw.githubusercontent.com/marimo-team/marimo/HEAD/packages/ts-config/package.json","title":"Ts-config Skill","category":"anthropic-skill","format":"json","content":"# Ts-config Skill\n\nPath: `packages/ts-config/package.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/marimo-team/marimo/HEAD/packages/ts-config/package.json)","tokens":300,"sizeBytes":179},{"name":"copilot-instructions.md","path":".github/copilot-instructions.md","rawUrl":"https://raw.githubusercontent.com/marimo-team/marimo/HEAD/.github/copilot-instructions.md","title":"GitHub Copilot Instructions","category":"copilot-instructions","format":"markdown","content":"# Code Review Process\n\n1. If the PR seems AI-generated, you should request the contributor to:\n  - Provide screenshots of the fixed output (if possible)\n  - Check if it satisfies edge cases instead of just the direct problem it addresses.\n\nFor example, if there is a frontend change to make a border thicker, how does this look in run mode, app-view and edit-view?\nFor a backend change, has the user tested different scenarios?\n","isInternal":false,"tokens":91,"sizeBytes":428},{"name":"README.md","path":"examples/ai/tools/README.md","rawUrl":"https://raw.githubusercontent.com/marimo-team/marimo/HEAD/examples/ai/tools/README.md","title":"tools Documentation","category":"plugin-manifest","format":"markdown","content":"# tools Documentation\n\nPath: `examples/ai/tools/README.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/marimo-team/marimo/HEAD/examples/ai/tools/README.md)","tokens":300,"sizeBytes":175},{"name":"README.md","path":"packages/client/README.md","rawUrl":"https://raw.githubusercontent.com/marimo-team/marimo/HEAD/packages/client/README.md","title":"client Documentation","category":"plugin-manifest","format":"markdown","content":"# @marimo-team/client\n\nConnect to a marimo host to find notebooks, read their state, and request\nedits or execution. A host serves notebooks through the\n[host protocol](../../protocols/host/spec.md). `Client` works with the host's\ncatalog. `NotebookClient` works with one notebook.\n\n## Connect to a host\n\nGive `Client` the host's API base URL and token. These can come from your\napplication's configuration or the host's\n[local discovery record](../../protocols/host/spec.md#local-discovery).\n\n```ts\nimport { Client } from \"@marimo-team/client\";\n\nconst client = new Client(\"http://127.0.0.1:2718/api/marimo/v1\", {\n  token: \"your-token\",\n});\n```\n\nRequests use HTTP and event streams use server-sent events. Pass `fetch`\nalongside `token` to customize requests.\n\n## Find notebooks\n\nThe catalog stream describes the host's notebooks, projects, runtimes, and\nattachments. It also reports the host's capabilities. This example prints\nthe notebooks the host currently knows about.\n\n```ts\nfor await (const event of client.events({ types: [\"notebook\"] })) {\n  if (event.event === \"notebook\") {\n    console.log(event.data.notebook.id, event.data.notebook.name);\n  }\n  if (event.event === \"ready\") break;\n}\n```\n\n`ready` ends the initial snapshot. Breaking out closes the stream. Projects\nmay still be indexing when `ready` arrives, so more notebooks can appear\nafterward.\n\n## Discover local hosts in Node.js\n\n`discoverHosts()` performs [local discovery](../../protocols/host/spec.md#local-discovery)\non macOS and Linux (requires `procps` on Linux). This example lists the notebooks\neach discovered host currently knows about:\n\n```ts\nimport { Client } from \"@marimo-team/client\";\nimport { discoverHosts } from \"@marimo-team/client/node\";\n\nfor await (const host of discoverHosts()) {\n  const client = new Client(host.url, { token: host.token });\n  for await (const event of client.events({ types: [\"notebook\"] })) {\n    if (event.event === \"ready\") break;\n    if (event.event === \"notebook\") {\n      console.log(event.data.notebook.id, event.data.notebook.name);\n    }\n  }\n}\n```\n\n## Work with a notebook\n\nUse an id or a notebook record from the catalog to get a `NotebookClient`.\nThis example reads the document, prints its cell count, and asks the host\nto save it. It assumes the notebook supports `notebook.save`.\n\n```ts\nimport type { DocumentOutput } from \"@marimo-team/client/protocol\";\n\nconst notebook = client.notebook(\"n1\");\nlet document: DocumentOutput | undefined;\n\nfor await (const event of notebook.events({ types: [\"document\"] })) {\n  if (event.event === \"document\") document = event.data.document;\n  if (event.event === \"reset\") document = undefined;\n  if (event.event === \"ready\") break;\n}\n\nif (document === undefined) throw new Error(\"The host did not send a document\");\nconsole.log(`${document.order.length} cells`);\n\nconst result = await notebook.save({ ifMatch: document.etag });\nif (result.ok) {\n  console.log(\"Saved\", result.data.document.etag);\n} else {\n  console.error(result.problem);\n}\n```\n\n`ifMatch` makes the document's etag a precondition. If the document changes\nbefore the save, the host returns a conflict problem. Other actions, such\nas `edit` and `run`, use the same result shape. The notebook's advertised\noperations describe which actions it permits. Invalid request data,\ninvalid responses, and connection failures throw.\n\nYou can also construct a `NotebookClient` directly when you already know\nthe notebook's URL.\n\n## Follow changes\n\nKeep iterating after `ready` to follow changes. Streams reconnect and resume\nfrom their last cursor. If they cannot resume, they deliver `reset` followed\nby a new snapshot. Discard accumulated state on `reset` before applying the\nsnapshot.\n\nTo maintain a notebook list or document state from events, see the\n[reducer guide](REDUCERS.md).\n\nTo follow events over a WebSocket or another connection, see the\n[custom transport guide](TRANSPORTS.md).\n\n## Contributing\n\nThe [host protocol](../../protocols/host/spec.md) explains the model and\nbehavior. [OpenAPI](../../protocols/host/openapi.yaml) defines the routes and\npayloads. `@marimo-team/client/protocol` exports the TypeScript types and Zod\nschemas generated from it.\n\nRun these commands from the repository root. See\n[CONTRIBUTING.md](../../CONTRIBUTING.md) for setup.\n\nThe package is consumed from `dist`. Build it once, or watch for changes\nwhile developing.\n\n```sh\npnpm --dir packages/client build\npnpm --dir packages/client build --watch\n```\n\nAfter changing OpenAPI, regenerate the protocol types, schemas, and\noperation definitions. `codegen:check` checks that generated files match\nthe specification. Generation requires `uv` as well as the Node toolchain:\nboth language generators use the same Python overlay composer. The checked-in\nclient includes experimental features, including Analysis.\n\n```sh\npnpm --dir packages/client codegen\npnpm --dir packages/client codegen:check\n```\n\nThe package commands opt into all experimental features so Turbo builds retain\nthe APIs the handwritten client consumes. Use `codegen:stable` for stable-only\nbindings, using\n`--output-dir` to keep them separate from the client's checked-in bindings. Use\n`--include-experimental=analysis` to select a feature. This selects generated\ncontracts; it does not create a separate stable build of the client package.\nSee the [host protocol tooling](../../protocols/host/README.md) for details.\n\nRun the package's tests and typecheck. Omit `--run` to watch tests while\ndeveloping.\n\n```sh\npnpm --dir packages/client test --run\npnpm --dir packages/client typecheck\n```\n","isInternal":false,"tokens":1285,"sizeBytes":5557},{"name":"README.md","path":"packages/llm-info/README.md","rawUrl":"https://raw.githubusercontent.com/marimo-team/marimo/HEAD/packages/llm-info/README.md","title":"llm-info Documentation","category":"plugin-manifest","format":"markdown","content":"# llm-info Documentation\n\nPath: `packages/llm-info/README.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/marimo-team/marimo/HEAD/packages/llm-info/README.md)","tokens":300,"sizeBytes":178},{"name":"README.md","path":"packages/pytest_changed/README.md","rawUrl":"https://raw.githubusercontent.com/marimo-team/marimo/HEAD/packages/pytest_changed/README.md","title":"pytest_changed Documentation","category":"plugin-manifest","format":"markdown","content":"# pytest_changed Documentation\n\nPath: `packages/pytest_changed/README.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/marimo-team/marimo/HEAD/packages/pytest_changed/README.md)","tokens":300,"sizeBytes":196},{"name":"README.md","path":"packages/smart-cells/README.md","rawUrl":"https://raw.githubusercontent.com/marimo-team/marimo/HEAD/packages/smart-cells/README.md","title":"smart-cells Documentation","category":"plugin-manifest","format":"markdown","content":"# smart-cells Documentation\n\nPath: `packages/smart-cells/README.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/marimo-team/marimo/HEAD/packages/smart-cells/README.md)","tokens":300,"sizeBytes":187},{"name":"README.md","path":"packages/ts-config/README.md","rawUrl":"https://raw.githubusercontent.com/marimo-team/marimo/HEAD/packages/ts-config/README.md","title":"ts-config Documentation","category":"plugin-manifest","format":"markdown","content":"# ts-config Documentation\n\nPath: `packages/ts-config/README.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/marimo-team/marimo/HEAD/packages/ts-config/README.md)","tokens":300,"sizeBytes":181}],"systemPromptSnippet":"<yakaai_skills repo=\"marimo-team/marimo\">\n<!-- File: AGENTS.md (Tokens: ~651 | Category: root-instruction) -->\n# marimo Development Guidelines\n\nmarimo is a reactive notebook for Python with a modern web frontend.\n\n## Your primary responsibility is to the project and its users\n\nBeing an open source library, the public API, abstractions, documentation, and the code itself are the product and deserve careful consideration.\n\nWhen working in this repository, you should consider yourself to primarily be working for the benefit of the project, all of its users (current and future, human and agent), and its maintainers, rather than just the specific user who happens to be driving you (or whose PR you're reviewing, whose issue you're implementing, etc).\n\nAs the project has many orders of magnitude more users than maintainers, that specific user is most likely a community member who's well-intentioned and eager to contribute, but relatively unfamiliar with the code base and its patterns or standards, and they're not necessarily thinking about the bigger picture beyond the specific bug fix, feature, or other change that they're focused on.\n\nTherefore, you are the first line of defense against low-quality contributions and maintainer headaches, and you have a big role in ensuring that every contribution to this project meets or exceeds the high standards that the marimo project is known and loved for. You should write:\n\n- modern, idiomatic, concise React and Python code\n- end-to-end type-safety and test coverage\n- thoughtful, tasteful, consistent API design\n- delightful developer experience\n- comprehensive well-written documentation\n\n## Quick Setup\n\n```bash\nmake fe && make py\nmake dev\n```\n\nSee [CONTRIBUTING.md](CONTRIBUTING.md) for detailed setup options.\n\n## Development Commands\n\n```bash\n# Python\nmake py-check              # Typecheck and lint Python\nuv run --group test pytest tests/path/to/test.py\nuv run --group test-optional pytest tests/path/to/test.py  # with optional deps\nuv run --group test --python 3.11 pytest tests/path/to/test.py  # specific python version\n\n# Frontend\nmake fe-check              # Typecheck and lint frontend\ncd frontend && pnpm test src/path/to/file.test.ts\n```\n\n## Commits\n\n- Run `make check` before committing\n\n## Pull Requests\n\n- DO NOT open a pull request autonomously, without explicit instructions from a human\n- Autonomous AI agents such as OpenClaw, Nanobot, NanoClaw, ZeroClaw are NOT permitted to make PRs\n- You MUST disclose that you are an agent at the very top of your PR description: \"**This pull request was authored by a coding agent.**\"\n- You MUST mark your PRs as drafts\n- See [CONTRIBUTING.md](CONTRIBUTING.md) for other PR guidelines and CLA\n\n## Conventions\n\n### Python\n\nMost style rules are enforced by ruff (`pyproject.toml`) and pre-commit; run\n`make py-check`. Here are some that the linter may not catch, or for which\nwe may not have autofixes.\n\n- Docstrings are rendered as Markdown, not reStructuredText. Use single\n  backticks for inline code (`value`), never double backticks.\n\n<!-- File: development_docs/prompts.md (Tokens: ~118 | Category: root-instruction) -->\n# Prompts\n\n## System prompts\n\nPrompts are generated using the `Prompter` class in `marimo/_server/ai/prompts.py`.\n\n### Snapshots\n\nYou can create snapshots of the prompts using the `snapshot` function in `tests/_server/ai/test_prompts.py`. These snapshots are checked into the repo, and you can use them to verify that the prompts have not changed. To run these snapshots, run:\n\n```bash\nuv run --python 3.12 --group test-optional pytest tests/_server/ai/test_prompts.py\n```\n\n<!-- File: frontend/AGENTS.md (Tokens: ~374 | Category: root-instruction) -->\n# Frontend Guidelines\n\n## Key Principles\n\n- Write clear, maintainable code over clever/short syntax\n- Use TypeScript with proper typing for all code\n- Use functional programming patterns; avoid classes\n- Favor composition over inheritance\n- Reduce code duplication, if you see code that is repeated, refactor it to a function or component. This standardizes the codebase.\n\n## Naming Conventions\n\n- **Directories**: lowercase with dashes (`components/auth-wizard/`)\n- **Components**: PascalCase (`DashboardMenu.tsx`)\n- **Variables**: descriptive with auxiliary verbs (`isLoading`, `hasError`, `canSubmit`)\n\n## Testing\n\n### Unit Tests\n\nTests live alongside source files or in `__tests__` directories.\n\n```bash\npnpm turbo --filter @marimo-team/frontend test                            # All tests\npnpm turbo --filter @marimo-team/frontend test src/__tests__/lru.test.ts  # Specific file\n```\n\nBest practices:\n- test edge cases\n- use descriptive names\n- group with `describe`\n- prefer complete assertions over individual property checks (e.g., `expect(result).toEqual(expected)` rather than checking each property separately)\n\n### E2E Tests\n\nE2E tests use Playwright. See [e2e-tests/README.md](e2e-tests/README.md) for details.\n\n## Code Quality\n\nAvoid as much as possible using type assertions as they can cause runtime errors. Instead, use type guards, type predicates and error handling.\n```typescript\ncallFunction(x as T) // Avoid this\n```\n\n- Use logNever or assertNever to handle exhaustive switch cases.\n```typescript\nswitch (value) {\n  case \"a\":\n    break;\n  default:\n    logNever(value);\n}\n```\n\n- Keep comments minimal. Comments should only explain \"why\", not \"what\".\n\n<!-- File: marimo/AGENTS.md (Tokens: ~279 | Category: root-instruction) -->\n# Python Backend Guidelines\n\n## Testing\n\nTests live in `tests/` folder, mirroring `marimo/` structure.\n\n```bash\nuv run --group test pytest tests/path/to/test.py\nuv run --group test-optional pytest tests/path/to/test.py  # with optional deps\nuv run --group test --python 3.11 pytest tests/path/to/test.py  # specific python version\n```\n\nWe should utilize inline-snapshots more often to verify the outputs of objects, functions, etc.\nAvoid individual property assertions, opt for full object comparisons.\n\n```python\nfrom inline_snapshot import snapshot\nfrom dirty_equals import IsStr\n\n\ndef test_function():\n    assert func() == snapshot(\n        {\n            \"prop1\": IsStr(),\n            \"prop2\": \"some string\",\n        }\n    )\n```\n\n## Code Style\n\n- When writing comments, keep them minimal. Comments should explain \"why\", not \"what\"\n\n## Import handling\n\nGenerally, we should import at the top of the file. If there are circular imports, it means the file structure is not optimal. Refactor code to remove circular dependencies.\n\nHeavy dependencies must be imported lazily\n\n```python\ndef get_dataframe():\n    import pandas as pd  # altair, duckdb, numpy, polars, pyarrow, sqlglot, etc.\n\n    return pd.DataFrame()\n```\n\n<!-- File: DESIGN.md (Tokens: ~1994 | Category: project-spec) -->\n---\nversion: alpha\nname: marimo\ndescription: Design system for marimo, a reactive Python notebook for reproducible, git-friendly, deployable work.\ncolors:\n  background: \"#FFFFFF\"\n  background-dark: \"#181C1A\"\n  foreground: \"#0F172A\"\n  foreground-dark: \"#ECEEED\"\n  surface-muted: \"#F1F5F9\"\n  surface-muted-dark: \"#020303\"\n  muted-foreground: \"#64748B\"\n  muted-foreground-dark: \"#AAB2AF\"\n  popover: \"#FFFFFF\"\n  popover-dark: \"#252927\"\n  popover-foreground: \"#0F172A\"\n  popover-foreground-dark: \"#AAB2AF\"\n  card: \"#FFFFFF\"\n  card-dark: \"#252927\"\n  card-foreground: \"#0F172A\"\n  card-foreground-dark: \"#C0C6C3\"\n  border: \"#E2E8F0\"\n  border-dark: \"#3B403E\"\n  input: \"#A3A3A3\"\n  input-dark: \"#474C4A\"\n  primary: \"#0880EA\"\n  primary-dark: \"#28879F\"\n  on-primary: \"#F8FAFC\"\n  on-primary-dark: \"#B6ECF7\"\n  secondary: \"#F1F5F9\"\n  secondary-dark: \"#ECEEED\"\n  on-secondary: \"#0F172A\"\n  on-secondary-dark: \"#252927\"\n  accent: \"#EDF6FF\"\n  accent-dark: \"#1D5B6A\"\n  on-accent: \"#0B68CB\"\n  on-accent-dark: \"#B6ECF7\"\n  ring: \"#94A3B8\"\n  ring-dark: \"#2870BD\"\n  destructive: \"#E5484D\"\n  destructive-dark: \"#72232D\"\n  destructive-hover: \"#DC3E42\"\n  destructive-hover-dark: \"#8C333A\"\n  destructive-border: \"#CE2C31\"\n  destructive-border-dark: \"#FF9592\"\n  on-destructive: \"#FFFCFC\"\n  on-destructive-dark: \"#FFD1D9\"\n  error: \"#E5484D\"\n  error-dark: \"#72232D\"\n  on-error: \"#FFFCFC\"\n  on-error-dark: \"#FFD1D9\"\n  success: \"#46A758\"\n  success-dark: \"#2D5736\"\n  success-hover: \"#3E9B4F\"\n  success-hover-dark: \"#366740\"\n  success-border: \"#2A7E3B\"\n  success-border-dark: \"#71D083\"\n  on-success: \"#FBFEFB\"\n  on-success-dark: \"#C2F0C2\"\n  action: \"#FFE629\"\n  action-dark: \"#524202\"\n  action-hover: \"#FFDC00\"\n  action-hover-dark: \"#665417\"\n  action-border: \"#9E6C00\"\n  action-border-dark: \"#F5E147\"\n  on-action: \"#473B1F\"\n  on-action-dark: \"#F6EEB4\"\n  link: \"#0B68CB\"\n  link-dark: \"#479BF5\"\n  link-visited: \"#8E4EC6\"\n  link-visited-dark: \"#BF9BDF\"\n  stale: \"#EBE2CC\"\n  stale-dark: \"#525342\"\n  code-background: \"#FFFFFF\"\n  code-background-dark: \"#282C34\"\n  surface: \"#FFFFFF\"\n  surface-dark: \"#252927\"\n  code-foreground: \"#000000\"\n  code-foreground-dark: \"#ABB2BF\"\n  data-grid-accent: \"#7C3AED\"\ntypography:\n  body-md:\n    fontFamily: PT Sans\n    fontSize: 1rem\n    fontWeight: \"400\"\n    lineHeight: 1.75rem\n    letterSpacing: 0em\n  body-sm:\n    fontFamily: PT Sans\n    fontSize: 0.875rem\n    fontWeight: \"400\"\n    lineHeight: 1.25rem\n    letterSpacing: 0em\n  label-md:\n    fontFamily: PT Sans\n    fontSize: 0.875rem\n    fontWeight: \"500\"\n    lineHeight: 1.25rem\n    letterSpacing: 0em\n  label-xs:\n    fontFamily: PT Sans\n    fontSize: 0.75rem\n    fontWeight: \"600\"\n    lineHeight: 1rem\n    letterSpacing: 0em\n  markdown-heading:\n    fontFamily: Lora\n    fontSize: 1.875rem\n    fontWeight: \"600\"\n    lineHeight: 2.25rem\n    letterSpacing: -0.025em\n  code-editor:\n    fontFamily: Fira Mono\n    fontSize: 14px\n    fontWeight: \"400\"\n    lineHeight: 1.25rem\n    letterSpacing: 0em\n  slide-h1:\n    fontFamily: PT Sans\n    fontSize: 4.375rem\n    fontWeight: \"600\"\n    lineHeight: \"1.2\"\n    letterSpacing: 0em\nrounded:\n  sm: 4px\n  DEFAULT: 8px\n  md: 6px\n  lg: 8px\n  cell: 10px\n  xl: 0.75rem\n  full: 9999px\nspacing:\n  unit: 0.5rem\n  xs: 0.25rem\n  sm: 0.5rem\n  md: 1rem\n  lg: 1.5rem\n  xl: 3rem\n  content-compact: 740px\n  content-medium: 1110px\n  content-wide: 1400px\n  grid-row-height: 20px\n  grid-columns: \"24\"\ncomponents:\n  app-shell:\n    backgroundColor: \"{colors.background}\"\n    textColor: \"{colors.foreground}\"\n    typography: \"{typography.body-md}\"\n  cell:\n    backgroundColor: \"{colors.surface}\"\n    textColor: \"{colors.foreground}\"\n    typography: \"{typography.body-md}\"\n    rounded: \"{rounded.cell}\"\n    width: 100%\n  output-area:\n    backgroundColor: \"{colors.surface}\"\n    textColor: \"{colors.foreground}\"\n    typography: \"{typography.body-md}\"\n    padding: 1rem\n    width: 100%\n  code-editor:\n    backgroundColor: \"{colors.code-background}\"\n    textColor: \"{colors.code-foreground}\"\n    typography: \"{typography.code-editor}\"\n    width: 100%\n  button-primary:\n    backgroundColor: \"{colors.primary}\"\n    textColor: \"{colors.on-primary}\"\n    typography: \"{typography.label-md}\"\n    rounded: \"{rounded.md}\"\n    height: 2.25rem\n  button-action:\n    backgroundColor: \"{colors.action}\"\n    textColor: \"{colors.on-action}\"\n    typography: \"{typography.label-md}\"\n    rounded: \"{rounded.md}\"\n    height: 2.25rem\n  input:\n    backgroundColor: \"{colors.background}\"\n    textColor: \"{colors.foreground}\"\n    typography: \"{typography.body-sm}\"\n    rounded: \"{rounded.sm}\"\n    height: 1.5rem\n  data-table:\n    backgroundColor: \"{colors.surface}\"\n    textColor: \"{colors.foreground}\"\n    typography: \"{typography.body-sm}\"\n    width: 100%\n---\n\n## Brand Assets\n\n- Logo SVG: https://raw.githubusercontent.com/marimo-team/marimo/main/docs/_static/marimo-logotype-thick.svg\n- Preserve the original aspect ratio.\n- Do not recolor unless explicitly requested.\n\n## Visual Character\n\n- Compact, software-native, and utilitarian.\n- White or near-black work surfaces with slate borders and muted secondary text.\n- Restrained blue for primary interaction; yellow for action, stale, or needs-run states.\n- Avoid decorative gradients, marketing-style heroes, nested cards, and one-off palettes.\n\n## Color\n\n- Use background, surface, foreground, border, and muted tokens for structure.\n- Use primary for primary actions, selection, progress, and clear focus only.\n- Use action and stale colors for manual action or freshness state, not generic warning.\n- Use destructive, error, and success colors only for their semantic states.\n- Preserve light and dark token pairs whenever a color appears in both modes.\n\n## Typography\n\n- Use PT Sans for UI and prose, Lora for authored markdown headings, and Fira Mono for code-like values.\n- Keep control text compact and legible.\n- Do not add viewport-based type scaling beyond marimo's app defaults.\n\n## Surfaces\n\n- Use borders first and subtle shadows second.\n- Cells, outputs, editors, markdown, tables, and data grids should be full-width and overflow-safe.\n- Keep data UI dense and inspectable: stable columns, predictable overflow, readable headers, and no decorative framing around tables or charts.\n- Cards are for repeated items, dialogs, or genuinely framed tools; do not style page sections as cards.\n\n## Components\n\n- Buttons should be compact, label-like, focusable, and drawn from primary, secondary, or action semantics.\n- Icon buttons should use familiar existing icons and tooltips for unclear actions.\n- Inputs, selects, and textareas should be compact, bordered, readable, and use code typography only for code-like values.\n- Tabs, menus, popovers, dialogs, and tooltips should use semantic surfaces, borders, focus states, and restrained shadow.\n- Runtime states should pair color with labels, icons, borders, position, or shape.\n\n## Motion\n\nUse short transitions for hover, focus, loading, resize, drag, and stale-output changes. Avoid decorative animation.\n\n<!-- File: docs/guides/lint_rules/rules/branch_expression.md (Tokens: ~300 | Category: anthropic-skill) -->\n# Rules Skill\n\nPath: `docs/guides/lint_rules/rules/branch_expression.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/marimo-team/marimo/HEAD/docs/guides/lint_rules/rules/branch_expression.md)\n\n<!-- File: docs/guides/lint_rules/rules/cycle_dependencies.md (Tokens: ~300 | Category: anthropic-skill) -->\n# Rules Skill\n\nPath: `docs/guides/lint_rules/rules/cycle_dependencies.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/marimo-team/marimo/HEAD/docs/guides/lint_rules/rules/cycle_dependencies.md)\n\n<!-- File: docs/guides/lint_rules/rules/empty_cells.md (Tokens: ~300 | Category: anthropic-skill) -->\n# Rules Skill\n\nPath: `docs/guides/lint_rules/rules/empty_cells.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/marimo-team/marimo/HEAD/docs/guides/lint_rules/rules/empty_cells.md)\n\n<!-- File: docs/guides/lint_rules/rules/general_formatting.md (Tokens: ~300 | Category: anthropic-skill) -->\n# Rules Skill\n\nPath: `docs/guides/lint_rules/rules/general_formatting.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/marimo-team/marimo/HEAD/docs/guides/lint_rules/rules/general_formatting.md)\n\n<!-- File: docs/guides/lint_rules/rules/incompatible_import.md (Tokens: ~300 | Category: anthropic-skill) -->\n# Rules Skill\n\nPath: `docs/guides/lint_rules/rules/incompatible_import.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/marimo-team/marimo/HEAD/docs/guides/lint_rules/rules/incompatible_import.md)\n\n<!-- File: docs/guides/lint_rules/rules/incompatible_package.md (Tokens: ~300 | Category: anthropic-skill) -->\n# Rules Skill\n\nPath: `docs/guides/lint_rules/rules/incompatible_package.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/marimo-team/marimo/HEAD/docs/guides/lint_rules/rules/incompatible_package.md)\n\n<!-- File: docs/guides/lint_rules/rules/invalid_syntax.md (Tokens: ~300 | Category: anthropic-skill) -->\n# Rules Skill\n\nPath: `docs/guides/lint_rules/rules/invalid_syntax.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/marimo-team/marimo/HEAD/docs/guides/lint_rules/rules/invalid_syntax.md)\n\n<!-- File: docs/guides/lint_rules/rules/markdown_indentation.md (Tokens: ~300 | Category: anthropic-skill) -->\n# Rules Skill\n\nPath: `docs/guides/lint_rules/rules/markdown_indentation.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/marimo-team/marimo/HEAD/docs/guides/lint_rules/rules/markdown_indentation.md)\n\n<!-- File: docs/guides/lint_rules/rules/misc_log_capture.md (Tokens: ~300 | Category: anthropic-skill) -->\n# Rules Skill\n\nPath: `docs/guides/lint_rules/rules/misc_log_capture.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/marimo-team/marimo/HEAD/docs/guides/lint_rules/rules/misc_log_capture.md)\n\n<!-- File: docs/guides/lint_rules/rules/multiple_definitions.md (Tokens: ~300 | Category: anthropic-skill) -->\n# Rules Skill\n\nPath: `docs/guides/lint_rules/rules/multiple_definitions.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/marimo-team/marimo/HEAD/docs/guides/lint_rules/rules/multiple_definitions.md)\n\n<!-- File: docs/guides/lint_rules/rules/parse_stderr.md (Tokens: ~300 | Category: anthropic-skill) -->\n# Rules Skill\n\nPath: `docs/guides/lint_rules/rules/parse_stderr.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/marimo-team/marimo/HEAD/docs/guides/lint_rules/rules/parse_stderr.md)\n\n<!-- File: docs/guides/lint_rules/rules/parse_stdout.md (Tokens: ~300 | Category: anthropic-skill) -->\n# Rules Skill\n\nPath: `docs/guides/lint_rules/rules/parse_stdout.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/marimo-team/marimo/HEAD/docs/guides/lint_rules/rules/parse_stdout.md)\n\n<!-- File: docs/guides/lint_rules/rules/private_import_alias.md (Tokens: ~300 | Category: anthropic-skill) -->\n# Rules Skill\n\nPath: `docs/guides/lint_rules/rules/private_import_alias.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/marimo-team/marimo/HEAD/docs/guides/lint_rules/rules/private_import_alias.md)\n\n<!-- File: docs/guides/lint_rules/rules/reusable_definition_order.md (Tokens: ~300 | Category: anthropic-skill) -->\n# Rules Skill\n\nPath: `docs/guides/lint_rules/rules/reusable_definition_order.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/marimo-team/marimo/HEAD/docs/guides/lint_rules/rules/reusable_definition_order.md)\n\n<!-- File: docs/guides/lint_rules/rules/self_import.md (Tokens: ~300 | Category: anthropic-skill) -->\n# Rules Skill\n\nPath: `docs/guides/lint_rules/rules/self_import.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/marimo-team/marimo/HEAD/docs/guides/lint_rules/rules/self_import.md)\n\n<!-- File: docs/guides/lint_rules/rules/setup_cell_dependencies.md (Tokens: ~300 | Category: anthropic-skill) -->\n# Rules Skill\n\nPath: `docs/guides/lint_rules/rules/setup_cell_dependencies.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/marimo-team/marimo/HEAD/docs/guides/lint_rules/rules/setup_cell_dependencies.md)\n\n<!-- File: docs/guides/lint_rules/rules/sql_parse_error.md (Tokens: ~300 | Category: anthropic-skill) -->\n# Rules Skill\n\nPath: `docs/guides/lint_rules/rules/sql_parse_error.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/marimo-team/marimo/HEAD/docs/guides/lint_rules/rules/sql_parse_error.md)\n\n<!-- File: docs/guides/lint_rules/rules/unparsable_cells.md (Tokens: ~300 | Category: anthropic-skill) -->\n# Rules Skill\n\nPath: `docs/guides/lint_rules/rules/unparsable_cells.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/marimo-team/marimo/HEAD/docs/guides/lint_rules/rules/unparsable_cells.md)\n\n<!-- File: docs/guides/lint_rules/rules/unsafe_system_call.md (Tokens: ~300 | Category: anthropic-skill) -->\n# Rules Skill\n\nPath: `docs/guides/lint_rules/rules/unsafe_system_call.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/marimo-team/marimo/HEAD/docs/guides/lint_rules/rules/unsafe_system_call.md)\n\n<!-- File: marimo/_server/ai/skills/marimo-pair/references/gotchas.md (Tokens: ~300 | Category: anthropic-skill) -->\n# References Skill\n\nPath: `marimo/_server/ai/skills/marimo-pair/references/gotchas.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/marimo-team/marimo/HEAD/marimo/_server/ai/skills/marimo-pair/references/gotchas.md)\n\n<!-- File: marimo/_server/ai/skills/marimo-pair/references/notebook-improvements.md (Tokens: ~300 | Category: anthropic-skill) -->\n# References Skill\n\nPath: `marimo/_server/ai/skills/marimo-pair/references/notebook-improvements.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/marimo-team/marimo/HEAD/marimo/_server/ai/skills/marimo-pair/references/notebook-improvements.md)\n\n<!-- File: marimo/_server/ai/skills/marimo-pair/references/rich-representations.md (Tokens: ~300 | Category: anthropic-skill) -->\n# References Skill\n\nPath: `marimo/_server/ai/skills/marimo-pair/references/rich-representations.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/marimo-team/marimo/HEAD/marimo/_server/ai/skills/marimo-pair/references/rich-representations.md)\n\n<!-- File: marimo/_server/ai/skills/marimo-pair/SKILL.md (Tokens: ~2591 | Category: anthropic-skill) -->\n---\nname: marimo-pair\ndescription: >-\n  Work inside the user's live marimo notebook from the code editor: run Python\n  in the same kernel the user does, inspect live notebook state, and commit\n  durable notebook changes through code mode. Use whenever you create, analyze,\n  or improve the user's marimo notebook.\n---\n\nmarimo is a reactive Python runtime for building reproducible Python programs\n(marimo notebooks). Cells are connected by the variables they define and\nreference. Running a cell re-executes dependents in dataflow order. The active\nruntime holds the kernel namespace, cell state, and dataflow graph. The\nnotebook (`.py` file) is the artifact the kernel writes from that state while a\nsession is running.\n\nA user interacts with the same runtime via a notebook UI with cells, outputs,\nand widgets.\n\n**WARNING. The active runtime is the source of truth.** You are working inside\nthe user's live notebook session. The kernel — not the `.py` file on disk —\nholds the truth about cells, variables, and the dataflow graph. Make every\nnotebook change through `marimo._code_mode` (`cm`); direct file edits WILL NOT\nreach the live kernel or user, and the kernel may overwrite them on save.\nReading disk is fine, but prefer `ctx.cells[...].code` for current cell code.\n\n**WARNING. Every notebook edit goes through code mode — no exceptions.** When\nthe user asks you to change the notebook (add, edit, delete, or run a cell;\nrename; change a value or a package), you MUST make that change through\n`marimo._code_mode` (`cm`) by running it with the `execute_code` tool. There is\nno separate file-editing path — `execute_code` + `cm` is the only way to reach\nthe user's running session. Running ad-hoc Python with `execute_code` to\nexplore or test is fine; _persisting any change to the notebook_ is only ever\ndone via `cm`.\n\n## Running Code in the Kernel\n\nYou are already attached to the user's running notebook — there is nothing to\nconnect to or start. Use the `execute_code` tool to run Python in that kernel,\npassing your Python as the `code` argument. Everything you do — inspecting\nstate, testing transformations, and persisting changes via `cm` — runs through\n`execute_code` in the scratchpad (see below).\n\n## Required First Kernel Command\n\nStart every code-mode session with this dedicated `execute_code` call:\n\n```python\nimport marimo._code_mode as cm\n\nhelp(cm)\n```\n\nFollow this order for every live kernel, including read-only tasks:\n\n1. Run only the inspection command above.\n2. Wait for successful `help(cm)` output.\n3. Use `cm.get_context()` or another `cm` API in a later `execute_code` call.\n\nDo not combine the inspection with task-specific code, and do not use another\n`cm` API before the inspection succeeds. This verifies the private, unstable\nAPI exposed by the marimo version in the user's active kernel.\n\n## Scratchpad Scope\n\n`execute_code` evaluates Python in marimo's scratchpad: a temporary namespace\nwith a shallow copy of the kernel globals. Notebook variables are available by\nname, but new top-level bindings and rebindings are discarded after each call.\nIn-place mutations to notebook-owned objects can persist because those names\nstill reference live objects.\n\nEach call reports stdout and stderr from the scratchpad, plus console output\nfrom notebook cells it causes to run, including reactive descendants.\n\n### Ordinary Python\n\nUse ordinary Python in the scratchpad to inspect variables, sample data, test\ntransformations, probe APIs, check imports, and read widget state.\n\n```python\nprint(df.head())\n\nx = 10\nprint(x)\n```\n\nHere `df` comes from notebook globals, while `x` is a scratchpad-local binding.\n`x` exists for this call only and WILL NOT be added to notebook globals.\n\n### Persist with `cm`\n\nTop-level scratchpad assignments and rebindings are temporary. To persist work,\nincluding new variables, you MUST submit changes through `marimo._code_mode`\n(`cm`).\n\n`marimo._code_mode` is a PRIVATE, UNSTABLE agent API (note the leading\nunderscore). It exists for tools like this skill to drive a live kernel from\nthe scratchpad. DO NOT import it from notebook cells, library code, or\nanything a user would run — methods can change or disappear across marimo\nversions and kernels. Treat every `import marimo._code_mode as cm` as\nscratchpad-only.\n\nOpen a code-mode context to queue notebook changes.\n\n```python\nimport marimo._code_mode as cm\n\nasync with cm.get_context() as ctx:\n    cid = ctx.create_cell(\"x = df.head()\")\n    ctx.run_cell(cid)\n```\n\nThe scratchpad supports top-level async code. Use `async with` directly;\nwrapping it in `asyncio.run(...)` is unnecessary and can conflict with the\nkernel's event loop.\n\nAfter this block exits and the new cell runs, `x` is notebook state. Later\nscratchpad calls can read `x` by name. Code later in the same scratchpad call\nshould read `ctx.globals[\"x\"]`, because the scratchpad namespace was copied\nbefore the cell ran.\n\nInside the context, queued mutation methods are synchronous. Call them\ndirectly; do not `await` them. Each call queues an operation for marimo to\napply when the context exits normally. If the block raises, the queue is\ndiscarded.\n\nOn clean exit, marimo applies packages, validates and applies structural cell\nchanges, runs queued cells, then may run dependents. Validation is only\nstructural since queued cell runs can still error. `create_cell` and\n`edit_cell` change notebook structure only. Use `run_cell` to execute.\n\n`create_cell` currently defaults to `hide_code=True`, which collapses the code\neditor in the UI. Pass `hide_code=False` if the user wants created cells to\nbe visible without manually expanding them.\n\n## Marimo Rules\n\nmarimo imposes a small contract on notebook code so it can keep the notebook as\na directed acyclic graph (DAG):\n\n- **No cycles** - cells cannot depend on each other in a cycle.\n- **No public redefinitions across cells** - each name has one owning cell.\n- **No wildcard imports** - `import *` prevents static analysis of definitions.\n\nThese rules keep the kernel, UI, and saved artifact consistent.\n\nWhen `cm` submits a cell body, marimo parses its top-level definitions and\nreferences. A top-level name enters the graph unless it is private with a\nleading underscore.\n\n```python\n# Public definitions: values, total, i, value, mean\nvalues = np.array([1, 2, 3])\ntotal = 0\nfor i, value in enumerate(values):\n    total += value\nmean = total / len(values)\nmean\n```\n\n```python\n# Public definition: mean\n_values = np.array([1, 2, 3])\n_total = 0\nfor _i, _value in enumerate(_values):\n    _total += _value\nmean = _total / len(_values)\nmean\n```\n\nUse private names for intermediates that no other cell should read. Public\nnames define the notebook-level dataflow. If a `cm` edit violates the contract,\nmarimo rejects the structural change and returns the validation error.\n\n## The Notebook's Shape\n\nA notebook is an ordered collection of cells. `ctx.cells` is the document view\nand `ctx.graph` is the dataflow view.\n\n```python\nfor cell in ctx.cells:\n    cell  # .id, .code, .name, .config, .status, .errors\n\nctx.cells[\"setup\"]  # by name\nctx.cells[0]  # by position\nlist(ctx.cells.keys())  # all IDs, in notebook order\n```\n\nCell IDs are opaque strings which can be queried from the notebook or captured\nfrom `cm` return values:\n\n```python\ncid = ctx.create_cell(\"df = pd.read_csv('data.csv')\")\nprint(cid)  # e.g. 'Hbol'\n```\n\nAlternatively, cells can be assigned and referenced by `name`. The graph can be\nused to understand its role in the dataflow.\n\n```python\nfor cid, impl in ctx.graph.cells.items():\n    impl  # .defs, .refs   (sets of public names)\n\nctx.graph.descendants(cid)  # cells that re-run when this one changes\nctx.graph.ancestors(cid)  # cells this one depends on\n```\n\nIn marimo, deletes are _destructive_ so it can be useful to query the\ndescendants prior to deleting to understand it's impact.\n\n## Writing Notebook Changes\n\nThe graph contract keeps marimo able to run and save the notebook. Passing\nthose checks alone does not guarantee a useful artifact. Committed cells should\nstill be readable, rerunnable, and editable.\n\nMake durable edits that reuse the notebook's existing names, imports,\ndependencies, and UI model. Don't be lazy. Avoid one-off workarounds that pass\n`cm` validation but leave a brittle notebook.\n\n### Cell Bodies\n\nSubmit the code that belongs in the cell.\n\n- **Submit cell contents** - `create_cell` and `edit_cell` take cell contents,\n  not saved-file `@app.cell` wrappers.\n- **Read before replacing** - for now, another editor may change a cell between\n  scratchpad calls. Before `edit_cell`, read the current body from\n  `ctx.cells[...]` and submit the full replacement.\n- **Reuse notebook imports** - if `np` already exists, use it or edit the owning\n  import cell. DO NOT add `import numpy as _np` just to bypass the graph.\n- **Define public names intentionally** - use public names for values later\n  cells should reference. Use private `_name` bindings or function locals for\n  same-cell intermediates.\n- **Define each public name once** - a public name has one owning cell.\n  Reassigning it in another cell fails with `Multiply-defined names`; edit the\n  owning cell or give the result a new name. Load the `gotchas` capability for\n  more traps.\n- **Run cells deliberately** - `create_cell` and `edit_cell` change structure\n  only. Queue `ctx.run_cell(...)` when the cell should execute.\n\n### Prefer `cm`-Managed Changes\n\nUse `cm` APIs when they exist. Avoid direct file edits, shell package commands,\nand scratchpad-only state for changes that should persist.\n\n- **Persist only through `cm`** - never try to change the notebook by writing\n  the `.py` file; `execute_code` + `cm` is the only path that reaches the live\n  session. Use `ctx.edit_cell(...)` even for small changes.\n- **Manage packages through `cm`** - use `ctx.packages.add()` or\n  `ctx.packages.remove()` instead of direct `uv` or `pip`; confirm\n  non-obvious dependency changes.\n- **Avoid transient paths** - persisted cells should not depend on `/tmp/...`\n  unless the work is intentionally transient.\n- **Delete deliberately** - deleting a cell removes globals it defines. Reuse\n  empty cells when convenient and delete cells left empty after edits.\n\n### UI and Widgets\n\nInspect the object before changing it. Different UI objects update through\ndifferent paths.\n\n- **Set `mo.ui.*` through `cm`** - use `ctx.set_ui_value(element, value)` inside\n  `cm.get_context()`.\n- **Set anywidget traitlets directly** - synced traitlets are Python\n  attributes, for example `widget.value = 5`.\n\nFor designing custom visual or interactive output, load the\n`rich-representations` capability.\n\n## On-demand references\n\nLoad these with the `load_capability` tool when you need deeper guidance. Do\nnot read reference files from disk.\n\n- **`gotchas`** — name redefinition, cached module proxies, and notebook traps\n- **`rich-representations`** — custom widgets and visualizations\n- **`notebook-improvements`** — improving existing notebooks\n\n<!-- File: packages/client/package.json (Tokens: ~300 | Category: anthropic-skill) -->\n# Client Skill\n\nPath: `packages/client/package.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/marimo-team/marimo/HEAD/packages/client/package.json)\n\n<!-- File: packages/client/REDUCERS.md (Tokens: ~1035 | Category: anthropic-skill) -->\n# Keep state from events\n\nHost state is read over event streams. The catalog stream describes the\nhost's notebooks, projects, runtimes, and attachments. A notebook stream\ndescribes one notebook's document and execution state.\n\nA stream starts with a snapshot of the current state. A `ready` event marks\nthe end of the snapshot. Subsequent events report changes. For example, a\n`notebook` event carries the notebook's current record, and\n`notebook.removed` identifies a notebook that was removed.\n\n`CatalogEvents` and `NotebookEvents` validate incoming events and track the\ncursor used to resume after a disconnect. They deliver events through an\nasync iterator or a subscription. Your application decides which records\nto retain. If the stream cannot resume, it delivers `reset` followed by a\nnew snapshot that replaces the previous state.\n\n## Keep a notebook list\n\nTo keep a notebook list, define a resource that starts with an empty list.\nIts `notebook` handler adds or replaces an entry. Its `notebook.removed`\nhandler removes an entry by id. Each entry keeps only the notebook's id\nand name.\n\nPass the resource to `createCatalogReducer`, then apply each event with\n`reduce(state, event)`. The resulting list is in `state.resources.notebooks`.\nThis example stops at `ready` and prints the list from the snapshot.\n\n```ts\nimport type { NotebookOutput } from \"@marimo-team/client/protocol\";\nimport {\n  Client,\n  createCatalogReducer,\n  type CatalogResource,\n} from \"@marimo-team/client\";\n\ntype NotebookSummary = Pick<NotebookOutput, \"id\" | \"name\">;\n\nconst notebooks: CatalogResource<readonly NotebookSummary[], \"notebook\"> = {\n  initial: [],\n  on: {\n    notebook: (state, { data }) => [\n      ...state.filter((entry) => entry.id !== data.notebook.id),\n      { id: data.notebook.id, name: data.notebook.name },\n    ],\n    \"notebook.removed\": (state, { data }) =>\n      state.filter((entry) => entry.id !== data.id),\n  },\n};\n\nconst reducer = createCatalogReducer({ notebooks });\nconst client = new Client(\"http://127.0.0.1:2718/api/marimo/v1\", {\n  token: \"your-token\",\n});\nlet state = reducer.initial;\n\nfor await (const event of client.events({ types: [\"notebook\"] })) {\n  state = reducer.reduce(state, event);\n  if (event.event === \"ready\") break;\n}\n\nconsole.log(state.resources.notebooks);\n```\n\nThe reducer handles the stream's lifecycle. `ready` changes `state.phase`\nfrom `snapshot` to `live`. `reset` returns the phase to `snapshot` and each\nresource to its initial value. Resources can handle `ready` to finish\nassembling a snapshot. The handler's third argument contains the phase\nbefore the event is applied. It is `snapshot` for the initial `ready` and\n`live` for a `ready` that follows a resumed connection.\n\nHandlers return a new value when state changes and the existing value\notherwise. They must not modify the previous value or perform side effects.\n\nFor a notebook stream, define a `NotebookResource` and pass it to\n`createNotebookReducer`. This reducer also keeps the notebook's record and\nidentity in `notebook` and `notebookId`. It handles `notebook` and\n`notebook.removed` itself. Removing the notebook clears its record and\nresources. A `reset` also clears its identity.\n\n## Follow changes in React\n\nTo keep a notebook list updated in a UI, subscribe to the stream and pass\neach event to the reducer through your store's state update function. This\nhook uses React state. It removes the subscription and closes the stream\nwhen the effect is cleaned up.\n\n```tsx\nimport { useEffect, useState } from \"react\";\n\nfunction useNotebooks(client: Client) {\n  const [state, setState] = useState(reducer.initial);\n\n  useEffect(() => {\n    setState(reducer.initial);\n    const events = client.events({ types: [\"notebook\"] });\n    const unsubscribe = events.subscribe((event) => {\n      setState((current) => reducer.reduce(current, event));\n    });\n    return () => {\n      unsubscribe();\n      events.close();\n    };\n  }, [client]);\n\n  return state;\n}\n```\n\nKeep the client instance stable across renders. Temporary disconnects preserve\nstate while the stream resumes. A `reset` rebuilds it. Pass a second function\nto `subscribe` to surface connection failures in your application. It\nreceives the error when the stream stops.\n\nIf you persist state for a later connection, save its matching cursor and\nreuse the same host, stream, and filter. The stream's cursor tracks received\nevents. When state updates are queued, as in React, it can be ahead of the\nstate you have applied. Resume needs both state and its matching cursor.\n\n<!-- ... +25 more modular skills available via /api/skills/marimo-team/marimo?path={path} -->\n</yakaai_skills>"}