Conda Environments: Never Break Your Setup Again

Every bioinformatician hits the same wall: you install a new tool and it silently breaks three old ones, or a script that ran last month fails today, or a colleague cannot reproduce your results because their software versions differ. Conda environments solve all of this. This lesson explains why dependency conflicts happen, how conda and bioconda fix them, and how a single environment.yml file makes your whole setup reproducible and shareable.

🟡 Professional layer ⏱️ ~1 hr 💻 Command line 🔁 Reproducibility

Before you start

  • You are comfortable running commands in a terminal. New to the shell? See the Foundations Bash basics lesson.
  • Helpful but not required: you have tried to install a bioinformatics tool and hit an error. That frustration is exactly what this lesson removes.
  • Any term new? The Glossary has it.

Learning objectives

By the end of this lesson you will be able to: explain why dependency conflicts break bioinformatics setups, create and activate an isolated conda environment per project, install tools from bioconda, and capture an environment.yml file so your setup is reproducible and shareable.

The problem: dependency hell

Bioinformatics tools are built on top of other software: specific versions of Python, R, C libraries, samtools, and so on. The trouble is that different tools want different, conflicting versions of the same dependency. Tool A needs Python 3.8 and an old NumPy; tool B needs Python 3.11 and a new one. Install them into the same place and one of them breaks. Worse, the breakage is often silent: the tool runs but gives subtly wrong answers.

