Packaging: conda vs. wheel

In pixi mode a tin is a source dependency: pixi fetches the tin's repo at its registry-pinned commit and builds it into a conda package in your environment. The conda machinery underneath does real work for us:

What conda does for tins

The same machinery distributes the shelf CLI itself: a conda package on the static channel at /channel, installed with pixi global install.

One repo, more than one tin

A library whose optional half pulls in heavy dependencies can ship that half as a separate tin from the same repository, so the dependencies stay optional at install time rather than only at compile time. Put a second pixi.toml and shelf.toml in a subdirectory, with its sources beneath it — a subdirectory manifest's build context is the subdirectory, not the repo root — and depend on the root package by relative path:

# full/pixi.toml
[package]
name = "parquet-full-mojo"

[package.build.config.pkg]
path = "src/parquet_full"      # i.e. full/src/parquet_full
name = "parquet_full"

[package.host-dependencies]
parquet-mojo = { path = ".." }  # the root package, same commit

Publish it by running shelf publish from that directory. The registry records where the manifest sits, and consumers get it automatically:

pixi shelf add parquet-full-mojo
# writes: { git = "…/parquet.mojo", rev = "…", subdirectory = "full" }

Two rules make this work, and breaking either ships a tin nobody can install:

Publish every tin in the repo at the same commit. path = ".." resolves to git+<repo>?rev=<the commit the subdirectory tin was published at>. If the registry pins the root at a different commit, a consumer ends up with two source records for one package and the solve fails with encountered duplicate records for <root>-…_source.conda.

Do not list an in-repo path dependency in shelf.toml's tins. That field is for tins the registry must resolve; the root package is already reached by path = "..", and naming it as well pins it a second time — the same collision from the other side. A tin's own FFI shim is not listed either, for the same reason.

Both tins then move together, so there is no re-pinning between them. The usual rule still applies in the other direction: a path dependency that climbs past the repository root resolves in nobody's checkout and is refused at publish.

A pypi/wheel backend?

Wheels are a plausible additional distribution for pure-Mojo, Python-facing tins: PyPI hosting is universal, uv is fast, plain venvs could consume tins, and pixi speaks PyPI natively. What's missing today: a PEP 517 build backend for Mojo (the wheel-world equivalent of pixi-build-mojo), a convention for finding .mojopkgs in site-packages, and per-wheel vendoring of native shim libraries — wheels have no shared native dependency graph, so each shim must bundle its dylibs. Conda stays the primary substrate; a wheel experiment would start with a Python-interop tin like pontoneer.