Skip to content

ReferenceLook things up as you need them.

Other Jupyter clients ​

Jupyter frontends and clients other than JupyterLab and VS Code (see JupyterLab and VS Code), and whether each could run against Ganymede. Surveyed in October 2026; none of these are in the automated tests.

What Ganymede offers a client today ​

As of this survey:

  • REST: /api/kernels, /api/kernelspecs, /api/sessions, /api/contents, /api/status, /api/me, /api/config, /api/events, and JupyterLab's /lab/api/*. Websocket at /api/kernels/{id}/channels.
  • Auth: token in header or ?token=, or the login cookie a token or the /login form sets, with jupyter_server's _xsrf check.
  • CORS via allow_origins.
  • Kernel connection files are written to JUPYTER_RUNTIME_DIR, so a ZMQ client can attach to a kernel Ganymede launched.
  • Not served: classic Notebook / Notebook 7 pages (/tree, /notebooks), terminals, /lsp/*, collaboration rooms (/api/collaboration), nbconvert exporters, server extensions.

So a client works today if it speaks REST/websocket with a token and needs no HTML pages from the server.

Survey ​

"Last commit" is the default branch's latest commit date, read from a shallow clone on 2026-10-17. App Store apps show the latest release instead.

Mobile ​

ClientMaintainedTalks toAgainst Ganymede
Juno Connect (iPad, $4.99)Stale. Last release 1.6.13, 2022-09-18REST/websocket to a remote server, over HTTP(S) or SSH tunnelUnknown, likely blocked. Its JupyterLab 4 workaround is pointing it at nbclassic/tree, so it seems to need the classic Notebook pages and maybe a login form. Needs a device test.
Juno (iPad)Same developerRuns Python on the deviceNo server involved.
Carnets (iOS)Last commit 2024-02Bundled Python and Jupyter on the deviceNo server involved.

There is no maintained native Android Jupyter client; people use a browser.

Desktop apps ​

ClientMaintainedTalks toAgainst Ganymede
nteract (originally backed by Netflix)Yes, rewritten. Last commit 2026-10-16. Now a Tauri + React app with a Rust daemon (runtimed), Automerge sync and hosted "rooms"; Electron version is goneDirect ZMQ to local kernels via jupyter-zmq-client / jupyter-protocol. No Jupyter server clientNo. It replaces the server rather than using one. Relevant as prior art (same Rust crates Ganymede's notes list) and as a place to run cdp-kernel.
JupyterLab DesktopYes, last commit 2026-10-14Bundles a Python env; can also open a remote server URL, which loads that server's JupyterLab pageSame as JupyterLab in a browser, which works with cookie login. No separate test needed.
PyCharm / DataSpell (JetBrains)Yes, commercialREST/websocket to a server by URL + tokenLikely works; it is a token client like VS Code. Manual test only.
Positron (Posit)Yes, last commit 2026-10-17Its own kernel supervisor (Kallichore, Rust) over ZMQ; no Jupyter server clientNo. Prior art for a Rust kernel supervisor.
Google Colab "local runtime"Extension last commit 2021-08Needs the jupyter_http_over_ws server extension (an HTTP-over-websocket proxy)No, and not worth adding.

Editors and terminal ​

ClientMaintainedTalks toAgainst Ganymede
Zed REPLYes, last commit 2026-10-17Rust; jupyter-websocket-client from runtimed. Set JUPYTER_SERVER and JUPYTER_TOKEN; it calls /api/kernelspecs, /api/kernels, then /api/kernels/{id}/channels?token=Should work today. Also has an early .ipynb notebook UI.
jpterm (successor to nbterm)Yes, last commit 2026-10-15--server URL: REST/websocket. Collaborative mode needs Y rooms (Jupyverse)Should work with --no-collaborative. Scriptable, so CI-friendly.
emacs-jupyterYes, last commit 2026-08-13ZMQ locally, or REST/websocket via jupyter-server-* commandsShould work over REST.
Emacs IPython Notebook (EIN)Slow, last commit 2025-12REST/websocket, /api/contentsProbably works; lower priority than emacs-jupyter.
molten-nvimYes, last commit 2026-07-02ZMQ locally, or :MoltenInit <server URL> over REST/websocketShould work over REST.
jupynium.nvimYes, last commit 2026-09-20Drives a browser running Notebook/JupyterLab via SeleniumNeeds the classic or Lab UI in a browser; Lab works, the classic UI isn't served.
euporieYes, last commit 2026-10-07ZMQ only: local kernelspecs or --connection-fileCan attach to a Ganymede-launched kernel's connection file.
jupyter console / qtconsoleYes (2026-09 / 2026-03)ZMQ, --existing connection fileSame as euporie.

Embeddable / libraries ​

ClientMaintainedTalks toAgainst Ganymede
Datalayer jupyter-ui (@datalayer/jupyter-react)Yes, last commit 2026-10-06, MITReact components over @jupyterlab/services: REST/websocket with token; optional Yjs collaborationShould work today in non-collaborative mode, cross-origin with allow_origins. Its README notes comms "need to be fixed", so widgets may not. Relevant to Ganymede's own TypeScript UI.
ThebeYes, last commit 2026-06-22@jupyterlab/services against a server or BinderShould work with token + CORS. Live code cells in static pages.
JupyterLiteYesNo server; in-browser kernelsNot a client; precedent for the iPad profile.
VoilàYes, last commit 2026-09-04A jupyter_server extensionNo (Python server extension).

Headless ​

ClientMaintainedTalks toAgainst Ganymede
papermillYes, last commit 2026-03-08nbclient → jupyter_client: launches kernels locally and talks ZMQ. No server neededTwo ways to test: (1) run papermill on cdp-kernel's kernelspec and compare with Ganymede's own executor (a kernel and output-parity test, no server); (2) a custom engine using jupyter_server's GatewayKernelManager pointed at Ganymede, which drives Ganymede's REST/websocket API (Elyra ships such an engine).
nbclient / jupyter executeYes, last commit 2026-06-05Same as papermillAlready the e2e oracle.
jupyter_server --gateway-url / Enterprise Gateway clientsGateway client yes; Kernel Gateway last commit 2024-03Remote kernels over /api/kernels, /api/kernelspecs and channelsShould work: Ganymede already serves the gateway subset. One test covers papermill-via-gateway, Elyra and JupyterLab-on-Python-with-Ganymede-kernels.
Datalayer jupyter-kernel-client, jupyter-mcp-serverYesREST/websocket; MCP server also uses collaboration rooms for notebook editsKernel client should work; MCP notebook editing needs Y rooms.

Worth trying, in order ​

  1. Zed REPL. A native, maintained, Rust REST/websocket client. Two env vars, no Ganymede changes expected. Quick confidence that a non-browser client works.
  2. papermill, both ways: kernel-level parity on cdp-kernel, and the GatewayKernelManager engine against Ganymede. The second also proves Ganymede works as a Jupyter gateway, which opens the door to every Python Jupyter server using it for kernels.
  3. Datalayer jupyter-ui. The cheapest way to see a React notebook on Ganymede, cross-origin with a token, and a candidate base for Ganymede's own UI. Can be automated with the existing Playwright harness.
  4. Juno Connect. The only iPad client. Expect gaps (classic /tree page, login form). Needs an iPad; cookie login has landed.
  5. jpterm (--no-collaborative) as a cheap scripted CI client, and jupyter console --existing on a Ganymede-launched kernel to check that two clients can share one kernel.

Skip: nteract, Positron, euporie, Colab local runtime, JupyterLab Desktop (covered by JupyterLab), Voilà.

Sources ​

How nteract builds its UI ​

Read from nteract/nteract (last commit 2026-10-16), mainly docs/adr/. Patterns worth considering for Ganymede's own UI (see User interfaces):

  • One UI, several hosts. A NotebookHost interface (packages/notebook-host/src/{tauri,browser,electron}) wraps every native call: dialogs, windows, logging, transport. Desktop, hosted cloud and a component gallery share one NotebookDocumentShell, fed a host-neutral capabilities object (read-only, ACLs). This maps onto a Swift/WKWebView host plus a browser host. (docs/adr/notebook-host-shell-convergence.md)
  • React doesn't own the document. The document lives in a WASM peer (Automerge). An RxJS SyncEngine emits one stream per concern (cells, runtime state, outputs, presence), and a bridge writes them into small useSyncExternalStore stores read through hooks like useCell(id). This stops kernel-status updates from re-rendering cell edits. (docs/adr/frontend-sync-bridge.md)
  • Local-first edits. A keystroke mutates the local doc at once; the flush to the daemon is debounced, and execute/save wait for the flush explicitly.
  • Sandboxed outputs. Rich outputs render in iframes with sandbox="allow-scripts ..." and no allow-same-origin, so each frame gets an opaque origin. Native bridges are never exposed to output frames. (docs/adr/output-frame-security.md)
  • Output lanes. Plain streams render in the main DOM. Widgets and charts, document-like HTML, and large tables each get their own frame type, so a table can't trap page scrolling. (docs/adr/output-rendering-segmentation.md)
  • Stable DOM order. Moving an iframe reloads it and loses widget state, so cells are never reordered in the DOM.
  • Stack. React, CodeMirror 6, Radix/shadcn primitives, Tailwind with oklch semantic tokens, ansi-to-react. A DESIGN.md holds the token set.

MIT license.