Customize A Runtime#
Use this guide when you want a conda-ship-built runtime with your own package set, runtime name, delegate executable, install location, channels, or documentation URL.
conda-ship is generic. It does not publish a first-party runtime, and it
does not reserve a default runtime name. conda-express is one downstream
distribution that uses conda-ship to publish cx and cxz; use a runtime name
owned by your distribution.
The manifest examples below describe the build input conda-ship consumes.
Packaged CLI builds find the runtime template installed next to cs
automatically. Source checkouts need either a packaged install that includes
cs-template or an explicit --template path.
Choose A Runtime Name#
The runtime name becomes part of the user interface:
the executable users run
the default install path,
~/.conda/INSTALL_NAMEwith theconda-homeinstall schemethe metadata file,
.RUNTIME.jsonthe bundle environment variable,
RUNTIME_BUNDLEthe offline environment variable,
RUNTIME_OFFLINE
For environment variables, non-alphanumeric characters are converted to
underscores. A runtime named demo uses DEMO_BUNDLE and
DEMO_OFFLINE.
Use a product-specific name:
[tool.conda-ship]
runtime = "demo"
delegate = "conda"
layout = "online"
Avoid publishing downstream builds as cx or cxz. In the conda ecosystem,
those names identify the conda-express artifacts maintained in the
jezdez/conda-express repository.
Choose An Install Location#
By default, a runtime uses the conda-home install scheme and installs below
~/.conda/RUNTIME, where RUNTIME is the runtime name. A downstream
distribution can choose a different install name without stamping an
operating-system-specific path:
[tool.conda-ship]
runtime = "cx"
delegate = "conda"
layout = "online"
install-scheme = "conda-home"
install-name = "express"
cs build
That builds a runtime named cx whose default install path resolves to
~/.conda/express on the user’s machine. Users can still override the resolved
path locally with the global runtime option, for example
RUNTIME --path PATH bootstrap or RUNTIME --path PATH status.
Choose a product-specific install name. conda-ship does not reserve names
under ~/.conda; it writes runtime metadata into bootstrapped prefixes and
uses that metadata to avoid overwriting prefixes owned by other tools. The
metadata includes the runtime display name, install name, metadata filename,
and metadata schema version, so a runtime refuses to use or remove a prefix
that belongs to a different stamped runtime.
For a platformdirs-style location, use install-scheme = "user-data". That stores the
runtime below the platform user data directory, such as
${XDG_DATA_HOME:-~/.local/share}/conda/INSTALL_NAME on Linux,
~/Library/Application Support/conda/INSTALL_NAME on macOS, and
%LOCALAPPDATA%\\conda\\INSTALL_NAME on Windows.
If a downstream package manager owns the runtime binary, set
install-method in the manifest or pass it from the release job. The generated
runtime uses that value only after uninstall, when it tells users how to
remove the runtime binary itself:
[tool.conda-ship]
runtime = "demo"
delegate = "conda"
install-method = "homebrew"
For matrix builds that produce the same runtime for different distribution
channels, use cs build --install-method METHOD or the GitHub Action
install-method input.
Choose Runtime Packages#
A conda-ship runtime must include:
pythoncondaconda-rattler-solverconda-spawn
Additional plugins are a distribution decision. A downstream project records its own plugin set in its manifest and committed lockfile; conda-ship does not choose one for every runtime.
Configure Local Build Input#
Keep package and channel intent in the manifest format owned by your workspace
tool. Keep conda-ship-specific build policy in [tool.conda-ship].
Use conda.toml when the project uses
conda-workspaces as its primary
manifest:
[workspace]
name = "demo"
channels = ["conda-forge"]
platforms = ["linux-64", "osx-arm64", "win-64"]
[feature.ship.dependencies]
python = ">=3.12"
conda = ">=25.1"
conda-rattler-solver = "*"
conda-spawn = ">=0.1.0"
numpy = "*"
pandas = "*"
[environments]
ship = { features = ["ship"], no-default-feature = true }
[tool.conda-ship]
runtime = "demo"
runtime-version = "0.1.0"
delegate = "conda"
layout = "online"
source-environment = "ship"
exclude = ["conda-libmamba-solver"]
docs-url = "https://example.com/demo/"
install-scheme = "conda-home"
install-name = "demo"
install-method = "homebrew"
Refresh the source lockfile:
conda workspace lock
Use this form when a Python project keeps conda-workspaces config in
pyproject.toml. conda-workspaces tables live under [tool.conda], while
[tool.conda-ship] remains a sibling tool table:
[tool.conda.workspace]
name = "demo"
channels = ["conda-forge"]
platforms = ["linux-64", "osx-arm64", "win-64"]
[tool.conda.feature.ship.dependencies]
python = ">=3.12"
conda = ">=25.1"
conda-rattler-solver = "*"
conda-spawn = ">=0.1.0"
[tool.conda.environments]
ship = { features = ["ship"], no-default-feature = true }
[tool.conda-ship]
runtime = "demo"
runtime-version = "0.1.0"
delegate = "conda"
layout = "online"
source-environment = "ship"
exclude = ["conda-libmamba-solver"]
Refresh the source lockfile:
conda workspace lock
This writes conda.lock.
For Pixi-compatible projects, keep the source environment package intent in
Pixi’s own sections. If Pixi config lives in pyproject.toml, the package and
channel sections live under [tool.pixi], while [tool.conda-ship] stays at
the Python project tool level:
[tool.pixi.workspace]
name = "demo"
channels = ["conda-forge"]
platforms = ["linux-64", "osx-arm64", "win-64"]
[tool.pixi.feature.ship.dependencies]
python = ">=3.12,<3.15"
conda = ">=25.1"
conda-rattler-solver = "*"
conda-spawn = ">=0.1.0"
numpy = "*"
pandas = "*"
[tool.pixi.environments]
ship = { features = ["ship"], no-default-feature = true }
[tool.conda-ship]
runtime = "demo"
runtime-version = "0.1.0"
delegate = "conda"
layout = "online"
source-environment = "ship"
exclude = ["conda-libmamba-solver"]
Refresh the source lockfile:
pixi lock
This writes pixi.lock.
conda-ship consumes the solved ship environment during cs build; it does
not replace the workspace solver.
Build the runtime:
cs build
The staged runtime and metadata files are written to dist/.
Build In GitHub Actions#
For CI builds, commit the manifest and lockfile, then point the composite action at that project root:
- uses: actions/checkout@v4
- uses: jezdez/conda-ship@0.2.1
id: cs
with:
root: .
The action does not run conda workspace lock, pixi lock, or any other solve
step. That keeps release artifacts tied to reviewed project files.
Build An Embedded Variant#
Use the embedded layout when you want a larger single binary that carries the
package archives inside itself:
cs build --layout embedded
The embedded runtime uses the z suffix, so the staged binary is
dist/demoz on Unix and dist/demoz.exe on Windows.
The embedded runtime detects its built-in bundle automatically during
bootstrap; users do not need to pass --bundle or --offline.