Metadata-Version: 2.4
Name: hot-notebook-patching
Version: 0.1.0
Summary: JupyterLab extension for hot patching externally modified notebooks
License: MIT
License-File: LICENSE
Classifier: Framework :: Jupyter
Classifier: Framework :: Jupyter :: JupyterLab
Classifier: Framework :: Jupyter :: JupyterLab :: 4
Classifier: Framework :: Jupyter :: JupyterLab :: Extensions
Classifier: Framework :: Jupyter :: JupyterLab :: Extensions :: Prebuilt
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Requires-Python: >=3.8
Requires-Dist: jupyterlab<5.0.0,>=4.0.0
Description-Content-Type: text/markdown

# hot-notebook-patching

A JupyterLab extension for **hot patching** notebooks that are edited externally — for example by an AI coding agent like Claude Code.

Instead of triggering a full notebook reload (which restarts the kernel and clears widget state), only the cells that actually changed are patched into the live notebook model.

## What it does

```
Claude Code edits notebook.ipynb on disk
          ↓
Extension detects the file change
          ↓
Only modified cells are patched
          ↓
Kernel keeps running · Widget state intact · Scroll position preserved
```

Modified lines are highlighted with an orange left-border marker directly in the cell editor, similar to git-diff gutter decorations in VS Code.

## Requirements

- JupyterLab ≥ 4.0
- Notebooks must use `nbformat` 4.5+ (cell IDs required for accurate diffing)

## Installation

```bash
pip install hot-notebook-patching
```

## Usage

### Toolbar button

Each notebook gets a ⚡ bolt button in the toolbar. Click it to toggle **auto-patch mode** — the extension will watch the file for changes and patch automatically.

### Commands

| Action | How |
|---|---|
| Patch once from disk | Toolbar ⚡ button (when auto-patch is off) · `Shift+P` inside a notebook · Command Palette → *Patch Notebook From Disk* |
| Toggle auto-patch | Toolbar ⚡ button · Command Palette → *Toggle Auto-Patch on File Change* |

### What is preserved

- Running kernel
- Widget state (ipywidgets, anywidget, …)
- Cell outputs and execution counts
- Scroll position

### What is updated

- Cell source code (with line-level diff indicators)
- Cell metadata
- Added / deleted / reordered cells

### Conflict detection

If both you and an external tool edited the same cell since the last patch, the extension skips that cell and logs a warning — it will never silently overwrite your changes.

### Auto-execute on patch

Add `"hotpatch": true` to a cell's metadata and the cell will be automatically executed after its source is patched:

```json
{
  "hotpatch": true
}
```

## Development

```bash
git clone https://github.com/kolibril13/hot-notebook-patching
cd hot-notebook-patching

# Create venv and install JupyterLab
uv venv .venv
uv pip install --python .venv/bin/python jupyterlab

# Install JS dependencies and build
.venv/bin/jlpm install
.venv/bin/jlpm build:lib:prod
.venv/bin/jlpm build:labextension:dev

# Install Python package in editable mode
uv pip install --python .venv/bin/python hatchling hatch-jupyter-builder editables
uv pip install --python .venv/bin/python -e . --no-build-isolation

# Link the extension for live development
.venv/bin/jupyter labextension develop . --overwrite

# Start JupyterLab
.venv/bin/jupyter lab
```

For iterative development, rebuild after source changes:
```bash
.venv/bin/jlpm build:lib:prod && .venv/bin/jlpm build:labextension:dev
```
Then hard-refresh JupyterLab (`Cmd+Shift+R` / `Ctrl+Shift+R`).

## License

MIT
