JupyterLab 4.1 beta - call for testing!

JupyterLab 4.1 beta featuring a number of new features is available for testing!

To test the beta you can install it with either pip or conda:

pip install -U 'jupyterlab>=4.1.0b2'
# or with conda:
# conda install -c conda-forge/label/jupyterlab_beta -c conda-forge jupyterlab

Please report any issues on Issues · jupyterlab/jupyterlab · GitHub and thank you for testing this pre-release!

The up-to-date changelog is available here, with the highlights extracted below:

JupyterLab 4.1

JupyterLab 4.1 includes a number of new features (described below), bug fixes, and enhancements for extension developers. This release is compatible with extensions supporting JupyterLab 4.0. Extension authors are recommended to consult the Extension Migration Guide which lists deprecations and changes to the public API.

Custom CSS

Jupyterlab now supports automatic loading of custom CSS. Themes are the recommended way for customizing the JupyterLab look and feel,
while custom CSS is intended for minor personal adjustments.

To opt in, start JupyterLab with the --custom-css flag.
The location of the custom.css file is documented in the section on customizing the user interface.

Note: custom.css is also available in Jupyter Notebook; while similar selectors can be used for components shared between JupyterLab 4.1 and Jupyter Notebook 7.0, there was a different set of selectors in Notebook 6 and older versions.

Users with the custom CSS file using the selectors from legacy Notebook versions
will need to update them and note that tutorials may refer to the selectors for the old Notebook versions.

Diagrams in Markdown

Matching GitHub-Flavoured Markdown, JupyterLab 4.1 now supports Mermaid diagrams. To create a mermaid diagram use the mermaid language specifier for a code block in a markdown cell or document, for example:

flowchart LR

A[Hard] -->|Text| B(Round)
B --> C{Decision}
C -->|One| D[Result 1]
C -->|Two| E[Result 2]

which renders as:

Rendered Mermaid diagram going from left to right with modern look; the diagram contains blueish square node with text Hard pointing to round square node with text Round; over the arrow connecting the two nodes there is a word Text; the second node further connects to a rhombus-shaped node with text Decision which then connects to two further nodes, Result 1 and Result 2.

Inline completer

JupyterLab now supports completion presented as ghost text in the cell and file editors, allowing generative AI models to provide multi-line completions. The suggestions are provided by plugins implementing the IInlineCompletionProvider API; by default a single provider which uses kernel history is available.

In a code cell with `def fac` content a ghost text containing a suggestion representing further code of factorial function is shown; over the code cell there is a floating widget allowing to accept the suggestion and iterate between alternative suggestions

The suggestions can be invoked as-you-type or manually using a configurable shortcut (by default Alt + \). The default keyboard shortcuts are displayed in the small widget shown when hovering over the ghost suggestion:

  • Alt + End - accept suggestion
  • Alt + [ - previous suggestion
  • Alt + ] - next suggestion

To enable the inline suggestions based on the kernel history, go to Settings → Inline Completer → History provider → check the “enabled” checkbox.

In addition to the built-in history suggestions, the jupyter-ai extension will provide
suggestions from supported models. The jupyter-ai integration with inline completer can be tested starting with the v2.10.0beta0 pre-release.

The Inline Completer API is still considered experimental and may be subject to changes, please share feedback!

Keyboard navigation improvements

Numerous improvements to keyboard navigation with focus on accessibility and usability are included in this release:

  • the notebook cells now retain focus
  • the focus can now be moved beyond the active notebook
  • the toolbars can now be navigated using arrow keys

For more details, see this post on Jupyter Blog.

Execution history in notebook

The code from previously executed cells can be used to populate empty cells, allowing to iterate on code from previous cells or even sessions (depending on how a specific kernel stores history).

To cycle between history items press Alt + Arrow Up and Alt + Arrow Down.

To enable execution history, go to Settings → Notebook → check the “Kernel history access” checkbox.

This feature was already available in the console in previous releases; it only works with kernels supporting execution history requests. To clear the execution history consult the documentation of the kernel you are using (e.g., IPython/ipykernel).

Opening files from tracebacks

Paths to code files detected in the tracebacks returned by kernels on execution error are now turned into links. These links will open the corresponding file for editing, if it is in the Jupyter root directory, or they will open a read-only preview if the file is outside of the root directory and the active kernel supports the debugger.

A link to the file with definition of imported module is shown in the traceback

Error indicator in the table of contents

When a cell fails during execution, an error indicator will be displayed by the corresponding heading, increasing awareness of the notebook state and enabling users to quickly navigate to the cell which requires attention.

Error indicator in the shape of a triangle with exclamation sign (using ⚠ UTF character) shown next to one of the headings in the table of contents panel

Plugin Manager

Individual plugins can now be disabled or enabled from a new Plugin Manager user interface. Each extension is composed of one or more plugins, and plugins form the basis of JupyterLab itself, thus the plugin manager enables more extensive customization of the JupyterLab experience.

An example search result in the plugin extension listing

This feature is intended for advanced users and documented in depth in the documentation.

