Skip to main content

Claude-powered chat side panel for JupyterLab / Notebook 7.

Project description

pynote

PyPI distribution: jupyter-pynote · Python import: pynote · Lab extension id: pynote

Claude-powered chat side panel for JupyterLab 4 and Jupyter Notebook 7.

Open any notebook, crack open the side panel, and talk to Claude about the code. When Claude proposes changes to the notebook, type apply in chat and they're written into real cells — no dialog box, no reload, no token-pasting.

Features

  • Right-hand side panel docked into the Lab shell; follows the currently active notebook.
  • Chat with Claude about the current notebook's cells (their source is sent as context each turn).
  • Structured cell edits via Claude tool-use — replace existing cells or insert new ones by stable cell id, not brittle index.
  • apply / cancel are typed in chat; no modal or popup.
  • Edits go through Lab's own shared model, so undo / autosave / RTC all Just Work.
  • Server extension proxies the Claude call, so ANTHROPIC_API_KEY lives in the Jupyter process — never in the browser.

Prerequisites

  • Python 3.9+
  • JupyterLab 4 or Notebook 7
  • An Anthropic API key

Install from PyPI

pip install jupyter-pynote

That's it — the wheel ships the prebuilt labextension, so no Node, no jupyter labextension install, no post-install step. Both the server extension and the Lab plugin auto-enable.

Provide your Anthropic key once (persistent across shells; auto-loaded by the server at startup):

mkdir -p ~/.pynote
echo 'ANTHROPIC_API_KEY=sk-ant-...' > ~/.pynote/.env
chmod 600 ~/.pynote/.env

Or export it in your shell (~/.zshrc, direnv, per-venv activate scripts — anything that gets into the environment of the jupyter lab process).

Launch:

jupyter lab

Open any .ipynb. You'll see a PyNote tab in the right sidebar.

Install from source (dev)

From jupyter-pynote/:

# 1. Install the Python side (server extension) in editable mode
pip install -e ".[dev]"

# 2. Install npm deps and build the labextension assets
jlpm install
jlpm build

# 3. Wire the labextension into JupyterLab
jupyter labextension develop . --overwrite

# 4. Enable the Jupyter server extension
jupyter server extension enable pynote

# 5. Provide your API key (or put it in ~/.pynote/.env — auto-loaded)
export ANTHROPIC_API_KEY=sk-ant-...

# 6. Launch Jupyter
jupyter lab

Verify the extension is loaded:

jupyter labextension list      # should show: pynote v0.1.0 enabled ok
jupyter server extension list  # should show: pynote enabled

Open any .ipynb. You'll see a pynote tab in the right sidebar.

Model / tokens

Override via env vars before launch:

export PYNOTE_MODEL=claude-sonnet-4-6     # default
export PYNOTE_MAX_TOKENS=4096             # default

How the chat works

  1. You type a question — "plot the last column" or "explain cell 3". pynote sends your message plus a snapshot of every cell's id, type, and source to the server extension.
  2. The server forwards it to Claude with a system prompt that describes the propose_notebook_changes tool.
  3. Claude replies with prose, and optionally calls the tool with a list of changes {op, target_cell_id, source}.
  4. The panel shows the prose + a compact preview of each proposed change.
  5. You type apply → pynote walks the change list and calls sharedModel.setSource(...) / sharedModel.insertCell(...) inside a single transaction. One undo reverts the whole batch.
  6. Type cancel / discard / no to drop the proposal, or just keep chatting — a follow-up question clears the pending proposal automatically.

There's no apply button, no modal, no popup — everything is in the chat line.

Smoke test without Lab

Quickly verify Claude integration without running Jupyter:

export ANTHROPIC_API_KEY=sk-ant-...
python scripts/smoke_test.py

Expected: a proposal with at least one replace or insert_after change targeting the empty cell.

Dev workflow

# In one terminal — rebuild on TS changes
jlpm watch

# In another — Lab picks up the changes on refresh
jupyter lab

On Python-side changes, restart Lab.

Uninstall

jupyter server extension disable pynote
jupyter labextension uninstall pynote
pip uninstall jupyter-pynote

Troubleshooting

  • Panel doesn't appear: run jupyter labextension list; if pynote isn't there, redo step 3.
  • Panel says "No notebook open": that's literal — open a .ipynb in the same Lab window.
  • ANTHROPIC_API_KEY is not set: the server process (the one running jupyter lab) didn't inherit the env var. Export it in that shell before launch.
  • 403 / xsrf in browser console: shouldn't happen since requests go through @jupyterlab/services — but if you see one, disable any other extension that proxies Lab API calls.

License

MIT — see LICENSE.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

jupyter_pynote-0.1.0.tar.gz (133.4 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

jupyter_pynote-0.1.0-py3-none-any.whl (54.5 kB view details)

Uploaded Python 3

File details

Details for the file jupyter_pynote-0.1.0.tar.gz.

File metadata

  • Download URL: jupyter_pynote-0.1.0.tar.gz
  • Upload date:
  • Size: 133.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.9

File hashes

Hashes for jupyter_pynote-0.1.0.tar.gz
Algorithm Hash digest
SHA256 a0129204324c389a58e52b3aaffe6811fcdb0ef652346675905a98555e0b8570
MD5 09fe904bc8a29feb706f28d177daceb5
BLAKE2b-256 30fe394220cca13b3fd53df248282e26d8fc4195bfc3271c268f24f6ce797305

See more details on using hashes here.

File details

Details for the file jupyter_pynote-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: jupyter_pynote-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 54.5 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.9

File hashes

Hashes for jupyter_pynote-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 e35a7a1bf3604507a1e8de6a80be9e49a3dadbe4ea6fab329bc6921f64316530
MD5 4715c965d7b75079375323659bc48fcf
BLAKE2b-256 5cfd318ba5442177ae48ad8ee7e59097836fbe6ec7c53024eff973b1dedaae6f

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page