Skip to content

Kernels

jOtter doesn’t run code itself. Like JupyterLab, it starts a Jupyter kernel, a separate process that executes cells and sends back their output. Any kernel that speaks the Jupyter protocol works: Python’s ipykernel, IJulia, IRkernel, and others.

When a notebook opens, jOtter decides on a kernel name and then looks for a kernelspec with that name.

The name is, in order: the --kernel option, then the notebook’s own kernelspec (metadata.kernelspec.name, written by whatever tool saved it last), then python3.

For that name, jOtter searches these places and uses the first match:

  1. The activated environment: $VIRTUAL_ENV (venv, uv, poetry, pdm) or $CONDA_PREFIX (conda, mamba, pixi).
  2. A .venv or venv directory next to the notebook, even if it isn’t activated.
  3. The global Jupyter paths: $JUPYTER_PATH, the standard system and user directories, and whatever jupyter --paths reports if Jupyter is installed.

If the requested name isn’t found anywhere, jOtter repeats the search for python3 before giving up.

Kernels from an environment (steps 1 and 2) run with that environment’s own Python, so import sees exactly the packages installed there. The kernel’s working directory is the notebook’s directory, so relative paths in your code behave as they do in JupyterLab.

Install ipykernel into the environment your notebook should use:

Terminal window
uv venv # creates .venv next to your notebook
uv pip install ipykernel numpy matplotlib
jotter notebook.ipynb # finds .venv on its own

Projects managed with uv add work the same way: uv add --dev ipykernel.

Named kernels registered with Jupyter are found through the global paths. Register one from any environment and pick it with --kernel:

Terminal window
python -m ipykernel install --user --name phys --display-name "Python (phys)"
jotter --kernel phys notebook.ipynb

jupyter kernelspec list shows every kernel Jupyter knows about. If the notebook has no kernelspec yet (a new notebook, or one generated by a script), jOtter records the kernel it started, and the next save writes it into the metadata, so next time --kernel isn’t needed. An existing kernelspec is never overwritten; --kernel only applies to the current session.

Install the language’s Jupyter kernel and register it, then open the notebook as usual. Syntax highlighting and the file type used by the external editor follow the notebook’s language (metadata.language_info, or the kernelspec’s language), not just Python.

Language Kernel Register with
Julia IJulia using Pkg; Pkg.add("IJulia")
R IRkernel IRkernel::installspec()
Rust evcxr evcxr_jupyter --install

The kernel starts in the background as soon as the notebook opens; the status line shows starting kernel '…'. You can run cells right away: they wait in a queue until the kernel is ready.

Press R to restart the kernel. jOtter asks first: R again restarts, a restarts and then runs all cells. If a kernel can’t be found or dies, the status line says why and R starts a new one. Troubleshooting covers the usual causes.