Switching to cdp-kernel
This page is for people who already write notebooks with another kernel: deno jupyter, tslab or IJavascript, or Python. Each section says what carries over, what changes, and where the details are.
From deno jupyter
cdp-kernel is a port of deno jupyter's kernel, so most of a Deno notebook carries over. Deno's runtime is on a 2.9.x LTS line, with bug-fix and security releases until October 2027 and no new features (What changed). cdp-kernel can keep running the same notebooks on Deno, and on Node when you want to move off Deno.
Two kernels run a Deno notebook:
cdp-denoruns cells on Deno itself.Deno.jupyterand every otherDeno.*API are Deno's own, and adeno.jsonat or above the notebook is used asdeno jupyteruses it.cdp-node-denoruns cells on Node with a partialDenonamespace:Deno.jupyter,Deno.env, and Deno's basic file and process functions. Use it to move a notebook to Node without rewriting it.
cdp-kernel install --runtime deno
cdp-kernel install --runtime node --deno-compatOpen the notebook and pick one of them with Kernel › Change Kernel. Install covers the JSR route, which needs no Node.
What stays the same:
- The display API.
Deno.jupyterand thejupyterglobal are the same object on both kernels, withdisplay,md,html,svg,image,format,broadcastand the$displaysymbol. - Rich values: Polars DataFrames, Vega-Lite charts, canvases, images and DOM elements display as they do in Deno.
- The language: TypeScript, TSX, top-level
await,constredeclaration across cells,npm:andjsr:imports. Cells aren't type-checked, as in Deno. - The notebook file. A Deno-style notebook is written against
deno jupyter's APIs and gives the same outputs oncdp-denoandcdp-node-deno.
What changes:
- Lockfiles.
cdp-denoruns Deno with--no-lock, so it neither reads nor writes a project'sdeno.lock. Pin a version with an exact specifier (npm:nodejs-polars@0.18.0). On Node, acdp-kernel.lock.jsonnext to the notebook pins everynpm:andjsr:import (Lockfile). - The
Denonamespace on Node is partial.Deno.serve,Deno.Command,Deno.open,Deno.openKvand other members outside the shim areundefined, andDeno.version.denois"0.0.0-cdp-kernel". Notebooks written for Deno lists what's there. - Formatting. On Node, results are formatted by
util.inspect, so strings are quoted'…'rather than"…"(Known gaps). - WebGPU textures and buffers don't display.
What you gain: widgets (deno jupyter has none), JupyterLab's debugger on Node and Deno, and the other runtimes. New notebooks should use jupyter rather than Deno.jupyter, so they run on every kernel.
From tslab or IJavascript
tslab and IJavascript are the older Node kernels. According to the feasibility study, tslab's last release was in mid-2024 and IJavascript's in 2021, and both depend on the native zeromq addon. cdp-kernel speaks Jupyter's ZeroMQ protocol in plain JavaScript, so it has no native addon to build.
Install the Node kernel and pick cdp-node with Kernel › Change Kernel:
npm install -g @tlockney/cdp-kernel
cdp-kernel install --runtime nodeWhat cdp-kernel adds:
npm:andjsr:imports that install on first use, with an optional lockfile (Language and imports).- TypeScript and TSX through esbuild, with no
tsconfig.json. - Rich output through the
jupyternamespace, the same API asdeno jupyter. Code that called a kernel-specific display helper needs to calljupyter.displayorjupyter.htmlinstead. - Interactive widgets, JupyterLab's debugger, typed completion and inspection (Inspection, completion and history), and, on Node, an interrupt that keeps your variables.
- The same notebook on Deno, Bun, workerd and celld (Choosing a runtime).
One behavior may differ from what you're used to. On Node and Deno, cells run as deno jupyter runs them: a top-level const stays constant, and any final expression is the cell's result. The Bun, workerd and celld targets instead hoist declarations onto globalThis, the technique tslab and IJavascript use (Bun).
From Python
The notebook works the same way: cells, outputs, Kernel › Interrupt and Kernel › Restart. The libraries differ. Each line below is a starting point, not a drop-in replacement.
| In Python | In cdp-kernel | Where to read |
|---|---|---|
| pandas | npm:nodejs-polars DataFrames display as tables; npm:arquero is another option | Tables with Polars, MoMA's collection |
| matplotlib, seaborn | Observable Plot (npm:@observablehq/plot, with linkedom as its DOM on Node), Vega-Lite (npm:vega-lite-api), or a canvas (npm:@napi-rs/canvas) | Charts with Vega-Lite, MoMA's collection |
IPython.display.display, HTML, Markdown, SVG | jupyter.display, and the jupyter.html, jupyter.md, jupyter.svg tags | The jupyter namespace |
display(..., display_id=...) and update_display | jupyter.display(value, { display_id, update: true }) | Updating output in place |
_repr_html_ on a class | a [jupyter.$display]() method | Custom display |
input() | prompt() and confirm() | Asking for input |
| ipywidgets | jupyter.widget, anywidget-style. The ready-made controls (IntSlider, Dropdown) are Python classes and aren't available; you build controls from HTML | Widgets and comms |
pip install | import pl from "npm:nodejs-polars@0.18" installs on first use | Language and imports |
Widgets still need pip install anywidget in the Python environment that runs JupyterLab, for the frontend; no Python kernel is involved (Before you start).
Packages with native add-ons, such as nodejs-polars and @napi-rs/canvas, work on Node, Deno and Bun but not on workerd or celld.