The symptoms have a familiar shape:

  • "It worked yesterday and I changed nothing" (something updated underneath you).
  • "It works on my machine but not yours" (your versions differ from a collaborator's).
  • Installing one tool downgrades another and quietly corrupts an old project.

This is dependency hell, and it is the single biggest reason computational analyses fail to reproduce. The fix is to stop installing everything into one shared pile.

The solution: isolated environments

A conda environment is a self-contained folder with its own Python/R and its own exact set of package versions, isolated from everything else on your computer. You make one environment per project. Inside it, you install whatever versions that project needs; nothing leaks out to break other projects, and nothing else can break it. Switch projects, switch environments, and each one stays exactly as you left it.

Conda is the tool that creates these environments and installs packages into them. It is two things at once: a package manager (it fetches and installs software, resolving the web of dependencies for you) and an environment manager (it keeps those installs isolated).

Decode the jargonEnvironment

An isolated software workspace with its own interpreter and package versions. Activating an environment temporarily puts its tools first on your system path, so python or samtools means that environment's copy. Deactivate and you are back to normal. Think of it as a clean, labeled lab bench per project.

conda vs pip vs venv: what is the difference?

You will have met pip and venv in the Python track. Here is how they relate:

ToolManagesBest for
venv + pipPython packages only (from PyPI)Pure-Python projects
condaPython and R, C libraries, and command-line tools (samtools, bwa, bcftools)Bioinformatics, where most tools are not Python

This is the key reason conda dominates bioinformatics: the field's core tools (aligners, variant callers, samtools) are compiled C/C++ programs, not pip-installable Python packages. Conda can install those too, with all their system libraries, which pip cannot. (You can still use pip inside a conda environment for Python-only packages that are not on conda.)

Channels: where packages come from (bioconda)

Conda downloads packages from channels (repositories). Two matter enormously:

  • conda-forge: a huge community channel for general-purpose packages.
  • bioconda: the channel for bioinformatics software, over 10,000 tools (samtools, bwa, STAR, salmon, and almost anything else you will need), maintained by a large community. Bioconda is the reason "install this genomics tool" is usually a one-line command instead of an afternoon of compiling.

Because of how channel priority works, the recommended one-time setup orders the channels so bioconda and conda-forge resolve correctly:

# one-time channel setup (order matters)
conda config --add channels conda-forge
conda config --add channels bioconda
conda config --set channel_priority strict

Decode the jargonChannel

A repository conda installs packages from. bioconda is the bioinformatics channel; conda-forge is the broad community channel. "strict channel priority" tells conda to prefer higher-priority channels consistently, which avoids a class of subtle, hard-to-debug version conflicts.

The core workflow (the commands you will actually use)

Day to day, conda comes down to a handful of commands:

# create a new environment named "rnaseq" with specific tools + versions
conda create -n rnaseq python=3.11 samtools=1.19 star salmon

# turn it on (your prompt shows the active env name)
conda activate rnaseq

# install one more tool into the active env
conda install multiqc

# list what is installed
conda list

# turn it off when done
conda deactivate

Notice you pinned versions (samtools=1.19). That is deliberate: pinning is what makes a result reproducible months later. The two biggest habits to build are one environment per project and never install into the base environment (keep base clean so a bad install cannot break conda itself).

The reproducibility payoff: environment.yml

Here is where this connects to the rest of Track 6. You can write your entire environment to a single text file, environment.yml, and commit it to your Git repository. Anyone, including future-you on a new laptop, can recreate the exact setup from it:

# environment.yml
name: rnaseq
channels:
  - conda-forge
  - bioconda
dependencies:
  - python=3.11
  - samtools=1.19
  - star=2.7.11b
  - salmon=1.10.3
  - multiqc=1.21
# export your current environment to a file
conda env export --from-history > environment.yml

# recreate it anywhere from that file
conda env create -f environment.yml

This one file is the difference between "trust me, it works" and a result a reviewer can actually rerun. Controlling the compute environment this way is one of the recognized five pillars of computational reproducibility (Ziemann et al., 2023), alongside version control, literate programming, data sharing, and documentation. When a journal or employer asks "is this reproducible?", a committed environment.yml is a large part of the answer.

⚠️ Use --from-history, and know the platform caveat

A plain conda env export writes every low-level dependency and pins them to your operating system's specific builds, which often will not recreate on a different OS. --from-history records only the packages you actually asked for, which is far more portable. For bit-for-bit reproducibility across machines, the next step up is a container (Docker), where conda environments are commonly used as the base, see Nüst et al. (2020) on writing reproducible Dockerfiles.

Speed: mamba and the modern solver

Conda used to be slow at "solving" the dependency puzzle for big environments. Mamba is a drop-in, much faster reimplementation of the solver; you can often just replace conda with mamba in the commands above. The good news is that modern conda has adopted the same fast solver (libmamba) by default, so recent installations are already quick. (You may also hear about pixi, a newer project-focused tool built on the same ecosystem.) The concepts in this lesson are identical whichever front-end you use.

Your habits checklist

  1. One environment per project. Name it after the project.
  2. Keep base clean. Never conda install into base.
  3. Pin versions for anything that matters to your results.
  4. Commit an environment.yml (exported --from-history) to your repo, right next to your code.
  5. Set up channels once with conda-forge + bioconda + strict priority.

Check your understanding

A collaborator cannot reproduce your RNA-seq results: they get slightly different numbers. You both have the same code and raw data. What is the most likely cause and the best preventive fix?
Correct. Same code and data but different results almost always means a different compute environment, different tool or library versions. Pinning versions and sharing an environment.yml lets a collaborator rebuild the identical environment, which is exactly the "compute environment control" pillar of reproducibility.
A beginner installs every tool into the conda "base" environment with pip whenever conda is slow. Two months in, multiple projects break. Which combination of habits would best have prevented this?
Exactly. Cramming tools into base and mixing ad-hoc pip installs is the classic recipe for dependency hell: one install silently changes a dependency another project relied on. Per-project environments, a clean base, conda-first installation, and pinned versions keep each project isolated and stable.
You run conda env export > environment.yml on macOS and send it to a colleague on Linux, who finds it will not build. What is the issue and the better command?
Right. A plain export captures every transitive dependency pinned to your platform's specific builds, which often will not resolve on a different OS. --from-history records just your explicitly requested packages, making the file portable. For exact cross-platform reproducibility, wrap the environment in a container.
Why does conda dominate bioinformatics setups, whereas a pure Python project might happily use only venv and pip?
Correct. venv and pip manage Python packages from PyPI only. Conda is both a package and environment manager that can install non-Python tools and their C libraries, which is exactly what genomics pipelines need. You can still use pip inside a conda environment for Python-only packages.
During one-time setup you run the channel commands and finish with conda config --set channel_priority strict. What does strict channel priority help you avoid?
Right. Strict channel priority tells conda to resolve packages from higher-priority channels first instead of mixing builds across channels, which prevents the kind of inconsistent dependency mixes that cause silent breakage. It is part of the recommended bioconda plus conda-forge setup.

Sources & further reading

  1. Grüning B, et al. Bioconda: sustainable and comprehensive software distribution for the life sciences. Nature Methods 15, 475–476, 2018. doi:10.1038/s41592-018-0046-7
  2. Ziemann M, Poulain P, Bora A. The five pillars of computational reproducibility: bioinformatics and beyond. Briefings in Bioinformatics 24(6), bbad375, 2023. doi:10.1093/bib/bbad375
  3. Nüst D, et al. Ten simple rules for writing Dockerfiles for reproducible data science. PLOS Computational Biology 16(11): e1008316, 2020. doi:10.1371/journal.pcbi.1008316
  4. Conda documentation: Managing environments. docs.conda.io
  5. Bioconda documentation and tool index. bioconda.github.io

Last reviewed: June 2026.

Next in Track 6

Building a portfolio that gets noticed →