Prior art#
The idea of running tools from conda packages without a persistent install has come up several times in the conda ecosystem.
conda-execute (2015)#
conda-execute by Phil Elson allowed running Python scripts with inline dependency declarations embedded in YAML comments. It created temporary environments from those inline specs and cached them by hash. The project has been unmaintained since 2019 and its conda-forge feedstock is archived.
conda-exec builds on this concept with two key differences: it supports
both packaged CLI tools (conda exec ruff) and scripts with inline
metadata (conda exec script.py), and it uses the now-standardized
PEP 723 TOML format instead of
YAML, with a [tool.conda] extension for conda-native dependencies.
conda issue #2379 (2016)#
conda/conda#2379 requested a
fast way to execute commands inside existing environments without the
overhead of conda activate. The discussion led to conda run, which
shipped in conda 4.6 (2018). The issue was closed in October 2025 with
conda run as the official solution.
conda-exec is complementary to conda run: while conda run executes
commands in environments that already exist, conda-exec creates ephemeral
cached environments on the fly from package specs. They address different
use cases.
conda-exec shell script on conda-forge (2019)#
A minimal shell script
by Patrick Sodré that activates an existing conda environment and uses
exec to replace the process with a given command. It was last updated
in 2020 and has effectively zero downloads. It requires a full environment
path as input and does not create environments.
conda-exec is fundamentally different: it resolves package specs, creates cached environments via the solver, discovers binaries, and manages the cache lifecycle.
Comparable tools in other ecosystems#
conda-exec fills the same role as these tools in their respective ecosystems:
PEP 723 and the [tool.conda] extension#
PEP 723 standardizes inline script
metadata in Python scripts using TOML in comment blocks. The standard
dependencies field declares PyPI packages, and requires-python
constrains the Python version.
conda-exec extends this with a [tool.conda] table for conda-native
dependencies:
# /// script
# requires-python = ">=3.12"
# dependencies = ["requests"]
#
# [tool.conda]
# channels = ["conda-forge", "bioconda"]
# dependencies = ["samtools>=1.19"]
# ///
When both PyPI and conda dependencies are declared, all packages are resolved together in a single environment solve. PyPI packages are resolved through the conda-pypi channel, which converts PyPI wheels into conda packages so the rattler solver can handle both in one pass.
Scripts with only [tool.conda].dependencies work without conda-pypi.
Scripts with only dependencies (PyPI) require conda-pypi to be installed.
Forward compatibility#
PEP 725 (draft) and
PEP 804 (draft) are working toward
a standardized way to declare non-PyPI dependencies ([external] table
and a cross-ecosystem dependency name registry). When those PEPs are
accepted, conda-exec can support both [tool.conda] and [external]
simultaneously.