Skip to content

Code cells

A code cell runs real code against a real Jupyter kernel, Python, JavaScript, or anything else with an installed kernelspec, directly from a bullet. Subspace speaks the Jupyter wire protocol itself: there is no Python of ours, no jupyter-server process to run, and no notebook file format to reconcile. The kernel is just another process the server spawns and talks to.

Type a backtick (`) at the start of a bullet’s text and the bullet converts into a code cell. The node’s text becomes the cell’s source, edited in a CodeMirror 6 editor with syntax highlighting for the kernelspec’s language, Python, JavaScript, or TypeScript get full highlighting; anything else falls back to plain text.

Each cell has its own kernel picker in the node-frame header. It lists every kernelspec Subspace discovers on the standard Jupyter search paths (~/Library/Jupyter/kernels, /usr/local/share/jupyter/kernels, and any directories in $JUPYTER_PATH), so any kernel you’d normally see in Jupyter or JupyterLab shows up here with no extra configuration. Picking a kernel spawns it (or reuses an already-running instance for that cell) the first time you execute.

⌘↵ (or the execute button in the frame header) runs the cell, following the universal activation convention every element shares. Under the hood, Subspace talks to the kernel directly over zeromq using kernel wire protocol 5.3, the same protocol Jupyter clients use, with every message HMAC-signed per the kernel’s connection file. There’s no intermediary jupyter-server: the server process owns the zeromq sockets and streams execute_request / execute_reply / stream / display_data messages straight from the kernel to the cell.

Whatever the kernel returns, text, sandboxed HTML, images, or errors, is captured and written into the cell’s element.outputs via the setCellOutputs command, the same command protocol every other element edit uses. Images land in the content-addressed blob store. Because outputs are persisted, reopening a page renders the last output immediately without re-running the cell; execution only happens when you explicitly trigger it again.