Jupyter Kernels
Installing Jupyter, and registering, listing, and removing kernels — with the current best kernel for each major language
Jupyter separates the frontend (JupyterLab, Notebook, VS Code, Positron, jupyter console)
from the kernel — the process that actually executes code. Any language with a kernel
implementing the Jupyter messaging protocol
works in any frontend. Kernels are registered via small JSON files called
kernelspecs,
which is what all the commands below manipulate.
Install Jupyter
JupyterLab is the current flagship frontend; the classic Notebook (v7+) is rebuilt on the same components. Neither install below requires you to manage a Python yourself.
On macOS (and Linuxbrew), the Homebrew formula ships JupyterLab with its own bundled, isolated Python:
brew install jupyterlabCross-platform, uv installs it as an isolated tool (downloading a managed Python if none exists):
uv tool install jupyterlab # adds the `jupyter` and `jupyter-lab` commands
# or run without installing:
uvx jupyter labpip install -U jupyterlab notebook or conda install -c conda-forge jupyterlab work as
well. Launch with jupyter lab (or jupyter notebook).
Either way, JupyterLab lives in its own isolated environment. It does not need to share an environment with your project code — that's what per-project kernels are for (next sections).
List available kernels
jupyter kernelspec list # names + kernelspec directories
jupyter kernelspec list --json # full detail, machine-readable
jupyter --paths # all directories Jupyter searchesUser-level kernelspecs live in ~/Library/Jupyter/kernels (macOS),
~/.local/share/jupyter/kernels (Linux), or %APPDATA%\jupyter\kernels (Windows). Each
kernel is a directory containing a kernel.json with the launch command and display name —
you can edit it directly to rename a kernel or add environment variables.
Remove a kernel
jupyter kernelspec remove my-project # prompts for confirmation
jupyter kernelspec remove -f my-project # no promptThis only deletes the kernelspec — the underlying environment or binary is untouched. Kernels pointing at deleted environments linger in the picker until removed this way.
Python: ipykernel, one kernel per environment
ipykernel is the reference Python kernel. The standard workflow is one kernel per project environment, so notebooks run against exactly the dependencies of that project:
# In a uv project
uv add --dev ipykernel
uv run python -m ipykernel install --user \
--name my-project --display-name "Python (my-project)"
# In any activated venv/conda env
python -m ipykernel install --user --name my-project --display-name "Python (my-project)"--name is the kernelspec identifier (what kernelspec list and remove use);
--display-name is what the notebook picker shows. Re-running the command with the same
name overwrites the spec, so it's safe to repeat after moving an environment.
Alternatively, skip registration entirely and launch Jupyter inside the project
environment — the default python3 kernel then is the project's interpreter:
uv run --with jupyter jupyter labR: Ark or IRkernel
Ark is Posit's modern R kernel — a native frontend to
R written in Rust, the same kernel that powers Positron, with an integrated debugger.
Download a release binary, put it on your
PATH, then:
ark --installIRkernel is the long-standing CRAN kernel, written in R itself — still the simplest install if you're already in R:
install.packages("IRkernel")
IRkernel::installspec() # name = "ir", display name "R"
# Multiple R versions side by side:
IRkernel::installspec(name = "ir45", displayname = "R 4.5")Julia: IJulia
IJulia registers a kernel automatically when the package is installed:
using Pkg; Pkg.add("IJulia")
# Extra kernel variants, e.g. multithreaded or pinned to a project
using IJulia
installkernel("Julia (8 threads)", env = Dict("JULIA_NUM_THREADS" => "8"))
installkernel("Julia", "--project=@.")JavaScript / TypeScript: Deno
The Deno runtime ships a built-in kernel —
the modern choice for both JS and TS, replacing the older ijavascript/tslab kernels. It
supports TypeScript natively, npm and JSR imports directly in cells, and rich output via
Deno.jupyter helpers:
deno jupyter --installimport * as Plot from "npm:@observablehq/plot"; // npm imports just work
Deno.jupyter.md`# Rendered **markdown** output`;Deno kernel cells currently run with --allow-all — no Deno sandbox permissions apply
inside notebooks.
Rust: evcxr
evcxr_jupyter is the canonical Rust kernel:
cargo install --locked evcxr_jupyter
evcxr_jupyter --installAdd crates inside a notebook with the :dep directive:
:dep rand = "0.9"
rand::random::<f64>()Kernels at a glance
| Language | Kernel | Install | Kernelspec name |
|---|---|---|---|
| Python | ipykernel | python -m ipykernel install --user --name <name> | <name> |
| R | Ark | ark --install | ark |
| R | IRkernel | IRkernel::installspec() | ir |
| Julia | IJulia | Pkg.add("IJulia") | julia-1.x |
| JS / TS | Deno | deno jupyter --install | deno |
| Rust | evcxr | evcxr_jupyter --install | rust |
Any kernel also works outside notebooks in a terminal REPL:
jupyter console --kernel deno