nb_conda_kernels, running Jupyter kernels from other conda environments
Package for managing conda environment-based kernels inside of Jupyter
At a glance
- What is it?
- nb_conda_kernels is a Jupyter extension that discovers kernel specifications inside other conda environments and rewrites them so a single notebook server can launch them, activating the right environment first. It is a small package that solves a real problem, and it only works out of the box with Notebook and JupyterLab.
- Who is it for?
- nb_conda_kernels suits a conda-based data team that keeps several environments for different Python or R versions and wants to pick them from a single notebook server instead of restarting Jupyter per environment. It does not suit a pip-only project, and it does not suit a pipeline that needs the same external kernels to work under nbconvert, voila or papermill without the extra kernelspec_path configuration the documentation describes as a workaround.
- Can I use it commercially?
- Yes. BSD-3-Clause is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 12 days ago.
- What is it written in?
- Mainly Python, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.
Editorial analysis
One notebook server, many conda environments
The problem is familiar to anyone who has worked with conda and Jupyter at the same time. You have a base environment with Jupyter installed, and separately an environment for an old client that pins Python 3.7, another for a data stack, and a third for R. The usual workaround is to install Jupyter into each environment and run a separate notebook server per project, which means several servers, several URLs, and a port to remember.
nb_conda_kernels removes that duplication. The project describes it as an extension that enables a Jupyter Notebook or JupyterLab application in one conda environment to access kernels for Python, R and other languages found in other environments. When a kernel from an external environment is selected, the kernel's conda environment is automatically activated before the kernel is launched. The result is that you can use different versions of Python, R and other languages from a single Jupyter installation.
The audience is a data scientist or analyst on a conda-based workflow, and more broadly a team that standardises on conda for environment management and would rather not have Jupyter itself be a per-project dependency. It is also relevant to anyone who has been bitten by the mismatch between the environment the notebook server runs in and the environment the code actually needs.
It is worth being clear about the scope. This is not a Jupyter installation, not a package manager, and not a kernel itself. It is the bridge between conda's environment layout and Jupyter's kernel spec model, and it is deliberately small.
A custom KernelSpecManager rewrites each spec in place
The mechanism is described in a few sentences in the project documentation, and understanding it explains most of the package's behaviour, including its limits.
The package works by defining a custom `KernelSpecManager` that scans the current set of conda environments for kernel specifications. It dynamically modifies each `KernelSpec` so that it can be properly run from the notebook environment. When you create a new notebook, these modified kernels are made available in the selection list.
So the flow is: enumerate conda environments, find the kernel specs inside them, rewrite the spec so that launching it activates the correct environment and then starts the interpreter from that environment rather than the server's own. The rewriting is what makes the activation happen automatically, and it is why the kernels appear in the picker for a new notebook.
The key design decision is that this happens at runtime, in the notebook server process, rather than by writing kernel specs to disk during installation. That is the difference between this package and the manual approach of installing kernels into a shared directory, and it is the reason the environment list stays in sync with what conda actually has installed rather than with what was true at setup time.
It also explains the package's dependence on conda itself. The scanner walks conda environments, so this only works where conda is the environment manager. In a pip-only or a venv-only workflow there is nothing for the scanner to walk.
Installing means installing a kernel in every environment you want
The installation instructions are conda commands, and the project states that the package is designed to be managed solely using conda. It should be installed in the environment from which you run Jupyter Notebook or JupyterLab, which might be your base conda environment but need not be. If the environment `notebook_env` contains the notebook package, the install goes there.
conda install -n notebook_env nb_conda_kernelsThe second half of the setup is the part people miss. Any other environment you want to reach from your notebooks must have an appropriate kernel package installed. To access a Python environment it must have the `ipykernel` package.
conda install -n python_env ipykernelFor R, the package named in the documentation is `r-irkernel`.
conda install -n r_env r-irkernelFor other languages, the corresponding kernels from the Jupyter kernels list must be installed. The package is available from three channels, the project's own development label, the defaults channel and conda-forge, and the documentation puts the development label first, which tells you which one to use if you want the newest build.
This two-sided requirement is the real mental model. nb_conda_kernels is the mechanism, the kernel package in each environment is the payload, and a missing kernel package means an environment simply does not appear in the picker. Nothing warns you about it at install time.
nbconvert, voila and papermill need a documented workaround
This is the sharpest limitation in the package and the documentation is unusually direct about it. The extension works out of the box only with Jupyter notebooks and JupyterLab.
The reason is architectural. A new kernel discovery system is being developed in the Jupyter server, and the documentation states that this package will require modification to function properly in that new system. Until that happens, tools that were not designed to allow the use of custom KernelSpecs cannot see the conda environments. Jupyter Console, nbconvert and other tools are named.
The workaround is documented and takes four steps. You create a configuration file for jupyter named `jupyter_config.json` in the folder returned by `jupyter --config-dir`, and you add the kernelspec_path setting.
{
"CondaKernelSpecManager": {
"kernelspec_path": "--user"
}
}Then you run the extension's own listing command, or open the classical Notebook or JupyterLab UI.
python -m nb_conda_kernels listFinally you check that the conda environment kernels are discovered by jupyter.
jupyter kernelspec listThe documentation states that the previous command should list the same kernels as `nb_conda_kernels`. If it does, nbconvert, voila and papermill will find the conda environment kernels.
The cost of this is real, though. It installs kernel specs on disk outside the runtime mechanism, which means they can drift out of date with the actual environments, and it introduces a state that has to be regenerated when environments change. For a pipeline that runs nbconvert on a schedule, that is a maintenance item rather than a one-time setup.
Naming, filtering and the debugger flag are the knobs
The configuration surface is small, with five options, and each one solves a concrete annoyance.
`conda_only` decides whether to include only the kernels that are not visible from Jupyter normally, and it defaults to False except when `kernelspec_path` is set. `env_filter` is a regular expression matched against the environment path, defaulting to None, meaning no filter. This is the option that keeps a large list of environments manageable, and the documentation shows it can be passed on the command line as an argument to the list command, with an example regex, and set either in `jupyter_config.py` or in `jupyter_config.json`.
`kernelspec_path` is the workaround described above, and its possible values are worth reading carefully. An empty string installs for all users, `--user` installs for the current user, `--sys-prefix` installs into Python's sys.prefix, and a `PREFIX` value writes the specs into `PREFIX/share/jupyter/kernels`. The documentation warns that the prefix may not be discoverable by Jupyter and points at setting `JUPYTER_DATA_DIR` or running `jupyter --paths` to find the data directories.
`name_format` controls what the entries look like in the picker, with a default of `'{language} [conda env:{environment}]'`, and the documentation enumerates the available field names, including `{0}` for language, `{1}` and `{environment}` for the environment name, `{conda_kernel}`, `{display_name}`, `{kernel}` and `{language}`.
`enable_debugger` overrides kernelspec debugger metadata, defaulting to None, with True and False setting the flag. That option came with the 2.5.0 release, whose release note is override debugger metadata.
The naming format is worth a moment of thought rather than a copy of the default, because the default does not include the kernel folder name or the display name, and two environments running the same language will be hard to tell apart.
Development setup, testbed and the state of the release line
The repository is a conventional Python package layout with `nb_conda_kernels/` as the package directory, `tests/`, a `testbed/` directory, a `conda-recipe/` for the conda packaging, `setup.py` and `setup.cfg`, `requirements.txt`, `versioneer.py` and a Renovate configuration for dependency updates.
The setup.py shows a version derived from versioneer rather than hardcoded, which is the usual way to get version numbers from git tags. The description string, Launch Jupyter kernels for any installed conda environment, says the same thing as the README in fewer words.
The requirements file lists notebook, jupyter_client, r-irkernel, requests, flake8, psutil, pytest, pytest-cov and mock. That list tells you the test suite runs against a real notebook, exercises an R kernel, and uses psutil, presumably to inspect the running kernel process.
The documented development setup starts with installing Anaconda or Miniconda and a note that on Windows you need a Bash shell on your path. It then describes creating and activating a testbed environment, and the instructions are cut off in the documentation as it stands.
The release picture is the thing to weigh. The recorded releases are 2.5.0 in April 2024, 2.3.0 in September 2020 and 2.2.4 in August 2020. The last push to the repository was on 2026-10-11, so there has been recent work on the branch even though the last tagged release is from 2024. The version gap between 2.3.0 and 2.5.0 also means intermediate releases are not represented in the recorded list, so the published changelog is not the full history.
If you adopt this, pin the version and read the tag's own notes rather than assuming the branch tip is what you tested against. The licence is BSD-3-Clause, which is permissive, with the notice and disclaimer obligations attached to redistribution.
Editorial conclusion
nb_conda_kernels suits a conda-based data team that keeps several environments for different Python or R versions and wants to pick them from a single notebook server instead of restarting Jupyter per environment. It does not suit a pip-only project, and it does not suit a pipeline that needs the same external kernels to work under nbconvert, voila or papermill without the extra kernelspec_path configuration the documentation describes as a workaround. Verify first that every environment you want to expose actually has a kernel package installed, that is ipykernel for Python or r-irkernel for R, and that the name_format you choose produces distinguishable entries in the kernel picker before you rely on it with other people.
Frequently asked questions
How do I install nb_conda_kernels?
The project is designed to be managed solely with conda and should be installed in the environment from which you run Jupyter Notebook or JupyterLab, for example conda install -n notebook_env nb_conda_kernels. It is available on the jupycon development label, the defaults channel and conda-forge.
Why does my conda environment not appear in the Jupyter kernel list?
The environment needs its own kernel package installed, since nb_conda_kernels only finds environments that contain a kernel specification. For Python that is ipykernel, for R it is r-irkernel, and other languages need their corresponding kernels from the Jupyter kernels list.
Does nb_conda_kernels work with nbconvert, voila and papermill?
Not out of the box. The documentation states the extension works out of the box only with Jupyter notebooks and JupyterLab, and that a new kernel discovery system will require modification to the package. A documented workaround is to set kernelspec_path in jupyter_config.json and verify with python -m nb_conda_kernels list and jupyter kernelspec list.
How do I hide conda environments I do not want in the kernel picker?
Use the env_filter option, a regular expression matched against the environment path, which defaults to None. It can be set in jupyter_config.py or jupyter_config.json, or passed on the command line to the list command with the CondaKernelSpecManager.env_filter argument.
How does nb_conda_kernels find and start kernels in other environments?
It defines a custom KernelSpecManager that scans the current conda environments for kernel specifications and dynamically modifies each KernelSpec so it can be run from the notebook environment, activating the kernel's conda environment before launch. The modified kernels then appear in the selection list for a new notebook.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/anaconda-nb-conda-kernels)Was this useful?