Administrators may want to lock specific plugins if they are required for any reason; this will prevent users from disabling the plugins via Plugin Manager and remote API calls. The Plugin Manager itself can be disabled using the CLI.

Virtual scrollbar for notebook in windowed mode

The windowed notebook received an optional scrollbar delineating the active cell and selected cells. Users can jump to a specific cell.

Virtual scrollbar shown on the right side of notebook

To enable the virtual scrollbar, go to Settings → Notebook → Windowing mode, choose “full”, and click on the hamburger icon (≡) which appears in the notebook’s toolbar.

Virtual scrollbar is considered experimental, please share feedback!


JupyterLab 3.6 added a notification center which so far was only used for announcements and version update notifications (both opt-in).
JupyterLab 4.1 adds two notifications to guide users in potentially confusing situations:

  • when a user attempts to save a read-only document, a transient notification suggesting using “save as” is displayed
  • when a user attempts to execute a cell before a slow-starting kernel has initialized, a notification is shown to indicate that the cell cannot be yet executed (this is opt-in and needs to be enabled in settings)

Full notebook windowing mode improvements

Notebooks in the full windowing mode only render the visible cells, significantly improving the performance of the application.
Numerous improvements for the full windowing mode behaviour (such as scrolling, search, rendering, and navigation) are included in this release (see the list of issues in #15258 for details).

The windowing mode is still experimental and known issues remain to be solved
([#15415](https://github.com/jupyterlab/jupyterlab/issues/15415), [#15465](https://github.com/jupyterlab/jupyterlab/issues/15465),  [#15594](https://github.com/jupyterlab/jupyterlab/issues/15594)).
In addition, a sporadic regression in cell ordering ([#15610](https://github.com/jupyterlab/jupyterlab/issues/15610)) was observed in 4.1 beta,
and remains to be fixed, pending reports from users willing to test the windowing mode in JupyterLab 4.1 to help create reproducible steps that would enable fixing this issue.

Users who already enabled this mode in previous versions are advised to evaluate the benefits of fixes included in 4.1 against regressions linked above before deciding to upgrade.

Search improvements

  • The search box will now grow automatically to accommodate longer text
  • Search in selection can now be toggled using Alt + L and automatic search in selection can be configured in settings
  • Tooltips with shortcuts were added to the buttons in the search box to improve discoverability of the shortcuts


  • The current theme (dark/light) can now be synced with the browser/system preference (Settings menu → Theme → Synchronise with System Settings)
  • A blue “read-only” status indicator is now displayed in the toolbar of documents which cannot be saved because their model is read-only.
  • Native support for viewing jsonl/ndjson files was added
  • Collapsing of breadcrumbs in the File Browser can be disabled in File Browser settings
  • Extension manager can now use a HTTP proxy for fetching extensions

It is very stable for a beta, I tried out almost all of the new features.

Just had one setback getting it to run.

After updating to the beta with pip, jupyterlab wouldn’t start because it was trying to create the file /usr/etc/jupyter/page_config.json for which no permission is available on the user level. Guess this file is needed for the new Plugin Manager.

I created the folder/file manually with following content:

  "lockedExtensions": {}
1 Like

Thank you for testing it out! Do you still have the traceback for when it did not want to start?

Sure thing:

Traceback (most recent call last):
  File "/home/jj/.local/bin/jupyter-lab", line 5, in <module>
    from jupyterlab.labapp import main
  File "/home/jj/.local/lib/python3.11/site-packages/jupyterlab/labapp.py", line 101, in <module>
    app_version = get_app_version()
  File "/home/jj/.local/lib/python3.11/site-packages/jupyterlab/commands.py", line 599, in get_app_version
    handler = _AppHandler(app_options)
  File "/home/jj/.local/lib/python3.11/site-packages/jupyterlab/commands.py", line 642, in __init__
  File "/home/jj/.local/lib/python3.11/site-packages/jupyterlab/commands.py", line 1141, in _maybe_mirror_disabled_in_locked
    write_page_config(page_config, level=level)
  File "/home/jj/.local/lib/python3.11/site-packages/jupyterlab_server/config.py", line 213, in write_page_config
    cm.set("page_config", page_config)  # type:ignore[no-untyped-call]
  File "/home/jj/.local/lib/python3.11/site-packages/jupyter_server/services/config/manager.py", line 35, in set
    return self.write_config_manager.set(section_name, data)
  File "/home/jj/.local/lib/python3.11/site-packages/jupyter_server/config_manager.py", line 112, in set
  File "/home/jj/.local/lib/python3.11/site-packages/jupyter_server/config_manager.py", line 66, in ensure_config_dir_exists
    os.makedirs(self.config_dir, 0o755)
  File "<frozen os>", line 215, in makedirs
  File "<frozen os>", line 225, in makedirs
PermissionError: [Errno 13] Permission denied: '/usr/etc/jupyter'
1 Like

Thank you, I opened Locked plugin migration logic should handle config levels/permission errors better · Issue #15672 · jupyterlab/jupyterlab · GitHub - feel welcome to add any additional detail that you think might be relevant.

1 Like