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.
How jOtter picks a kernel
Section titled “How jOtter picks a kernel”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:
- The activated environment:
$VIRTUAL_ENV(venv, uv, poetry, pdm) or$CONDA_PREFIX(conda, mamba, pixi). - A
.venvorvenvdirectory next to the notebook, even if it isn’t activated. - The global Jupyter paths:
$JUPYTER_PATH, the standard system and user directories, and whateverjupyter --pathsreports 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.
Set up a Python kernel
Section titled “Set up a Python kernel”Install ipykernel into the environment your notebook should use:
uv venv # creates .venv next to your notebookuv pip install ipykernel numpy matplotlibjotter notebook.ipynb # finds .venv on its ownProjects managed with uv add work the same way: uv add --dev ipykernel.
python -m venv .venv.venv/bin/pip install ipykerneljotter notebook.ipynbconda create -n science python ipykernelconda activate sciencejotter notebook.ipynb # uses $CONDA_PREFIXpixi add ipykernelpixi run jotter notebook.ipynbpoetry add --group dev ipykernelpoetry run jotter notebook.ipynbNamed kernels
Section titled “Named kernels”Named kernels registered with Jupyter are found through the global paths. Register one from any environment and pick it with --kernel:
python -m ipykernel install --user --name phys --display-name "Python (phys)"jotter --kernel phys notebook.ipynbjupyter 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.
Other languages
Section titled “Other languages”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 |
Starting, restarting and failing
Section titled “Starting, restarting and failing”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.