Skip to main content

Programmatic Jupyter cell execution with persistent kernels

Project description

jupyter-cli

PyPI version Python 3.8+ License: MIT

Programmatic Jupyter notebook cell execution with persistent kernels.

The Problem

Existing Jupyter tools don't support selective cell execution with persistent state:

  • papermill/nbconvert/nbexec: Run entire notebooks
  • jupyter console: Requires manual interaction
  • nbclient: Kernel dies when Python process exits

jupyter-cli fills this gap: execute specific cells while keeping kernel state alive between CLI invocations.

Use Case

A data science notebook with ~60 cells:

  • Cells 1-49: Expensive setup (DB queries, model training) - takes ~20 minutes
  • Cells 50+: Experimental iterations

With jupyter-cli:

jupyter-cli start notebook.ipynb
jupyter-cli exec notebook.ipynb 0 1 2 ... 49  # Run setup once
jupyter-cli exec notebook.ipynb 50            # Iterate on cell 50
jupyter-cli exec notebook.ipynb 50            # Again, without re-running setup
jupyter-cli stop notebook.ipynb

Installation

pip install jupyter-cli

# Or from source
git clone https://github.com/andrewting19/jupyter-cli.git
cd jupyter-cli
pip install -e .

Requirements:

  • Python 3.8+
  • jupyter_client
  • nbformat
  • click

Quick Start

# Start a persistent kernel
jupyter-cli start notebook.ipynb

# Execute cells (0-indexed)
jupyter-cli exec notebook.ipynb 0 1 2

# Stop the kernel
jupyter-cli stop notebook.ipynb

Commands

Kernel Management

Command Description
start <notebook> Start persistent kernel
stop <notebook> Stop kernel
stop --all Stop all kernels
status [notebook] Check kernel status

Cell Execution

Command Description
exec <notebook> <cells...> Execute specific cells
exec <notebook> 0 1 2 --timeout 300 With custom timeout
exec <notebook> 0 --quiet Suppress output

Notebook Exploration

Command Description
list <notebook> List all cells with preview
list <notebook> --code Only code cells
list <notebook> --range 0-10 Cell range
read <notebook> 0 1 2 Read full cell source
read <notebook> --code Read all code cells
search <notebook> "pattern" Search cells
search <notebook> "regex" -r Regex search
outputs <notebook> 5 Read stored outputs
info <notebook> Notebook info

Examples

Exploring a Notebook

# Quick overview
$ jupyter-cli list notebook.ipynb
[0] code: import pandas as pd
[1] code: df = pd.read_csv('data.csv')
[2] code: df.head()
[3] markdown: ## Data Cleaning
[4] code: df = df.dropna()
...

# Find all cells using DataFrame
$ jupyter-cli search notebook.ipynb "DataFrame"
Found 3 match(es):
[5] code: df = pd.DataFrame(data)
[12] code: result = DataFrame.from_dict(...)
[45] code: final_df = pd.DataFrame(results)

# Read specific cells
$ jupyter-cli read notebook.ipynb 5 12
=== Cell 5 (code) ===
df = pd.DataFrame(data)
print(df.shape)

=== Cell 12 (code) ===
result = DataFrame.from_dict(processed_data)

Selective Execution

# Start kernel
$ jupyter-cli start analysis.ipynb
Kernel started. ID: abc123

# Run expensive setup
$ jupyter-cli exec analysis.ipynb 0 1 2 3 4 5
[Cell 0] Executing: import pandas as pd...
[Cell 1] Executing: df = load_data()...
Loading 1M rows from database...
...

# Iterate on experiment cell
$ jupyter-cli exec analysis.ipynb 50
[Cell 50] Executing: model.fit(X, y)...
Accuracy: 0.85

# Edit cell 50 in your editor, then re-run
$ jupyter-cli exec analysis.ipynb 50
[Cell 50] Executing: model.fit(X, y, epochs=100)...
Accuracy: 0.92

# Clean up
$ jupyter-cli stop analysis.ipynb
Kernel stopped.

Reading Previous Outputs

$ jupyter-cli outputs notebook.ipynb --range 10-15
=== Cell 10 output ===
[stdout] Training model...
[stdout] Epoch 1/10: loss=0.5

