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.3.tar.gz (21.6 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.3-py3-none-any.whl (22.6 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: jupyter_cli-0.1.3.tar.gz
  • Upload date:
  • Size: 21.6 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.3.tar.gz
Algorithm Hash digest
SHA256 de31b502ade2895805a6d6a255eedcdb49fe4101fb661a275aff6d1bd33d3d21
MD5 fba573818a302e64bd90e54ada7eacc6
BLAKE2b-256 6a35206ac58e38cbe8471277778004979db9d234298eee41f357c16d58ae9f8d

See more details on using hashes here.

File details

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

File metadata

  • Download URL: jupyter_cli-0.1.3-py3-none-any.whl
  • Upload date:
  • Size: 22.6 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.3-py3-none-any.whl
Algorithm Hash digest
SHA256 91cde833193fdc4655510296541602a6c3c72c81acb291d455e8ae382d75d54c
MD5 890cc55108c9de66868463ee1e5301f3
BLAKE2b-256 631d4c52fd3f70c1360997e7feb191c9b7d3c7038fc62044ab6443812c2623d4

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