Guidance for coding agents working in this uv, pnpm, and Vite+ workspace. marimo-export runs selected marimo notebook states and writes one verified export for applications, agents, Python, and custom clients.
Use the Python version from .python-version and the Node, pnpm, and Vite+
versions declared by package.json and pnpm-workspace.yaml. CI verifies the
Python package on every supported version on Ubuntu and Windows.
| Task | Command | Expected result |
|---|---|---|
| Install | make bootstrap |
Locked Python and TypeScript workspaces sync |
| Format | make format |
Authored source is formatted |
| Lint | make lint |
Python and TypeScript boundaries pass |
| Type-check | make typecheck |
Python and TypeScript types pass |
| Test | make test |
Python, browser, loader, skill, and app tests pass |
| Build | make build |
Python, npm, docs, and example packages build |
| Build docs | make docs-build |
VitePress site and LLM text bundles build |
| Serve docs | make docs-serve |
Portless prints the workspace-specific documentation URL |
| Package | make package |
Python and npm release artifacts pass isolated smoke tests |
| Complete local gate | make check |
Format, lint, types, tests, builds, and package smoke pass |
Run focused package commands while developing, then finish with make check.
- marimo owns notebook parsing, reactive execution, dependency pruning, cell hashing, computation-cache persistence, UI updates, and native serialization.
- marimo-export owns StateSpace and ExportSpec normalization, observations, state planning, preparation, reusable prepared outputs, export integrity, and typed Python and browser consumption.
- The export repository stores preparation metadata in private SQLite tables and portable artifacts in immutable directories. Marimo's native cache remains the computation cache.
- Producer functions call services under
_services. Those services use the privatePreparationRepository. The observation ledger uses the privateObservationRepository. Reader, public repository, inspection, and diagnostic operations use their focused owners. - Private
marimo._*imports stay under_marimo/compat. The package pins its supported Marimo release inpackages/python/pyproject.tomland validates the marimo source digests recorded in_marimo/compat/release.jsonbefore installing a reversible adapter lease. OwnedNotebookowns a temporary notebook copy, loopback server, session, process groups, and cleanup.prepareuses one owned context when work is missing.captureborrows one active edit session.packages/portable-jsonowns the cross-language JSON boundary.packages/browserowns export parsing, integrity, immutable readers, prepared-publication control, and loader contracts. Eachpackages/loader-*owns one representation runtime.- Applications compose the public Python SDK and browser
preparedsubpath. The proposed marimo-studio prepared runtime remains outside current architecture until its cross-repository acceptance conditions pass. docs/owns user workflows and reference.development_docs/owns code ownership, lifecycle, compatibility seams, and contributor validation.
Read Architecture before changing an ownership or lifecycle boundary.
Dependencies point from each public operation toward its focused owner. The producer path continues through narrow capabilities to private adapters:
CLI and applications -> public Python SDK
producer operations -> services -> records and capabilities
reader operations -> reader and verification
repository API -> ExportRepository -> SQLite and artifact adapters
diagnostics -> Marimo composition root
Observation ledger -> ObservationRepository -> SQLite adapter
Observation runs -> KernelRun records -> Marimo composition root -> compat run hook
Producer services -> PreparationRepository -> repository adapters
Marimo bridge -> exporter preparation -> ExporterRuntime port
Marimo composition roots -> private Marimo compatibility adapters
Compatibility adapters -> marimo-export policy modules
Browser application -> prepared controller -> browser core -> loader facade
-> one loader runtime
_servicesowns planning, preparation, capture, artifact assembly, and durable writes.delivery.pyowns application-level staging and prepared-export materialization._directory*.pyowns destination races, native exchange, and rollback._repository/preparation.pyis the private preparation capability available to services._repository/observations.pyis the private raw observation capability available to the ledger and preparation._repository/sqliteowns SQL and schema details._marimo/composition.py,_marimo/anywidget.py,_marimo/blob.py,_marimo/entrypoints.py, and_marimo/managed_server.pyconstruct private Marimo adapters._marimo/compat/observations.pyreports each finished cell-runner pass as aKernelRun._observations/runs.pydecides which runs become observations, and_observations/source.pybinds them to one stable source revision.exporters/_prepare.pyresolves and freezes exporters through theExporterRuntimeport.PrivateKernelRuntimein_marimo/compat/kernel.pyimplements it with the kernel reads in_marimo/compat/exporters.py.exporters/_identity.pyhashes exporter sources and detects drift.- Compatibility adapters delegate these decisions to marimo-export policy
modules.
_marimo/file_urls.pyparses marimo file URLs,_marimo/ui_functions.pydecides which UI functions an output may list,exporters/_anywidget_assets.pyvalidates AnyWidget modules and styles,_environment.pycomputes the import-scoped environment identity that producer identity and the native cell cache share, and_execution/plan.pydecides which output cells run live. _remoteowns HTTP, authentication, scratchpad transport, server-sent events, and managed process ownership.- Browser core imports no specialized chart, table, array, or widget runtime.
- Loader packages either implement browser contracts or expose a browser-independent decoder bound by one public facade. A loader package referenced by browser remains browser-independent. Loader packages remain independent of one another.
- Add dependencies to the smallest workspace member that imports them.
Ruff and repository boundary tests enforce service, repository, and private Marimo containment. Vite+ enforces browser and loader direction.
marimo-export creates a notebook export. Use export after defining the noun once.
| Action | Verb |
|---|---|
| Resolve reusable and missing work | plan |
| Prepare from a notebook file | prepare |
| Prepare from a running session | capture |
| Prepare and write from a notebook file | build |
| Write a prepared export | write |
| Read in Python or TypeScript | open |
| Select a state by name or inputs | resolve |
| Decode an output for browser use | load |
| Attach an interactive value to the DOM | mount |
| Put static files on a host | deploy or serve |
| Release a package to a registry | publish |
A state space is a finite declaration of explicit state rows, a Cartesian input matrix, or both. A state is one complete assignment for the inferred ExportSpec inputs. Authors may write sparse rows because one captured baseline supplies omitted values. An observation is one successful complete input vector retained as authoring evidence. A prepared state is a reusable portable result for one producer, output plan, and state fingerprint. A prepared export is a leased immutable generation for one exact ExportSpec. An output is one published name with a representation in every state, or an unavailable entry where an optional output has no value. An asset is a content-addressed file referenced by an output descriptor. A consumer is a Python reader, browser reader, agent, or another implementation of the export format.
| Change | Primary owner | Required companions |
|---|---|---|
| StateSpace, ExportSpec, or state normalization | spec.py, _execution/plan.py, planning.py |
YAML, JSON, programmatic, matrix, and live-state tests |
| Observation lifecycle | observations.py, _observations/runs.py, _repository/observations.py |
Success, queue, and close tests |
| Observation source matching | _observations/source.py, compat/observations.py |
Source-match, revision, and KernelRun tests |
| Planning or preparation | _services, prepared.py, progress.py, _index_budget.py |
Exact reuse, incremental state, cancellation, and live tests |
| Repository or retention | repository.py, _repository |
SQLite, filesystem, concurrency, fencing, and recovery tests |
| Export format or local reader | descriptors.py, index.py, wire.py, reader.py, _limits.py |
Browser schema and canonical fixtures |
| Marimo integration or cache | _marimo/capabilities.py, composition, one compat adapter |
Probe, adapter, build, and capture tests |
| Live outputs and cache bypass | _execution/plan.py, exporters/_definitions.py |
Warm-build cache hit and miss tests |
| Environment identity | _environment.py |
Import closure, script metadata, and reuse tests |
| Exporter resolution or identity | exporters/_prepare.py, exporters/_identity.py, compat/exporters.py |
Identity pin, source drift, and custom exporter build tests |
| marimo file URLs or exported UI functions | _marimo/file_urls.py, _marimo/ui_functions.py |
URL grammar, read-only table, and transfer tests |
| Managed process lifecycle | producer.py, _remote/managed.py, managed entry points |
Startup, shutdown, source, and descendant tests |
| Prepared browser control | packages/browser/src/prepared |
Manifest, refresh, transition, cancellation, packed tests |
| Browser reader or loader contract | packages/browser |
TypeScript and cross-language tests |
| Portable JSON contract | packages/portable-json, _json.py |
Cross-language fixtures and packed consumers |
| One output representation | packages/loader-*, exporters/_runtime, exporters/_anywidget_assets.py |
Peer dependency, malformed input, abort, and disposal tests |
| Value selection or media negotiation | values.py |
Grammar, resolution, renderer, and standard-library tests |
| CLI or public Python API | _cli, package root, public records |
Human output, JSON, JSONL, exit, and wheel smoke |
| Application directory delivery | delivery.py, _directory* |
Materialization, races, rollback, and Windows tests |
| External consumer integration | Public SDK and browser prepared subpath |
Consumer revision and cross-repository acceptance tests |
| Example or browser transition | examples/vite-vanilla |
Typecheck, build, desktop, and narrow browser proof |
| Public documentation | docs/, VitePress config |
Examples, links, search, LLM bundles, and rendered proof |
- Every output runs through one transient marimo leaf for every state, unless an optional output is already known to be unavailable in that state.
- State vectors are complete and fingerprinted before execution.
- The ExportSpec names an explicit default state. Authoring observations remain repository history until an application places them in an explicit spec.
- Public observation and exact-prepared repository operations accept an
ExportPlan. Raw producer keys remain inside private repository capabilities. - A prepared state is reusable by producer identity, output-plan identity, and complete state fingerprint. A prepared export adds the exact spec identity.
- Exact reuse returns a leased
PreparedExportbefore starting a notebook. - Ordinary overrides and UI updates stay local to one child state run.
- AnyWidget patches record the complete serializer-owned model state.
- The authored notebook source remains byte-for-byte unchanged.
- The client and attached kernel use the same marimo-export version and source identity.
- One failed state, output, transfer, or verification fails the complete producer operation. An optional output records an unavailable output for a missing value, missing representation, or stopped closure instead. Cleanup preserves the primary error. Post-commit parent sync and retired-destination cleanup failures return typed warnings.
- Preparation reservations carry monotonically increasing fencing tokens. Publication compares the current pointer and reservation owner before commit.
- Active artifact, staging, and preparation leases renew until their owner closes. Retention preserves every live artifact.
- Repository storage failures preserve the current prepared export. Confirmed integrity failures retire the affected artifact for cleanup.
index.jsonis canonical UTF-8 JSON and the single export entry point.- Readers verify the declared asset closure before decoding output data.
- Application delivery re-verifies each materialized export before committing the complete outer directory.
- Opening and verification execute no notebook-authored browser module. Mounting an interactive value grants it page authority.
- Test through public APIs, command results, files, protocol records, package imports, or browser state. Avoid assertions on private helper trivia.
- Run live build and capture evidence after changing marimo integration, process ownership, state execution, cache behavior, or transfer.
- Use browser inspection for layout, responsive behavior, rapid state changes, charts, AnyWidgets, cancellation, and mount disposal.
- Rebuild generated package and documentation output from its owning source. Do not commit raw build directories.
- Contributor guide
- Architecture
- Product model and export format
- Preparation
- Export repository
- Ports and composition
- Execution and caching
- marimo integration
- Proposed Marimo upstream capabilities
- Browser loaders and mounts
- Live transport and processes
- Application publication and delivery
- Identities and protocols
- Portable JSON
- Runtime profiles
- Proposed marimo-studio prepared runtime
- Failure and concurrency
- Product surfaces and distribution
- Development
- Documentation system
- Validation
- Releasing