# nb - Notebook CLI
A fast, command-line interface for working with Jupyter notebooks. Designed for both humans and AI agents, with human-readable text output by default and JSON output available for programmatic use. Enables reliable notebook manipulation without opening a browser.
[](LICENSE)
[](https://www.rust-lang.org)
## Installation
### Quick Install
```bash
This installs the binary to `~/.nb-cli/bin/nb`. Follow the instructions to add it to your PATH.
**Note**: If you get an error while installation, where your platform is not supported, please use `cargo install` or build from source.
### Install from crates.io
```bash
cargo install nb-cli
```
### Build from Source
```bash
git clone https://github.com/jupyter-ai-contrib/nb-cli.git
cd nb-cli
cargo build --release
```
The binary will be available at `target/release/nb`.
## AI Agent Integration
To enable AI agents (like Claude Code) to work seamlessly with Jupyter notebooks using `nb`:
### Install the Skill
**Option 1: Using the Vercel Skills Tool (Recommended)**
```bash
npx skills install jupyter-ai-contrib/nb-cli
```
**Option 2: Manual Installation**
Copy the skill directory to your agent's skill location:
- **Claude Code/Cline**: `~/.claude/skills/notebook-cli/` or `~/.cline/skills/notebook-cli/`
- **Other agents**: Consult your agent's documentation for the skills directory
```bash
# Example for Claude Code
mkdir -p ~/.claude/skills/notebook-cli
cp -r skills/notebook-cli/* ~/.claude/skills/notebook-cli/
```
### Configure Your Agent
Add the following instruction to your project's agent configuration file (`CLAUDE.md`, `AGENTS.md`, `.cursorrules`, etc.):
```markdown
## Working with Notebooks (.ipynb files)
When the user asks to read, edit, execute, or work with .ipynb files, use the notebook-cli skill, which provides the `nb` command-line tool. Do not use the built-in Read/Write tools for `.ipynb` files.
```
This ensures your AI agent uses the `nb` CLI for all notebook operations instead of attempting to parse JSON directly.
## Quick Start
```bash
# Create and build a notebook
nb create analysis.ipynb
nb cell add analysis.ipynb --source "import pandas as pd"
nb cell add analysis.ipynb --source "# Analysis" --type markdown
nb read analysis.ipynb
# Execute and view results
nb execute analysis.ipynb
nb read analysis.ipynb --with-outputs
```
## Local Mode
**Default behavior. Operations directly modify `.ipynb` files.**
Local mode lets you create, edit, execute, and query notebooks on disk without any server running. All changes are written directly to the `.ipynb` file.
```bash
# Create and edit
nb create notebook.ipynb
nb cell add notebook.ipynb --source "x = 1 + 1"
nb cell update notebook.ipynb --cell-index 0 --source "x = 2 + 2"
# Read and search
nb read notebook.ipynb # View structure
nb read notebook.ipynb --cell-index 0 # View specific cell
nb search notebook.ipynb "import" # Find patterns
nb search notebook.ipynb --with-errors # Find cells with errors
# Execute locally (native Rust implementation)
nb execute notebook.ipynb --cell-index 0 # Execute specific cell
nb execute notebook.ipynb # Execute all cells
```
**Note**: Local execution requires a Jupyter kernel to be installed (e.g., `pip install ipykernel` for Python). The CLI communicates directly with kernels via ZeroMQ using native Rust.
## Remote Mode
**Connect to a running JupyterLab server for real-time synchronization.**
When you connect to a Jupyter server, the CLI uses Y.js for conflict-free real-time updates. Changes appear instantly in your open JupyterLab tabs, and you can execute code using the server's kernel.
### Connect to a Server
**Auto-detection (recommended):**
```bash
nb connect
```
Automatically finds running Jupyter servers, validates them, and connects. If multiple servers are found, you'll get an interactive prompt to choose one.
**Manual connection:**
```bash
nb connect --server http://localhost:8888 --token your-jupyter-token
```
**Connection options:**
- `--server`: Server URL (e.g., `http://localhost:8888`)
- `--token`: Authentication token from Jupyter
### Connection Persistence
Connection info is saved in `.jupyter/cli.json` in the current directory. All subsequent commands automatically use this connection until you disconnect or change directories.
```bash
# Connect once (auto-detect)
nb connect
# Future commands use saved connection
nb cell add notebook.ipynb --source "df.head()"
nb cell execute notebook.ipynb --cell f9l030
# Check current connection
nb status
# Disconnect when done
nb disconnect
```
**How it works**: When connected, the CLI always uses Y.js for real-time collaborative editing. Changes sync instantly if the notebook is open in JupyterLab, or will appear when you open it later.
### Remote Mode Examples
```bash
# Connect automatically
nb connect
# Add cell - appears instantly in JupyterLab
nb cell add experiment.ipynb --source "df.describe()"
# Update cell in real-time
nb cell update experiment.ipynb --cell-index 0 --append "\nprint('done')"
# Execute via remote kernel
nb execute experiment.ipynb --cell-index 0
# Disconnect when switching projects
nb disconnect
```
## Commands
| `nb create <path>` | Create a new notebook |
| `nb read <path>` | Read notebook cells and metadata |
| `nb execute <path>` | Execute cells in notebook |
| `nb search <path> <pattern>` | Search text and errors in notebook cells |
| `nb cell add <path> --source <code>` | Add a new cell |
| `nb cell update <path> --cell-index <index>` | Update an existing cell |
| `nb cell delete <path> --cell-index <index>` | Delete a cell |
| `nb execute <path> --cell-index <index>` | Execute a specific cell |
| `nb output clear <path>` | Clear cell outputs |
| `nb connect [--server URL --token TOKEN]` | Connect to Jupyter server (auto-detects if no args) |
| `nb status` | Show current connection status |
| `nb disconnect` | Disconnect from server |
Use `--help` with any command for full details and options.
## Key Features
### Cell Referencing
Two ways to reference cells:
- **Index**: `--cell-index 0` or `-i 0` (position-based, supports negative indexing: `-1` = last cell)
- **ID**: `--cell "my-cell"` or `-c "my-cell"` (stable, doesn't change when cells move)
### Output Format
Control output format for better integration with your workflow:
- **Text** (default): Human-readable for terminal viewing and debugging
- **JSON** (`--json`): Structured, nbformat-compliant for programmatic use and AI agents
```bash
# Default text output
nb read notebook.ipynb
# JSON output for programmatic use
nb read notebook.ipynb --json
```
### Multi-line Code
Escape sequences are automatically interpreted:
```bash
# Add cell with proper formatting
nb cell add notebook.ipynb \
--source 'def hello():\n print("world")\n\nhello()'
# Append to existing cell
nb cell update notebook.ipynb --cell 0 \
--append '\n# Added comment\nprint("more")'
```
## Common Workflows
**Build notebook programmatically:**
```bash
nb create analysis.ipynb --template basic
nb cell add analysis.ipynb --source "import pandas as pd"
nb cell add analysis.ipynb --source "# Analysis" --type markdown
nb execute analysis.ipynb
```
**Debug and fix cells:**
```bash
# Find problematic cells
nb search notebook.ipynb --with-errors
# Inspect specific cell with outputs
nb read notebook.ipynb --cell-index 5 --with-outputs
# Fix the cell
nb cell update notebook.ipynb --cell-index 5 --source "fixed code"
# Re-execute
nb execute notebook.ipynb --cell-index 5
```
**Extract specific content:**
```bash
nb read notebook.ipynb --only-code # All code cells
nb read notebook.ipynb --only-markdown # All markdown
nb read notebook.ipynb --cell-index -1 # Last cell
```
**For AI agents:**
```bash
# Analyze all code in a notebook
nb read notebook.ipynb --only-code
# Find cells with errors
nb search notebook.ipynb --with-errors
# Add analysis cell and execute
nb cell add experiment.ipynb --source "df.describe()"
nb execute experiment.ipynb --cell-index -1
```
## Examples
See `examples/` directory for sample notebooks demonstrating various cell types and outputs.
## License
[BSD-3-Clause](LICENSE)