=== Cell 12 output ===
[result] 0.923456

=== Cell 14 output ===
[error] ValueError: invalid shape

Gap Analysis: CLI vs Manual Jupyter

Feature jupyter-cli Manual Jupyter UI
Cell execution Yes Yes
Persistent kernel Yes Yes
Execute specific cells Yes Yes
State persistence Yes Yes
stdout/stderr output Yes Yes
Rich output (HTML) Truncated Full rendering
Image output [Image: PNG] Displayed
Interactive widgets No Yes
Cell editing No (use external editor) Yes
Magic commands Yes (via kernel) Yes
Auto-complete No Yes
Inline plots No (shows placeholder) Yes
Syntax highlighting No Yes
Variable inspector No Extension available
Debugging No Yes
Multiple kernels Yes (one per notebook) Yes

Key takeaway: jupyter-cli is for programmatic automation, not interactive development. Use it when you need:

  • Scripted notebook execution
  • LLM agent integration
  • CI/CD pipelines
  • Selective cell re-execution without re-running setup

Architecture

┌─────────────┐     ┌──────────────────┐     ┌────────────┐
│  CLI Client │────▶│  Daemon Process  │────▶│   Kernel   │
└─────────────┘     └──────────────────┘     └────────────┘
      │                     │                       │
      │  connection.json    │  keeps alive          │  Python
      │◀────────────────────│                       │  process
      │                     │                       │
      └─────────────────────┴───────────────────────┘
  1. Daemon Process: Starts kernel, keeps it alive, writes connection file
  2. CLI Client: Reads notebook, connects to kernel via connection file, executes cells

For LLM Agents

See CLAUDE.md for a comprehensive guide on using jupyter-cli with LLM agents, including:

  • Token-efficient exploration strategies
  • Common workflows
  • Best practices

Claude Code Skill

If you're using Claude Code, you can install the jupyter-cli skill to teach Claude how to use this tool:

# Install the skill (interactive prompt for global vs local)
jupyter-cli install-skill

# Or specify directly:
jupyter-cli install-skill --global   # Available in all projects
jupyter-cli install-skill --local    # Current directory only

After installation, restart Claude Code. The skill will:

  • Automatically activate when working with Jupyter notebooks
  • Be available via /jupyter-cli command
  • Teach Claude the proper commands and best practices

Development

# Install with dev dependencies
pip install -e ".[dev]"

# Run tests
pytest tests/ -v

# Run specific test class
pytest tests/test_jupyter_cli.py::TestCLIExec -v

License

MIT

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_cli-0.1.4.tar.gz (21.9 kB view details)

Uploaded Source

Built Distribution

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

jupyter_cli-0.1.4-py3-none-any.whl (22.8 kB view details)

Uploaded Python 3

File details

Details for the file jupyter_cli-0.1.4.tar.gz.

File metadata

  • Download URL: jupyter_cli-0.1.4.tar.gz
  • Upload date:
  • Size: 21.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.11

File hashes

Hashes for jupyter_cli-0.1.4.tar.gz
Algorithm Hash digest
SHA256 edba8a1d91bc45fc6cc884e70824343c2c90d43173a36a4d5c519b324d8ab92b
MD5 4a75a1c58bf3aa2843fea95bb36a94f8
BLAKE2b-256 657e135899f683a72793858226cc185f5d4b16509453d1cf1890a585ad87ea16

See more details on using hashes here.

File details

Details for the file jupyter_cli-0.1.4-py3-none-any.whl.

File metadata

  • Download URL: jupyter_cli-0.1.4-py3-none-any.whl
  • Upload date:
  • Size: 22.8 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.11

File hashes

Hashes for jupyter_cli-0.1.4-py3-none-any.whl
Algorithm Hash digest
SHA256 06ea1369e2262c68aa399e48d5b810a7979aca35e110db0a56767b0c487981e2
MD5 11c2165cbcbbc0ac22731cdf16bcc5cb
BLAKE2b-256 26254462a8dcf7d798eb7cc443e13dcc1eeeca1d94de5cbb2c81e2458c388977

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