Skip to main content

Git-free marimo notebook sharing via GitHub

Project description

⚓ mooring

Git-free marimo notebook sharing via GitHub.

Mooring is a single-file app (mooring.pyz / mooring.exe) that lets a team of data analysts pull, edit, and push marimo notebooks stored in a shared GitHub repo — without git installed on their machines. All sync happens over the GitHub REST API; the only requirement on an analyst's machine is Python 3.12.

Double-clicking the app opens a local browser hub: log in to GitHub with a one-time device code, see every team notebook with its sync status, pull the latest, open notebooks in the bundled marimo editor, and push your changes back — one commit per file, with conflicts detected and resolved per file (never silently overwritten).

Built with moonlit.


How it works

  • One shared team repo (e.g. your-org/notebooks) holds notebooks/ and data/ folders. Everyone pulls from and pushes to it.
  • No git anywhere. Pull walks the repo tree via the GitHub Git Data API and downloads only changed blobs; push uses the Contents API with the file's last-known SHA, so GitHub itself rejects writes that would clobber someone else's change.
  • Three-way change detection. Mooring computes git blob SHAs locally and keeps a manifest of what was last synced, so it always knows whether a file is modified locally, changed remotely, or conflicted.
  • Conflicts are explicit. Pull never overwrites local edits; push blocks conflicted files. The hub offers per-file resolution: Use remote, Keep both, or Push as copy (publishes your version under name-<your-github-login>.py).
  • Frozen package stack. Notebooks can import anything bundled into the artifact: polars, altair, plotly, openpyxl, fastexcel, requests (plus the standard library). There is no pip at runtime.

For analysts: install & use

  1. Install Python 3.12 (tick "Add python.exe to PATH").
  2. Get mooring.exe (or mooring.pyz) from your admin and put it anywhere, e.g. your Desktop.
  3. Run it (mooring.exe, or python mooring.pyz). Your browser opens the hub.
  4. Click Log in with GitHub, enter the code shown at github.com/login/device.
  5. Pull to fetch the team's notebooks, Open to edit one in marimo, New notebook to start fresh, Push to share your work.

Notebooks live in Documents\mooring\<repo>\notebooks\; data files your notebooks read go in ...\<repo>\data\ and sync the same way.

The first launch takes a minute while the app unpacks itself to a local cache; later launches are fast.

CLI (optional)

Everything the hub does is also available from a terminal:

python mooring.pyz login | logout | whoami
python mooring.pyz status
python mooring.pyz pull [--theirs | --keep-both]
python mooring.pyz push [paths...] [-m "message"]
python mooring.pyz open notebooks/sales.py
python mooring.pyz new sales-analysis
python mooring.pyz selftest

For admins: set up a team

  1. Create the shared repo, e.g. your-org/notebooks, with empty notebooks/ and data/ folders. Don't enable git-LFS (the API would deliver pointer files).

  2. Register a GitHub OAuth app (Settings → Developer settings → OAuth apps → New). Any homepage/callback URL works; then enable Device Flow on the app. Copy the client id — there is no secret to manage.

    • If the repo lives in an org with third-party-app restrictions, an org owner must approve the OAuth app.
  3. Bake the config: edit src/mooring/config_default.toml with the client id, owner, repo, and branch.

  4. Build (requires uv):

    uv sync
    uv run pytest
    uvx --python 3.13 moonlit build -e mooring.cli:main -o dist/mooring.pyz --python-version 3.12
    uvx --python 3.13 moonlit build -e mooring.cli:main -o dist/mooring.exe --windows-exe --python-version 3.12
    

    For machines with no Python at all, build a folder bundle with embedded CPython instead:

    uvx --python 3.13 moonlit build -e mooring.cli:main -o dist/mooring-bundle --bundle-python --python-version 3.12
    
  5. Distribute the artifact (file share, email, GitHub release — the .github/workflows/release.yml workflow builds and attaches artifacts on every v* tag).

Users without a baked config get a one-time setup form in the hub instead; their values are stored in %APPDATA%\mooring\config.toml.

Changing the bundled notebook packages

Edit dependencies in pyproject.toml, uv sync, rebuild, redistribute. Notebooks can only import what's frozen into the artifact.

Development

uv sync                                  # install everything
uv run pytest                            # unit tests (no network needed)
uv run ruff check src tests              # lint
uv run mooring hub                       # run the hub from source
uv run python tests/manual_editor_check.py   # editor-subprocess smoke test

Layout: src/mooring/cli.py (entry point; also sets PYTHONPATH so the marimo subprocess works from inside the packaged artifact), auth.py (device flow + keyring), github.py (REST client), gitsha.py/manifest.py/sync.py (the three-way sync engine), editor.py (marimo subprocess manager), hub/ (Starlette app + static frontend).

To integration-test sync against a real repo, set MOORING_TOKEN (a PAT works) plus MOORING_OWNER/MOORING_REPO/MOORING_CLIENT_ID and use the CLI against a scratch repository.

Constraints & notes

  • Python version is pinned. A .pyz/.exe built for 3.12 needs the user to have Python 3.12.x; moonlit shows a clear error otherwise. The --bundle-python build escapes this entirely.
  • File sizes: pushes warn at 10 MB and refuse at 45 MB per file (GitHub Contents API limit). Keep big datasets out of the repo.
  • Tokens are stored in the OS credential store (Windows Credential Manager); repo-scoped OAuth tokens grant access to all repos the user can reach — use a dedicated machine account org if that's a concern.
  • Artifact size is ~110 MB (marimo + polars + plotly + altair). First run extracts to %LOCALAPPDATA%\moonlit\; old versions' caches can be deleted freely.

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

mooring-0.1.0.tar.gz (61.9 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

mooring-0.1.0-py3-none-any.whl (29.4 kB view details)

Uploaded Python 3

File details

Details for the file mooring-0.1.0.tar.gz.

File metadata

  • Download URL: mooring-0.1.0.tar.gz
  • Upload date:
  • Size: 61.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.14 {"installer":{"name":"uv","version":"0.11.14","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":null,"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for mooring-0.1.0.tar.gz
Algorithm Hash digest
SHA256 c7a0ab8a84f2862ebea50a80df267e8a3fe2c169b15cc35012366b567ff5b491
MD5 61192dd2721dd5c93d2f685a157828d1
BLAKE2b-256 34a4d8e66fa0c2d7d247fdb0adb96e1aba4180422774ee12f4596ca90302e153

See more details on using hashes here.

File details

Details for the file mooring-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: mooring-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 29.4 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.14 {"installer":{"name":"uv","version":"0.11.14","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":null,"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for mooring-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 2f302ed728216838aebb95340bfb001ac83338e567625b9302b415aba2d30052
MD5 fafa0ce9f85f105226bf7a966f9c6582
BLAKE2b-256 a87d942a2f2d36e4d77e2c0d2c3fa8149d9eb34d7e9155b1001d546ae5e1f227

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page