Extension points overview#
This page is a map of safe ways to extend Cellucid Python and a decision guide for when changes require coordination with the web app.
If you are planning a change, start here before coding:
Cellucid-ready AnnData changes → prepare() writer architecture
hooks/protocol changes → Extension point: add a new hook event or command
The first decision: “Python-only” vs “contract change”#
Python-only changes (low coordination)#
Examples:
add a helper function (e.g., vector field utilities)
add a CLI subcommand that doesn’t change the Cellucid-ready AnnData contract
add docs pages or notebooks
improve error messages, validation, performance inside existing contracts
Usually touches:
src/cellucid/*.pydocs/tests/
Contract changes (requires coordination)#
Examples:
new elements or
uns['cellucid']keys in the Cellucid-ready AnnDatanew launch defaults
new hook event types or new frontend command types
changes to session file chunk codecs
These must be coordinated with:
the web app loader and UI behavior (
cellucid/repo)cellucid-r, which writes the same Cellucid-ready AnnData and speaks the same viewer channel (the shared
viewer-protocol.json)
Start with:
Extension point catalog#
A) Add a new public Python API function/class#
Checklist:
implement in
src/cellucid/<module>.pyexport via
src/cellucid/__init__.py(__getattr__+__all__)add docs (user guide or API reference)
add tests for edge cases
Watch out for:
importing heavy dependencies at module import time (CLI startup)
B) Add a new CLI command#
Checklist:
add a subparser in
src/cellucid/cli.pykeep parser lightweight (no heavy imports)
import heavy deps inside command handler
document in CLI architecture and commands
C) Add something to the Cellucid-ready AnnData (a new element or uns['cellucid'] key)#
This is the most coordination-heavy extension point.
Checklist:
update together:
prepare_data/(the Python writer) and cellucid-r’scellucid_prepare()the web app’s AnnData reader (
cellucid/assets/js/data/anndata/, andanndata-cellucid-metadata.js/requireAnnDataLaunchDefaultsfor a key)_launch_defaults.pyfor a launch default, so the server accepts it too
D) Add a new hook event or command#
Checklist:
update:
frontend event/command handlers (web app)
Python viewer helpers (
jupyter/) if adding a new public methoddocs and examples
E) Extend session file parsing#
Session files are untrusted input and must remain robust.
Checklist:
define one exact schema for every new chunk or codec
keep hard caps on decompression and allocations
update tests in
tests/test_sessions.py(add synthetic bundles; the golden historytests/fixtures/history_golden/is regenerated by the web repository’sscripts/generate-history-golden.mjs, never by hand)
Contract-change strategy#
When adding new fields/files:
update every writer, server adapter, loader, validator, test, and format document in the same change;
reject unknown keys and unsupported schemas with a clear error;
do not retain alternate schema readers or redirect paths.
Troubleshooting#
Symptom: “I added a key to uns['cellucid'] and the viewer refuses the file”#
Cause:
the web app refuses any key it does not know, so a misspelt default never passes unnoticed.
Fix:
add the key to the web app’s
anndata-cellucid-metadata.js(orrequireAnnDataLaunchDefaults) in the same change, and to cellucid-r.
Symptom: “I added an element but the viewer never reads it”#
Cause:
the web app’s AnnData reader is not hooked up to it.
Fix:
update the web app’s reader in the same change.