Skip to main content

jupyterlab-codex

A JupyterLab 4 extension that adds an OpenAI Codex chat panel to the left sidebar. The OpenAI mark serves as the sidebar tab icon.

Scope: notebook copilot, not project agent

This is a deliberately small tool. The agent can only:

  • list variables in your notebook kernel
  • describe a pandas DataFrame
  • run short Python snippets in the kernel
  • read the source / outputs of a selected cell or a cell by execution count
  • insert (and optionally run) a new code cell below the active one

That's the complete tool surface. No filesystem read/write. No shell. No MCP. No project-wide context. The agent sees what's in your kernel and your active notebook — nothing else.

This is a feature, not a limitation. Claude Code, Cursor, and the Codex CLI itself are excellent project agents — they edit files, run tests, manage git. Use them for that. jupyterlab-codex is for the inner loop inside a notebook: explain this cell, evaluate this model, describe this DataFrame, write the next cell. It runs where your exploratory work already lives, with zero context-switch and a live view of kernel state.

If you find yourself wishing it could grep your repo, that's a sign you want a different tool — and you almost certainly already have one open in another window.

Authentication uses the user's ChatGPT subscription via OAuth (the same flow the Codex CLI uses). Tokens live in localStorage and are forwarded to a small proxy that talks to the Codex Responses API.

Tested in JupyterLab 4 and JupyterLite. Notebook 7 should work — file an issue if it doesn't.

Two deployment modes

The extension needs a proxy because both chatgpt.com/backend-api/codex/responses and auth.openai.com reject browser fetches from arbitrary origins. Where the proxy lives depends on how you're running JupyterLab.

Classic JupyterLab — bundled, no external infra

pip install jupyter-codex ships a Tornado server extension that proxies to OpenAI from same-origin. The browser fetches /codex and /codex/device/... on whichever host the Jupyter server is exposed on — no CORS, no third-party services.

pip install jupyter-codex        # (or pip install -e . for dev)
jupyter lab

Open the OpenAI mark in the left sidebar and click Sign in with ChatGPT. That's it.

Setting Default Notes
codexProxyUrl codex Resolved against the Jupyter base URL → <base>/codex
codexModel gpt-5.3-codex Must be a model your ChatGPT account is entitled to

The bundled handlers live under the Jupyter base_url:

POST  <base>/codex                  → forwards Responses API call upstream
POST  <base>/codex/device/start     → request a device code
POST  <base>/codex/device/poll      → poll for completion + token exchange
POST  <base>/codex/refresh          → rotate the refresh_token

JupyterLite — external proxy required

In JupyterLite there is no Python server (the kernel runs in Pyodide, the page is static). The Python package isn't installed, so the bundled proxy can't run. Host a proxy out-of-band and override codexProxyUrl to point at it.

The bundled jupyter_codex/handlers.py is itself a reference implementation — port it to whichever runtime you prefer (Netlify Function, Cloudflare Worker, AWS Lambda, a small FastAPI service). Any proxy works as long as it exposes the same four routes:

POST  <proxy>                       → forwards Responses API call upstream
POST  <proxy>/device/start
POST  <proxy>/device/poll
POST  <proxy>/refresh

Then in Settings → jupyterlab-codex set codexProxyUrl to the proxy URL (e.g. /.netlify/functions/codex if the proxy is co-hosted on the lite site, or https://my-proxy.example.com/codex if it's elsewhere).

URL resolution

codexProxyUrl is interpreted as follows:

Value Resolved to
"codex" (default) <jupyter-base-url>/codex
"/foo/bar" /foo/bar (absolute path on current origin)
"https://x.com/y" used as-is
"" <jupyter-base-url>/codex

This lets the same default work in classic Lab (hits the bundled server extension), single-user JupyterHub (<base> becomes /user/<name>/), and JupyterLite (user picks an absolute path or a full URL).

Install for development

pip install -e ".[dev]"
jupyter labextension develop . --overwrite
jlpm build

jlpm watch rebuilds the labextension on change; refresh Lab to pick up TypeScript changes.

Project layout

src/
  index.ts              # plugin entry point — registers the sidebar
  widget.ts             # Lumino widget — chat UI + sign-in flow
  icon.ts               # OpenAI mark for the sidebar tab
  kernelRpc.ts          # run-Python + sentinel-parsing primitive
  agent/
    client.ts           # tool-use loop driver
    codexAuth.ts        # localStorage auth + device-code login
    codexProvider.ts    # Codex Responses API client (Anthropic-shape adapter)
    proxyUrl.ts         # codexProxyUrl resolution helper
    tools.ts            # kernel-side tool schemas + Python prelude
    toolRunner.ts       # injects prelude, parses sentinel-wrapped JSON
    frontendTools.ts    # browser-side tools (insert_cell, get_cell_context, …)
    transcriptStore.ts  # persists chat to .jupyterlab-codex-chat.json
    markdown.ts         # tiny markdown → HTML renderer
schema/plugin.json      # ISettingRegistry schema
style/                  # sidebar + chat CSS, OpenAI SVG mark
jupyter_codex/         # Python distribution name on PyPI: jupyter-codex
  __init__.py           # labextension paths + server-extension entry points
  handlers.py           # Tornado proxy: /codex, /codex/device/*, /codex/refresh
jupyter-config/         # auto-enables the server extension on install

Metadata

Release files for jupyter_codex 0.1.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for jupyter_codex 0.1.1
File Size Uploaded
jupyter_codex-0.1.1.tar.gz 113.4 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for jupyter_codex 0.1.1
File Interpreter ABI Platform
jupyter_codex-0.1.1-py3-none-any.whl Python 3 none any Details

Total release size: 148.8 kB

Release files / jupyter_codex-0.1.1.tar.gz

Download URL jupyter_codex-0.1.1.tar.gz
Size 113.4 kB
Tags Source
SHA-256 checksum
How to use checksums
8156b0771f471bf2bc715d010a9f5d336109e7c8662c8f095b9d68c368fd2666
BLAKE2b-256 checksum
How to use checksums
f2a33fb5f4d1f160faab1322b6e1166134a62cecc8fb99f7b552c1bf1465b4f0
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.9.7

Release files / jupyter_codex-0.1.1-py3-none-any.whl

Download URL jupyter_codex-0.1.1-py3-none-any.whl
Size 35.4 kB
Tags Python 3
SHA-256 checksum
How to use checksums
461130b822e85b72b99b888bc15577548e99d3487089a42dbb87c2bdea9e633c
BLAKE2b-256 checksum
How to use checksums
84a162924a5b09ccba2c81b306b0f9c24f00cafa87a1148069fb9ea4135b4932
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.9.7

Release history Release notifications | RSS feed

This release

0.1.1 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page