make build builds the workspace, or one target with target=chrome (firefox, safari, or any packages/<name>). browser writes dist/chrome, firefox and safari itself; every other package builds in place, where its package.json points, and dist/<name> links to it. make test runs every suite, and all of them pass. The Makefile, README and root src/, scripts/, test/, docs/, examples/, benchmark/ and tsconfigs belonged to the hanzo-dev CLI this repo used to be; none of it built or described anything here. CLAUDE.md, AGENTS.md and GEMINI.md are symlinks to LLM.md and stay out of git. jupyter ran a jupyter binary nobody installs; it runs under uvx pinned to jupyterlab 4.5, since 4.6 fetches core metadata from GitHub at build time. pdf's tests load pdf.js's legacy build, the one made for Node. vscode's test is its vitest suite; the Electron harness is test:electron. Claude-Session: https://claude.ai/code/session_01Dc8DXc3fEQCRHUa6XWK4Ku
Hanzo AI for JupyterLab
@hanzo/jupyter — an in-notebook AI assistant for JupyterLab 4. AI where data
scientists live.
- Assistant side panel — a model picker, a prompt, and streaming output. It can attach the active cell, the selected cells, or the whole notebook as context.
- Cell actions (command palette, cell context menu, and cell toolbar):
- Explain this cell — plain-language walkthrough of a code cell.
- Fix / debug — reads the cell and its error traceback, inserts a corrected cell below.
- Add docstring / comments — documents the code in place.
- Optimize — vectorizes / cleans up without changing behavior.
- Generate a cell from a prompt — describe what you want, get a new cell.
- Reads cell outputs (especially tracebacks) for the fix action, and inserts AI-generated code as a new cell below the active one.
Model calls route through the Hanzo AI gateway (api.hanzo.ai, /v1/...)
via the published headless client @hanzo/ai —
no bespoke HTTP. Your Hanzo sk- key is set in JupyterLab settings, never in
source.
Architecture
The JupyterLab widget layer is kept thin; the model-facing logic is pure and unit-tested.
| File | Responsibility |
|---|---|
src/index.ts |
The JupyterLab plugin — the imperative shell. Registers the panel, the five commands, the cell toolbar button + context menu, tracks the active notebook, and adapts live cells into the pure data shapes. |
src/panel.tsx |
The side-panel ReactWidget (model picker + prompt + streaming output over @hanzo/ai). |
src/notebook.ts |
Pure. Cell / notebook → context text, error-output & traceback extraction, ANSI stripping, truncation, fence stripping. |
src/hanzo.ts |
Thin over @hanzo/ai + the pure action catalog: system frame, per-action prompt builders, request shaping, and the two async model edges (runAction, streamChat). |
src/config.ts |
Settings resolution + command/plugin ids. |
schema/plugin.json |
The settings-registry schema (API key, default model, gateway base URL). |
Requirements
- JupyterLab >= 4.0
- Node >= 18 and pnpm, the workspace's package manager. The labextension
step runs
jupyter labextension build, so JupyterLab has to be onPATH. - A Hanzo
sk-API key (from https://hanzo.ai) for authenticated models; the gateway also serves public/limited models anonymously.
Build
# from the repo root, install workspace deps
pnpm install
cd packages/jupyter
# compile TypeScript → lib/ and build the federated labextension bundle
pnpm build # dev build
pnpm build:prod # minified production build
pnpm build runs build:lib (tsc) then build:labextension (jupyter labextension build .), emitting the federated bundle under
hanzo_jupyter/labextension.
Install (development)
# from packages/jupyter — installs the Python package and links the source
# extension so a rebuild is picked up on JupyterLab reload
pip install -e .
jupyter labextension develop . --overwrite
pnpm build
jupyter labextension list # should show @hanzo/jupyter … enabled OK
jupyter lab
For a normal install from a built wheel:
pip install .
jupyter lab
Settings — your Hanzo key
Open Settings → Settings Editor → Hanzo AI (or edit Advanced Settings JSON):
{
"apiKey": "sk-…",
"model": "zen5",
"baseUrl": "https://api.hanzo.ai"
}
apiKey— your Hanzosk-key. Sent as a Bearer token toapi.hanzo.ai. Leave blank to use the gateway's public models. Stored by the JupyterLab settings registry, never committed to source.model— the default model id for cell actions and the panel. Any id from/v1/models(the panel's picker lists them live). Defaults to a Zen model.baseUrl— override only for a self-hosted gateway.
Usage
- Panel — click the Hanzo tab in the right sidebar. Pick a model and a
context mode, type a prompt,
Send(or ⌘/Ctrl+Enter). Output streams in. - Cell actions — right-click a code cell, use the cell toolbar, or the command palette ("Hanzo AI"). Fix/document/optimize/generate insert a new cell below; explain inserts a markdown note.
Test / typecheck
pnpm test # vitest — pure logic (notebook.ts, hanzo.ts, config.ts)
pnpm typecheck # tsc --noEmit
The JupyterLab widget APIs are integration-tested by running JupyterLab; the
unit tests cover the pure core: context assembly & truncation, traceback
extraction, the action-catalog prompt builders, and @hanzo/ai request shaping
(with a mocked client).
Publish
-
npm (the source package):
npm publish(publishConfig.accessispublic). -
PyPI (the prebuilt extension end users
pip install):pnpm build:prod pip install build twine python -m build # sdist + wheel with the bundled labextension twine upload dist/*
License
MIT