Contents

Notebook Support

Zasper implements Jupyter’s wire protocol and reads and writes the .ipynb format directly, so notebooks move between Zasper and JupyterLab unchanged.

When Zasper opens and saves a notebook, the file comes out byte-for-byte as Jupyter would have written it, so saving creates no unwanted diff and no merge conflicts. A notebook also keeps its own nbformat version. A 4.2 notebook is saved as 4.2, where JupyterLab would silently upgrade it to the newest version. Notebooks in formats 2 and 3 are converted to 4.5 when opened.

Saves are atomic: Zasper writes beside the file and then renames over it, so a crash or a full disk cannot leave a half-written notebook.

When a kernel starts, the language_info it reports about itself replaces the one in the file, as Jupyter does, so a notebook records the language version it last ran with.

Cells

The rail between cells adds a Code, SQL, Markdown or Raw cell. Each cell’s box is labelled with its kind. A SQL cell is a code cell underneath; see SQL Cells.

A code cell’s run button and execution count sit side by side in its gutter. While the cell runs, the button becomes a stop button; a cell waiting behind another shows [*]. The cell’s run time, on its border, counts up while it runs and stays shown after. It is saved in the cell’s metadata.execution, as JupyterLab’s Record timing writes it, so a notebook opened later still says how long each cell took. Settings → Notebook → Keep cell times in the file turns the saving off; the times are still shown.

Shift-Enter runs a cell and moves to the next, and the next cell stays in view while the output above it grows.

In a cell, Tab completes from the kernel; Settings → Notebook → Insert a tab in a cell makes it indent instead. Settings → Notebook → Show the table of contents puts every notebook’s headings in a column beside its cells; the toolbar’s button turns it on for one notebook.

Runs That Outlive the Tab

A cell’s run belongs to the server, not to the browser tab that started it. Start a long cell, close the tab, and come back: every line it printed is there. (On a laptop running Zasper itself, sleep pauses the run too.)

A run keeps at most 8 MB of output, oldest first out, and a single stream keeps its last 1 MB, since the end of a long log is what gets read.

When the File Changes on Disk

A notebook can change under an open tab: git pull, a script, an agent, or another editor. Zasper takes the change in cell by cell rather than reloading the whole notebook.

When the change came through Zasper, the band names who made it, such as an agent.

A save never writes over a change it has not seen. If the file changed since the tab last read it, the save is refused, the band says the notebook was not saved, and the cells that differ ask as above.

When a Kernel Dies

A kernel that exits on its own, while starting or later, is reported in the notebook with the reason, such as its exit code, and the last lines it printed, which usually hold the error that killed it. Start it again from there or pick another kernel. A cell whose kernel died before answering keeps no execution count. See Installing Jupyter Kernels.

What Renders

Output Status
text/plain, stdout/stderr, tracebacks ✅
text/html ✅
image/png ✅
image/jpeg ✅
text/markdown ✅
image/gif, image/webp ✅
application/pdf ✅
image/svg+xml ✅
text/latex ✅
Plotly figures (application/vnd.plotly.v1+json) ✅
ipywidgets (application/vnd.jupyter.widget-view+json) ✅
application/json ✅
Markdown cells: GFM tables, task lists, raw HTML, LaTeX via KaTeX ✅

text/latex, which SymPy produces after init_printing() and IPython’s Latex and Math display, is typeset with KaTeX, the same renderer markdown cells use. image/svg+xml, which graphviz and networkx produce, and matplotlib under %config InlineBackend.figure_format = 'svg', is placed directly in the page rather than inside an <img>, so a figure that sizes itself to the cell still can. SVG, JPEG and LaTeX output render from 1.1.0.

Known Limitations