Contributor Guide

This page is intended for people interested in building new or modified functionality for Jupyter AI.

If you would like to build applications that enhance Jupyter AI, please see the developer’s guide.

Development Setup

Overview

In v3, Jupyter AI is no longer a monorepo. The various components of Jupyter AI now live as separate repos under the jupyter-ai-contrib GitHub org. jupyter-ai is now a metapackage that distributes a stable working set of these components with some default configuration, and is mostly empty on its own.

The following repositories are stable, i.e., this means the repos are, or are quickly becoming, stable and ready for production use.

These repositories are experimental and under active development:

New experimental submodules are added frequently (the list above is not exhaustive), and the current set may be accessed at: https://github.com/orgs/jupyter-ai-contrib/repositories.

Using the devrepo

jupyter-ai-devrepo is a “developer repo” intended for Jupyter AI contributors. This facilitates installing Jupyter AI along with all its submodules with a small number of steps. By cloning the repo and following the steps below, you can have an editable developer installation of all Jupyter AI subpackages.

0. Clone the repo

git clone --recurse-submodules https://github.com/jupyter-ai-contrib/jupyter-ai-devrepo.git

cd jupyter-ai-devrepo/

1. Install root dependencies

This monorepo requires git, uv, and just. Use homebrew to install these if you do not have them installed.

No dedicated Python environment is required because uv automatically manages a local venv.

If you use conda/mamba/micromamba, you can run the following commands to install these dependencies into the base environment:

{conda,mamba,micromamba} activate base
{conda,mamba,micromamba} install uv just
# make sure to activate the `base` environment before working in this repo

Otherwise, you can use your OS’s package manager. For example, on macOS:

brew install uv just

2. Pull in latest changes

This command switches to the main branch on every submodule and pulls from it.

just pull-all

If you do not have your RSA key set up to access GitHub from the CLI, you will be prompted to authenticate yourself on GitHub for each of the subpackages as they get cloned into the jupyter-ai-devrepo folder.

While this is not usually necessary, you can also run here:

just sync --refresh

Depending on your environment, sometimes it will clear errors and

  • Refresh UV’s cache to check for updated package versions

  • Synchronize your local Python environment with the updated lock file(s)

  • Ensure all dependencies from the newly pulled submodules are installed

  • Resolve any dependency conflicts.

3. Install all packages

This command automatically installs each of the packages in editable mode.

just install-all

4. Start JupyterLab

Start JupyterLab by running:

just start

This command will always run uv run jupyter lab from the root of this devrepo, even if your current directory is inside of a submodule.

This is analogous to running

uv run jupyter lab --config={{justfile_directory()}}/jupyter_server_config.py

If you want the root directory to be different from the justfile directory, you can also run an extended command:

uv run jupyter lab --config=jupyter_server_config.py --notebook-dir=<start_directory>

Devrepo commands

Global commands (can be run from anywhere in the devrepo):

  • just start: start JupyterLab

    • Ctrl + Z + kill -9 %1 stops JupyterLab in case Ctrl + C does not work

  • just sync: synchronize the Python environment with uv.lock

  • just pull-all: switch to main in all submodules and pull in all upstream changes

  • just build-all: build all frontend assets in every submodule

  • just enable-extensions: enable all server and lab extensions

  • just install-all: perform an editable, developer installation of all packages (includes build-all and enable-extensions)

  • just uninstall-all: uninstall everything (removes .venv and uv.lock)

  • just reinstall-all: re-install everything (useful for fixing a broken venv)

  • just clean: remove generated files (*.chat, *.qasm, *.ipynb)

Submodule-only commands (must be run from within a submodule directory):

  • just jlpm: install JavaScript dependencies for the current submodule

  • just build: build frontend assets for the current submodule

  • just lint: run linting for the current submodule

  • just pytest: run pytest for the current submodule

  • just reinstall: reinstall the current submodule package

Building documentation

The just install script should automatically install the documentation dependencies. You will need to install pandoc as well. You can install pandoc from the conda-forge channel:

conda install -c conda-forge pandoc

Otherwise have a look at pandoc’s installation instructions.

To build the documentation locally, run

cd jupyter-ai/docs/
make html

and open file://<JUPYTER-AI-ABSOLUTE-PATH>/docs/build/html/index.html, where <JUPYTER-AI-ABSOLUTE-PATH> is the absolute path of the Jupyter AI monorepo on your local filesystem. It is helpful to bookmark this path in your browser of choice to easily view your local documentation build.

After making any changes, make sure to rebuild the documentation locally via make html, and then refresh your browser to verify the changes visually.

Testing

Unit and integration tests

Jupyter AI packages all use pytest for unit and integration tests. Within a submodule, you can run

just pytest

to run the unit tests for a submodule.

E2E tests

Jupyter AI packages use Playwright for E2E tests (user-level tests). Galata is used to test JupyterLab extensions.

Install test dependencies (needed only once):

source .venv/bin/activate
cd <submodule>/ui-tests/
jlpm install
jlpm playwright install

Tests involve snapshot comparisons against reference snapshots generated by the Github CI. If you are using an OS other than Linux, you will need to generate local snapshots before running the tests locally for the first time. To do this, execute the command:

source .venv/bin/activate
cd <submodule>/ui-tests/
jlpm test:update

To execute tests, run:

source .venv/bin/activate
cd <submodule>/ui-tests/
jlpm test

Design principles

Maintainers of Jupyter AI have adopted principles that contributors should also follow. These principles, which build on top of the Zen of Python, are intended to earn users’ trust by keeping their data under their control. The following list is non-exhaustive; maintainers have discretion to interpret and revise these principles.

  1. Jupyter AI is vendor-agnostic. Jupyter AI does not discriminate between agent or model providers. A feature in Jupyter AI may be specific to one agent or model provider if it cannot be used with other models or providers.

  2. Jupyter AI only responds to an explicit prompt; it does not watch files and it does not send prompts automatically. Any change that watches user files must be opt-in only. One form of opt-in is users building agentic personas that undertake non-deterministic actions, including sending prompts to other personas or agents, managing the file system, etc.

  3. Jupyter AI is transparent with its chat prompts. The chat interface and magic commands use system messages and prompt templates that are open source, so that users know what gets sent to language models.

  4. Jupyter AI is traceable; users know when it has been used to generate content. When Jupyter AI generates a notebook, the notebook says that it was generated by Jupyter AI. When a user runs a Jupyter AI magic command in a notebook, output cells say, in their metadata, that they were generated by Jupyter AI.

  5. Jupyter AI uses a human-centered design. The chat interface should look and feel like chat applications that are generally available. The magic commands should look and work like other IPython magic commands. Settings screens should be used minimally, and wherever they are used, they should be readable and understandable, even for users not fluent in the user interface language.

Issues and pull requests that violate the above principles may be declined. If you are unsure about whether your idea is a good fit for Jupyter AI, please open an issue so that our maintainers can discuss it with you.