Local development setup#
This page walks you through setting up a development environment for cellucid-python (Python package + CLI + docs).
It is intentionally detailed so that:
first-time contributors don’t get stuck on environment issues,
computational users can reproduce bugs reliably,
and maintainers have a repeatable workflow.
Prerequisites#
Required:
Python 3.11 through 3.14
Git
Recommended:
a fresh virtual environment (
venv,conda,uv, etc.)
Optional (only if you work on notebook embedding):
JupyterLab (the environment the project tests; Notebook 7, VS Code, Colab, marimo and Databricks are expected to work, see Supported environments matrix)
Step 0 — Choose which repo(s) you’re working on#
Cellucid is split across repositories:
Python package (this page):
cellucid-python/Web app (UI/rendering):
cellucid/(see Developer Documentation (Web App Architecture))
If you are changing the Cellucid-ready AnnData contract or the hooks protocol, you will likely touch both repos.
Step 1 — Create an isolated environment#
Using venv:
python -m venv .venv
source .venv/bin/activate # Windows: .venv\\Scripts\\activate
python -m pip install --upgrade pip
If you use conda, choose Python 3.11 through 3.14 in a clean environment; the rest is the same.
Step 2 — Install in editable mode (dev + docs extras)#
From the cellucid-python/ folder:
python -m pip install -e ".[dev,docs]"
What this does:
installs runtime dependencies,
installs developer tooling (
pytest,pytest-cov,ruff,mypy,pre-commit),installs documentation tooling (Sphinx + MyST),
installs
mudatathrough thedevextra, which brings themudataextra with it: the MuData tests need it (CI installs.[dev]).
Step 3 — Quick sanity checks#
3.1 Import + version#
python -c "import cellucid; print(cellucid.__version__)"
3.2 CLI help#
cellucid --help
cellucid serve --help
If the CLI is slow or crashes, jump to: CLI architecture and commands.
3.3 Run tests and checks#
These are the commands CI runs (.github/workflows/test.yml):
python -m pytest
python -m ruff check src tests
python -m mypy src/cellucid
If tests are missing for what you changed, see: Testing and CI.
Step 4 — Build the docs locally#
From the cellucid-python/ folder:
make -C docs html
CI builds with warnings as errors, which make -C docs html does not; run the
exact CI command before you push:
sphinx-build -W --keep-going -b html docs docs/_build/html
Then open:
cellucid-python/docs/_build/html/index.html
Common variants:
make -C docs clean
make -C docs linkcheck
Doc-writing conventions live here: Docs development and style guide
Step 5 — Run a viewer locally (for manual testing)#
You can test with either:
Option A: a Cellucid-ready AnnData (fastest + most representative)#
Prepare your dataset:
from cellucid import prepare
# ... call prepare("my_dataset.h5ad", format="h5ad", ...) to write a Cellucid-ready AnnData ...
Serve it:
# A file written by cellucid.prepare() names itself: no identity flags.
cellucid serve ./my_dataset.h5ad
Option B: AnnData server (convenient during iteration)#
cellucid serve ./data.h5ad \
--dataset-name "Development dataset" \
--dataset-id development-dataset
Both modes should open the viewer in a browser automatically (unless --no-browser).
Step 6 — Notebook embedding (optional, but common)#
Notebook embedding is a widget (cellucid.Widget, jupyter/_widget.py and
jupyter/static/widget.js): it needs anywidget where the notebook server
runs, and its messages reach the kernel between cells.
Minimal test:
from cellucid import show_anndata
viewer = show_anndata(
"path/to/data.h5ad",
dataset_name="Development dataset",
dataset_id="development-dataset",
)
If the output is empty or hooks don’t work:
run
viewer.debug_connection(),follow Debugging playbook,
see notebook architecture details in Jupyter embedding architecture.
Offline / airgapped development notes#
A notebook widget needs no web generation: the browser loads the app from
web_source_url. The Python servers (browser-tab viewers, cellucid serve)
establish the configured exact web generation before binding:
they fetch and parse
cellucid-web-assets.json,download every declared object to a staging directory,
byte-verify and atomically publish the complete generation, and
serve it from the same origin as the dataset API.
Each startup requires source access. Select the destination explicitly with
--web-cache-dir or web_cache_dir= (see
Configuration, environment variables, and logging).
Troubleshooting#
Symptom: “pip install -e ".[dev,docs]" fails”#
Likely causes:
conflicting packages already installed in the environment,
old pip/setuptools,
corporate proxy restrictions.
Fix checklist:
ensure you activated the correct environment,
upgrade pip:
python -m pip install --upgrade pip,try a fresh environment.
Symptom: “Docs build fails with missing dependencies”#
Confirm you installed the docs extras:
python -m pip show sphinx myst-nb
Then rebuild:
make -C docs clean html
Symptom: server startup reports a web-generation failure#
This means the source generation could not be fetched, verified, or published.
Fix:
ensure access to the configured source,
correct the exact inventory/object error reported by startup, and
pass a writable
web_cache_dir.