Write Marimo notebooks that also work as CLI scripts, with unified UI controls
Project description
moops
Easily write Marimo notebooks that work as CLI scripts (and more!) with minimal boilerplate.
Marimo supports notebooks running as CLI scripts, but until now this required maintaining matching input handling implementations.
Using moops, both implementations are merged into one.
Installation
uv add (or pip install) moops
Transition guide
- Create your argument group:
args = moops.Group() - Replace your
mo.uiusages with using methods ofargs - Add
args.interfacecall, preferably as the top cell, and provide the UI elements to it. This makes the notebook works as a script and adds info about it in the notebook.
Now your notebook doubles as a CLI script
Running notebooks from Python
Notebooks can also be called from Python with moops.run.
This is useful for testing notebook logic without launching Marimo,
and for reusing notebook logic from other code.
Expose a variable named result from the notebook:
@app.cell
def _(input_text, mode_dropdown):
result = mode_dropdown.value(input_text.value)
return (result,)
Then call the notebook module directly:
import moops
from examples import name_casing
result = moops.run(
name_casing,
text="Hello World",
style="snake_case",
)
assert result == "hello_world"
Keyword arguments override moops.Group inputs by their option names,
with leading dashes removed and dashes converted to underscores.
If no overrides are provided, moops.run uses the notebook defaults.
Property-based testing
moops.testing.notebook_interface returns the notebook's Interface, from which .strategy() generates a Hypothesis strategy that produces valid moops.run kwargs by introspecting the notebook's interface — dropdowns yield their allowed keys, switches yield booleans, and text fields yield arbitrary strings.
from examples import name_casing
_name_casing_interface = moops.testing.notebook_interface(name_casing)
_name_casing_defaults = _name_casing_interface.default
@hypothesis.given(_name_casing_interface.strategy())
def test_name_casing_preserves_alphanumeric_count(kwargs):
result = moops.run(name_casing, **kwargs)
input_text = kwargs.get("input_text", _name_casing_defaults["input_text"])
assert sum(c.isalnum() for c in result) == sum(c.isalnum() for c in input_text)
Running the examples
From the project root:
uv run examples/notebook.py
Or uv run marimo edit to run as notebooks.
Feedback welcome
This is an early release — issues, ideas, and pull requests are very welcome on GitHub.
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file moops-0.1.1.tar.gz.
File metadata
- Download URL: moops-0.1.1.tar.gz
- Upload date:
- Size: 11.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
27bcbe3a941c8ce54cdaf9aae579833619894731b8f6db5996425dc7e44d8047
|
|
| MD5 |
2b69336e667382542cb5a2360368901d
|
|
| BLAKE2b-256 |
532e6e96a13d7a36118cafe87ffd343a4475cd5a9f42a8a8d66d3fc5e1493d2c
|
Provenance
The following attestation bundles were made for moops-0.1.1.tar.gz:
Publisher:
publish.yml on yairchu/moops
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
moops-0.1.1.tar.gz -
Subject digest:
27bcbe3a941c8ce54cdaf9aae579833619894731b8f6db5996425dc7e44d8047 - Sigstore transparency entry: 1484803958
- Sigstore integration time:
-
Permalink:
yairchu/moops@25a4c145d0479d3df6454550b5a15c24be9d3228 -
Branch / Tag:
refs/tags/v0.1.1 - Owner: https://github.com/yairchu
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@25a4c145d0479d3df6454550b5a15c24be9d3228 -
Trigger Event:
push
-
Statement type:
File details
Details for the file moops-0.1.1-py3-none-any.whl.
File metadata
- Download URL: moops-0.1.1-py3-none-any.whl
- Upload date:
- Size: 14.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
09c93f8a45638c0b70d1ab3f31261bc5eeb1bbdcff40674fbf6b95b56302debf
|
|
| MD5 |
9d170fcfe9d212247a71600c06b0c6b4
|
|
| BLAKE2b-256 |
939d0b4f0cb5c87e00b77646cb1bc03e2ee4369c7a90c05634df396e992e1029
|
Provenance
The following attestation bundles were made for moops-0.1.1-py3-none-any.whl:
Publisher:
publish.yml on yairchu/moops
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
moops-0.1.1-py3-none-any.whl -
Subject digest:
09c93f8a45638c0b70d1ab3f31261bc5eeb1bbdcff40674fbf6b95b56302debf - Sigstore transparency entry: 1484803988
- Sigstore integration time:
-
Permalink:
yairchu/moops@25a4c145d0479d3df6454550b5a15c24be9d3228 -
Branch / Tag:
refs/tags/v0.1.1 - Owner: https://github.com/yairchu
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@25a4c145d0479d3df6454550b5a15c24be9d3228 -
Trigger Event:
push
-
Statement type: