Bidirectional converter between marimo notebooks and dagster asset modules. Explore data interactively in marimo, then convert to dagster for production orchestration — or go the other way to debug and iterate on existing pipelines.
- Marimo to dagster:
@app.cellfunctions become@dg.assetfunctions, with the dependency graph inferred from cell inputs/outputs. - Dagster to marimo:
@dg.assetfunctions become@app.cellfunctions, with docstrings converted to markdown cells. - SQL cell conversion:
mo.sql()calls are rewritten toduckdb.sql()so SQL-based notebooks translate into runnable dagster assets. - PEP 723 metadata:
# /// scriptdependency blocks are preserved and framework dependencies are swapped automatically (marimo ↔ dagster). - Decorator kwargs:
@dg.asset(group_name=..., compute_kind=...)metadata survives the round trip. - Framework stripping: dagster-specific parameters (
AssetExecutionContext, resource types) and framework calls (context.log.info()) are removed during conversion, keeping the notebook focused on data logic.
pip install marimo-dagsterOr with uv:
uv add marimo-dagsterConvert a marimo notebook to a dagster asset module:
marimo-dagster to-dagster notebook.py assets.pyConvert a dagster asset module to a marimo notebook:
marimo-dagster to-marimo assets.py notebook.pyfrom marimo_dagster import marimo_to_dagster, dagster_to_marimo
dagster_source = marimo_to_dagster(open("notebook.py").read())
marimo_source = dagster_to_marimo(open("assets.py").read())| Marimo cell type | Dagster conversion |
|---|---|
| CODE | @dg.asset function |
SQL (mo.sql()) |
@dg.asset using duckdb.sql() |
| IMPORT_ONLY | Merged into the dagster import block |
| MARKDOWN | Dropped (preserved as docstrings on round-trip) |
UI (mo.ui.*) |
Dropped (interactive-only) |
| DISPLAY_ONLY | Dropped (display-only) |
make test # pytest with 100% coverage
make typecheck # ty type checker
make ruff # ruff linter
make all-tests # all threeReleases are automated on pushes to main by the CD workflow in .github/workflows/cd.yml.
- The workflow determines the latest
v*Git tag and runs.github/workflows/cd_version.pyto resolve the next version. If the latest tag matches the current major/minor, it bumps the patch to one higher than the max of the current patch and the tag patch. - If
pyproject.tomlchanges, the workflow commits the version bump back tomain. - It tags the release as
v<version>, builds the wheel withuv build, and creates a GitHub release.
To enable PyPI publishing, set PUBLISH_TO_PYPI: true in .github/workflows/cd.yml and configure
PyPI trusted publishing for this repository.