Under the hood

The database replaces the filesystem

Most scientific tooling lives on a filesystem: an install directory, an environment of packages, a folder of scripts whose exact versions nobody quite remembers. Scellis removes that layer. There is no install directory — every block, op, kernel, model, workflow, and viewer is a catalog entity, delivered from a database at runtime and cached on your machine. This article is about that spine, and why one delivery path, hash identity, and a strict split between truth and delivery make the work durable and shareable. The engine reads it; nothing else does.

One source, one path#

At runtime, every catalog entity is fetched exclusively from the database — the local database in your browser, the cloud database on the platform. The compiled app bundles no catalog: no static JSON, no baked-in block list, no file fallback quietly aging in the app bundle. If you can use it, it came through the database. The strictness is the point: two sources of truth always drift, and “which copy am I actually running?” is a question scientific work cannot afford. One path also means every entity — built-in or user-authored — passes through the same visibility, trust, and sync machinery on its way to you, which is why freshly published content can hot-plug into a running session with no app update.

Four conceptual layers#

Underneath, the spine is four layers, each with a different mutability rule. Write-once Objects are large immutable bytes stored under a content hash. Mutable References are the human-facing names — “the current version of this workflow” — that point at objects. Append-only Events are the sync log: nothing is ever rewritten, only appended. And Derived views — search indexes, catalog listings — are rebuildable projections that can always be thrown away and recomputed. Knowing which layer a thing lives in tells you exactly what can change about it and what never can.

Identity is a hash#

The object layer is content-addressed. Large immutable bytes — weights, datasets, compiled implementations — are stored under the SHA-256 hash of their content, and bytes at a hash never change. A cached blob that fails verification is not treated as stale; it is treated as corruption and refetched. Around those objects, published entities are immutable by version: a semantic change is a new version, and versions coexist.

json
{
  "block_id": "user/normalize",
  "version": 2,
  "spec_hash": "3f61c0a94b7e58d2…"     // the machine's name for the bytes
}

Two names for one entity#

A catalog row names an entity twice: once for humans (id plus version) and once for machines (the hash of its content). The name is for finding; the hash is what the machine trusts. Together they make a hard promise: nothing you built on can be rewritten underneath you. When someone improves a block you depend on, that ships as a new version — the one you pinned still resolves to exactly the bytes it always did. This is the same hash identity that makes a run reproducible.

Git is truth; the database is delivery#

For the built-in catalog, the source of truth is not the database at all — it is a git repository of specs. A delivery pipeline reads those specs, compiles implementations into content-addressed blobs, and writes rows and objects into the database, idempotently: run it twice and you get the same state. For built-in content, the database is pure delivery — never a second author. That split keeps recovery boring — the built-in catalog can always be reconstituted from git, exactly — and it keeps the platform honest about equality: from the database onward, built-in content travels the same road as anything a user publishes. One catalog, one path, no privileged side door for the maintainers' own content.

the specsin git · the truthpublishsafe to re-runthe databasein the cloudthe databaseon your devicethe database IS the deliverywhat the engine reads
Fig. 1 — One road, no side doors. The truth lives in the specs; publishing writes it into the database; and the database — in the cloud, mirrored on your device — is what delivers it to the engine. Built-in content and yours take the same road.

On demand, never wholesale#

The catalog is designed to grow past a million user-authored entities, so “fetch everything” cannot be the model. What lives on your machine is partitioned deliberately into two tiers:

  • Guaranteed-local: the engine plus everything you have used, installed, or pinned — including the full transitive closure of every saved workflow and model. Hash-verified, durable, and runnable network-unplugged forever.
  • Discovery: the rest of the global catalog. Browsing and searching it — in the Marketplace — requires the network; individual entities are fetched on demand, the moment you need them.
on your device · works offlinethe engine+ everything you have usedyour/cleanup@3 ✓core/matmul@2 ✓everything they depend on ✓everything else · one search awaylee/umap@2core/pca@1packs/genomics@1 · paidkim/qc-report@5opening something pulls it here
Fig. 2 — What you have works offline; what the world has published is one search away. Opening something pulls it — and everything it needs — onto your device, so your footprint follows your work, not the size of the catalog.

Use is what promotes content: opening, running, forking, or installing something pulls it — and everything it depends on — into your local working set. Before a workflow saves, its full closure is guaranteed local, which is why a saved workflow always runs offline. Demand-fetching is confined to browsing and authoring time; it never sits on the run path. Your local footprint is bounded by your own activity, not by how large the global catalog grows.

Offline-first writes that sync in the background#

Reads come from the local database; so do writes. Every mutation applies optimistically to your local store first and syncs to the platform in the background through a sync queue — you never wait on a round-trip to keep working. When two people change the same shared entity, the conflict surfaces explicitly, offering accept-server, rebase, or merge. Silent last-write-wins on shared content is treated as an anti-pattern, not a convenience: the platform would rather ask than quietly discard someone's edit.

Bootstrap once, then offline indefinitely#

Your first visit is the one moment the network is required: a bootstrap of a few seconds populates the local database with a minimal working set — the engine, your own and installed content, and the closure of anything you open. From then on, everything you have runs fully offline, indefinitely. This is not a degraded offline mode; it is the same engine reading the same local database it always reads. Only discovery of new global content needs a connection, and offline search says so plainly, degrading to a clearly labelled index of what you already have.

Note

Failure is loud by design. Opening a workflow offline whose dependencies you never fetched fails with the exact list of missing content — never by silently dropping a node or substituting a “nearest” version.

You collaborate on a draft; you cite a commit#

Sharing rides directly on hash identity. A shared link names the content-addressed artifacts of a commit — the program, the weights, the dataset — so wherever it is opened, it resolves the identical bytes, hash-verified on arrival. That is what reproducible by URL means here: the artifacts themselves are identical everywhere. The last piece is deliberate — a live collaborative session is never hashed. While you and others edit together, the draft is a moving thing, and pretending otherwise would poison every link that pointed at it. When the work is worth citing you commit it, and that commit is the immutable artifact a link resolves. You collaborate on a draft; you cite a commit — a citation in Scellis never points at a moving target.