Skip to content
| Marketplace
Sign in
Visual Studio Code>Visualization>MarkerNebulaNew to Visual Studio Code? Get it now.
MarkerNebula

MarkerNebula

Preview

Nafis Ahmed

|
2 installs
| (0) | Free
Whiteboard + code notebooks for VS Code. Native notebook UI (Shift+Enter, kernel picker, undo) where markdown cells are replaced by freeform drawing boards for graphics tablets.
Installation
Launch VS Code Quick Open (Ctrl+P), paste the following command, and press enter.
Copied to clipboard
More Info

MarkerNebula

A VS Code extension that opens a new file type, .ipywb ("I Py Whiteboard") — a notebook that behaves exactly like .ipynb, except markdown cells are replaced by freeform drawing boards (graphics-tablet friendly, with pressure support), alongside normal Python code cells running on a real Jupyter kernel.

Built on VS Code's native notebook UI

.ipywb files open in the same notebook editor .ipynb uses, so all the notebook features come for free and work exactly as you expect:

  • Shift+Enter / Ctrl+Enter to run cells, run-all, run-above/below
  • The native Select Kernel button (top right of the notebook)
  • Monaco code cells — syntax highlighting, IntelliSense with the Python extension installed
  • Native undo/redo (including drawing strokes — each stroke is an undo step)
  • Cell reordering, collapse, outline, find, diff view on save conflicts
  • Stop button interrupts a running cell (KeyboardInterrupt, variables survive — just like Jupyter)
  • Live streaming output, matplotlib/pandas rich output, ANSI-colored tracebacks

The whiteboard is implemented as a notebook output renderer: a board cell is a cell whose output is an interactive canvas. Draw on it with a mouse or graphics tablet (pen pressure is recorded); strokes persist into the file as vector data and participate in undo.

How the pieces fit

VS Code extensions run in a Node.js extension host, so the shell is TypeScript. Python appears exactly where it should: executing your code.

MarkerNebula/
├── package.json            # notebook type, board renderer, commands
├── src/
│   ├── extension.ts        # activation, commands, board-edit persistence
│   ├── ipywbTypes.ts       # the .ipywb JSON format types
│   ├── ipywbSerializer.ts  # .ipywb JSON <-> vscode.NotebookData
│   ├── controllers.ts      # kernels for the native kernel picker
│   └── kernelClient.ts     # talks to kernel_bridge.py (spawn + JSON pipes)
├── webview/
│   └── boardRenderer.js    # the drawing board (notebook output renderer)
├── python/
│   ├── kernel_bridge.py    # owns a real ipykernel via jupyter_client
│   └── requirements.txt
└── examples/
    └── sample.ipywb

Execution flow: each open .ipywb gets its own kernel_bridge.py process, which launches a genuine ipykernel on the same interpreter you picked in the kernel picker and streams outputs back over line-delimited JSON. State persists across cells; interrupt uses the same Win32-event/SIGINT machinery as Jupyter itself.

Picking a kernel (like ipynb)

Click Select Kernel in the notebook toolbar. You'll see:

  • MarkerNebula Python — uses the markernebula.pythonPath setting.
  • One entry per interpreter/venv discovered by the ms-python extension (if installed) — conda envs, venvs, system Pythons.

Whichever you pick must have the bridge deps installed: pip install jupyter_client ipykernel.

The .ipywb file format

Plain JSON, in the spirit of .ipynb but with whiteboard cells (markdown cells are also supported if you add one via the native "+ Markdown" button):

{
  "metadata": { "name": "...", "kernelspec": {...}, "ipywb_version": "1.0" },
  "cells": [
    { "id": "...", "type": "whiteboard", "canvas": { "width": 1600, "height": 1000, "strokes": [...] } },
    { "id": "...", "type": "code", "source": "...", "outputs": [...], "execution_count": 1 }
  ]
}

Strokes are stored as vector points with pressure, not raster pixels — crisp at any size, small diffs in git. Boards grow with the W/H buttons on each board's toolbar (an effectively unbounded page).

Adding board cells

Several ways, pick your favourite:

  • "+ Board above" / "+ Board below" — always visible in the status bar of every cell (bottom edge of the cell, next to the language indicator). The built-in between-cell "+ Code / + Markdown" hover bar is not extensible by extensions, so this is the equivalent for boards.
  • the + Board button in the notebook toolbar (top of the editor),
  • hover any cell and click the paint-can icon in its cell toolbar ("Insert Board Below"),
  • Ctrl+Alt+B (Cmd+Alt+B on Mac),
  • "MarkerNebula: Insert Board Cell" from the command palette.

Drawing is flicker-free: strokes are stored via cell-metadata updates that never re-render the cell. Every board also has its own Undo / Redo buttons (stroke-level), and notebook-level Ctrl+Z tracks strokes too.

Boards are self-healing: strokes live in cell metadata, not in the output, so "Clear All Outputs" only clears code cell results — if anything removes a board's on-screen canvas, the extension instantly rebuilds it from the stored strokes. A board can only be removed by deleting its cell.

Added a markdown cell by accident with the native "+ Markdown" button? Hover it and click Convert to Whiteboard in its cell toolbar. And if VS Code creates a "+ Code" cell with the board language (it copies the language of the neighbouring cell), the extension automatically rewrites it to Python so it always runs.

Setting it up locally

  1. npm install
  2. pip install -r python/requirements.txt (into whichever Python your cells should run on — e.g. the bundled .venv)
  3. npm run compile
  4. Press F5 to launch an Extension Development Host, then open examples/sample.ipywb there.

If python isn't the interpreter you want, set markernebula.pythonPath, or just install the ms-python extension and pick any environment from the kernel picker.

Publishing

npm install -g @vscode/vsce
vsce package        # produces marker-nebula-0.2.0.vsix
vsce publish        # requires a Marketplace publisher account

Known limitations

  • On Windows, interrupting a cell only takes effect between Python statements — blocking C calls (e.g. a single long time.sleep, heavy native NumPy ops) can't be broken mid-call. This is a Python/Jupyter platform limitation; real Jupyter behaves the same. Use MarkerNebula: Restart Kernel if a cell is truly stuck.
  • Exporting a board to PNG/SVG is not implemented yet.
  • Contact us
  • Jobs
  • Privacy
  • Manage cookies
  • Terms of use
  • Trademarks
© 2026 Microsoft