> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.conductorquantum.com/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.conductorquantum.com/_mcp/server.

# stanza.jupyter.core



## Module Contents

### Classes

| Name | Description |
|------|-------------|
| [`ServerState`](#stanzajupytercoreserverstate) | Persistent Jupyter server state stored on disk. |
| [`ServerStatus`](#stanzajupytercoreserverstatus) | Runtime Jupyter server status with calculated uptime. |
| [`RuntimeInfo`](#stanzajupytercoreruntimeinfo) | Jupyter runtime information parsed from jpserver-\{pid\}.json. |
| [`SessionInfo`](#stanzajupytercoresessioninfo) | Active Jupyter notebook session with log file metadata. |
| [`Config`](#stanzajupytercoreconfig) | Configuration for Jupyter server management. |
| [`_FileLock`](#stanzajupytercore_filelock) | File-based lock for preventing concurrent Jupyter server operations. |

### Functions

| Name | Description |
|------|-------------|
| [`_read_state`](#stanzajupytercore_read_state) | Read the Jupyter server state from disk. |
| [`_write_state`](#stanzajupytercore_write_state) | Write the Jupyter server state to disk atomically with secure permissions. |
| [`_clear_state`](#stanzajupytercore_clear_state) | Delete the server state file and log files, ignoring errors. |
| [`_is_alive`](#stanzajupytercore_is_alive) | Check if a process with the given PID is running. |
| [`_open_logs`](#stanzajupytercore_open_logs) | Open stdout and stderr log files, truncating if they exceed max size. |
| [`_discover_runtime`](#stanzajupytercore_discover_runtime) | Discover Jupyter runtime information by polling for jpserver-\{pid\}.json. |
| [`_shutdown`](#stanzajupytercore_shutdown) | Gracefully shutdown Jupyter server via REST API. |
| [`_kill`](#stanzajupytercore_kill) | Terminate Jupyter server process with SIGTERM. |
| [`_force_kill`](#stanzajupytercore_force_kill) | Force kill Jupyter server process with SIGKILL. |
| [`_api_request`](#stanzajupytercore_api_request) | Make authenticated request to Jupyter API. |
| [`_setup_ipython_startup`](#stanzajupytercore_setup_ipython_startup) | Copy auto-logging startup script to stanza's IPython configuration directory. |
| [`start`](#stanzajupytercorestart) | Start a Jupyter server in the background with auto-logging enabled. |
| [`stop`](#stanzajupytercorestop) | Stop the Jupyter server using escalating shutdown strategies. |
| [`status`](#stanzajupytercorestatus) | Get the current Jupyter server status including uptime. |
| [`list_sessions`](#stanzajupytercorelist_sessions) | List active notebook sessions with log metadata. |
| [`kill_kernel`](#stanzajupytercorekill_kernel) | Kill kernel for notebook via Jupyter API. |

### Data

`_config`

### API

```python
class stanza.jupyter.core.ServerState
```

Persistent Jupyter server state stored on disk.

Attributes:
    pid: Process ID of the Jupyter server
    url: Full URL with token for accessing JupyterLab
    started_at: ISO 8601 timestamp when server was started
    root_dir: Absolute path to the notebook root directory

```python
pid: int
```

**Value**: `None`


```python
url: str
```

**Value**: `None`


```python
started_at: str
```

**Value**: `None`


```python
root_dir: str
```

**Value**: `None`


```python
class stanza.jupyter.core.ServerStatus
```

Runtime Jupyter server status with calculated uptime.

Attributes:
    pid: Process ID of the running Jupyter server
    url: Full URL with token for accessing JupyterLab
    uptime_seconds: Number of seconds the server has been running
    root_dir: Absolute path to the notebook root directory

```python
pid: int
```

**Value**: `None`


```python
url: str
```

**Value**: `None`


```python
uptime_seconds: float
```

**Value**: `None`


```python
root_dir: str
```

**Value**: `None`


```python
class stanza.jupyter.core.RuntimeInfo
```

Jupyter runtime information parsed from jpserver-\{pid\}.json.

Attributes:
    url: JupyterLab URL with authentication token
    token: Authentication token for API requests
    port: Port number the server is listening on
    runtime_file: Path to the Jupyter runtime JSON file

```python
url: str
```

**Value**: `None`


```python
token: str
```

**Value**: `None`


```python
port: int
```

**Value**: `None`


```python
runtime_file: str
```

**Value**: `None`


```python
class stanza.jupyter.core.SessionInfo
```

Active Jupyter notebook session with log file metadata.

Attributes:
    notebook_path: Absolute path to the notebook file
    log_path: Absolute path to the notebook's log file
    size_bytes: Size of the log file in bytes
    line_count: Number of lines in the log file

```python
notebook_path: str
```

**Value**: `None`


```python
log_path: str
```

**Value**: `None`


```python
size_bytes: int
```

**Value**: `None`


```python
line_count: int
```

**Value**: `None`


```python
class stanza.jupyter.core.Config
```

Configuration for Jupyter server management.

Attributes:
    state_dir: Directory for storing server state and logs
    log_max_size: Maximum log file size in bytes before truncation

```python
state_dir: pathlib.Path
```

**Value**: `Path(...)`


```python
log_max_size: int
```

**Value**: `None`


```python
state_file: pathlib.Path
```

Path to the server state JSON file.


```python
lock_file: pathlib.Path
```

Path to the file lock for preventing concurrent operations.


```python
stdout_log: pathlib.Path
```

Path to the Jupyter server stdout log.


```python
stderr_log: pathlib.Path
```

Path to the Jupyter server stderr log.


```python
ipython_dir: pathlib.Path
```

Path to stanza's managed IPython configuration directory.


```python
ipython_startup_dir: pathlib.Path
```

Path to IPython startup scripts directory for auto-logging.


```python
stanza.jupyter.core._config
```

**Value**: `Config(...)`


```python
stanza.jupyter.core._read_state() -> stanza.jupyter.core.ServerState | None
```

Read the Jupyter server state from disk.

**Returns:**

ServerState if state file exists and is valid, None otherwise


```python
stanza.jupyter.core._write_state(state: stanza.jupyter.core.ServerState) -> None
```

Write the Jupyter server state to disk atomically with secure permissions.

Uses a temporary file and atomic rename to prevent corruption. Sets file
permissions to 0o600 (owner read/write only) for security.

**Parameters:**

<ParamField path="state" type="stanza.jupyter.core.ServerState">
  ServerState to persist to disk
</ParamField>


```python
stanza.jupyter.core._clear_state() -> None
```

Delete the server state file and log files, ignoring errors.


```python
stanza.jupyter.core._is_alive(pid: int) -> bool
```

Check if a process with the given PID is running.

**Parameters:**

<ParamField path="pid" type="int">
  Process ID to check
</ParamField>

**Returns:**

True if process is running, False otherwise


```python
class stanza.jupyter.core._FileLock(lock_file: pathlib.Path, timeout: float = 5.0)
```

File-based lock for preventing concurrent Jupyter server operations.

Uses fcntl.flock for process-level locking to ensure only one stanza
process can modify the Jupyter server state at a time.

### Initialization

Initialize lock with the lock file path and acquisition timeout.

**Parameters:**

**Parameters:**

- **lock_file**: Path to the lock file
- **timeout**: Maximum seconds to wait for lock acquisition


```python
__enter__() -> stanza.jupyter.core._FileLock
```

Acquire exclusive lock, blocking until available or timeout.

**Returns:**

Self for context manager usage

**Raises:**

RuntimeError: If lock cannot be acquired within timeout period


```python
__exit__(
    exc_type: typing.Any,
    exc_val: typing.Any,
    exc_tb: typing.Any
) -> None
```

Release lock and close file descriptor.


```python
stanza.jupyter.core._open_logs(tail_bytes: int = 50000) -> tuple[typing.TextIO, typing.TextIO]
```

Open stdout and stderr log files, truncating if they exceed max size.

If a log file exceeds log_max_size, it is truncated to keep only the last
tail_bytes with a marker indicating truncation occurred.

**Parameters:**

<ParamField path="tail_bytes" type="int" default="50000">
  Number of bytes to preserve when truncating logs
</ParamField>

**Returns:**

Tuple of (stdout_file, stderr_file) opened in append mode


```python
stanza.jupyter.core._discover_runtime(
    pid: int,
    timeout: float = 10.0,
    poll_interval: float = 0.2
) -> stanza.jupyter.core.RuntimeInfo
```

Discover Jupyter runtime information by polling for jpserver-\{pid\}.json.

Waits for Jupyter to write its runtime file containing the server URL, token,
and port. Constructs a JupyterLab URL with authentication token.

**Parameters:**

<ParamField path="pid" type="int">
  Process ID of the Jupyter server
</ParamField>

<ParamField path="timeout" type="float" default="10.0">
  Maximum seconds to wait for runtime file
</ParamField>

<ParamField path="poll_interval" type="float" default="0.2">
  Seconds between file existence checks
</ParamField>

**Returns:**

RuntimeInfo containing server URL, token, port, and runtime file path

**Raises:**

RuntimeError: If runtime file is not found within timeout period


```python
stanza.jupyter.core._shutdown(
    state: stanza.jupyter.core.ServerState,
    timeout: float = 5.0,
    poll_interval: float = 0.2
) -> None
```

Gracefully shutdown Jupyter server via REST API.

Sends a shutdown request to the Jupyter server using the authentication token,
then polls until the process terminates or timeout is reached.

**Parameters:**

<ParamField path="state" type="stanza.jupyter.core.ServerState">
  Server state containing URL and PID
</ParamField>

<ParamField path="timeout" type="float" default="5.0">
  Maximum seconds to wait for shutdown
</ParamField>

<ParamField path="poll_interval" type="float" default="0.2">
  Seconds between process aliveness checks
</ParamField>


```python
stanza.jupyter.core._kill(
    pid: int,
    timeout: float = 5.0,
    poll_interval: float = 0.2
) -> None
```

Terminate Jupyter server process with SIGTERM.

Sends SIGTERM signal and waits for process to exit gracefully.

**Parameters:**

<ParamField path="pid" type="int">
  Process ID to terminate
</ParamField>

<ParamField path="timeout" type="float" default="5.0">
  Maximum seconds to wait for termination
</ParamField>

<ParamField path="poll_interval" type="float" default="0.2">
  Seconds between process aliveness checks
</ParamField>


```python
stanza.jupyter.core._force_kill(pid: int) -> None
```

Force kill Jupyter server process with SIGKILL.

**Parameters:**

<ParamField path="pid" type="int">
  Process ID to force kill
</ParamField>


```python
stanza.jupyter.core._api_request(
    state: stanza.jupyter.core.ServerState, endpoint: str
) -> typing.Any
```

Make authenticated request to Jupyter API.

**Parameters:**

<ParamField path="state" type="stanza.jupyter.core.ServerState">
  Server state containing URL with token
</ParamField>

<ParamField path="endpoint" type="str">
  API endpoint path (e.g., "api/sessions")
</ParamField>

**Returns:**

JSON response from the API

**Raises:**

requests.HTTPError: If the request fails


```python
stanza.jupyter.core._setup_ipython_startup() -> None
```

Copy auto-logging startup script to stanza's IPython configuration directory.

**Raises:**

RuntimeError: If the startup script cannot be found


```python
stanza.jupyter.core.start(
    notebook_dir: pathlib.Path,
    port: int = 8888,
    startup_wait: float = 0.5
) -> dict[str, typing.Any]
```

Start a Jupyter server in the background with auto-logging enabled.

Launches jupyter_server as a detached process, discovers its runtime information,
and saves the state to disk. Configures IPYTHONDIR to enable automatic cell
output logging to notebook_name.log files.

**Parameters:**

<ParamField path="notebook_dir" type="pathlib.Path">
  Root directory for notebooks
</ParamField>

<ParamField path="port" type="int" default="8888">
  Port number for the server (default: 8888)
</ParamField>

<ParamField path="startup_wait" type="float" default="0.5">
  Seconds to wait before checking if server started successfully
</ParamField>

**Returns:**

Dictionary with keys: pid, url, started_at, root_dir

**Raises:**

RuntimeError: If server is already running or fails to start


```python
stanza.jupyter.core.stop() -> None
```

Stop the Jupyter server using escalating shutdown strategies.

Attempts graceful shutdown via REST API, then SIGTERM, then SIGKILL if necessary.
Cleans up state files when complete. Safe to call even if no server is running.


```python
stanza.jupyter.core.status() -> dict[str, typing.Any] | None
```

Get the current Jupyter server status including uptime.

**Returns:**

Dictionary with keys: pid, url, uptime_seconds, root_dir.
None if no server is running or state is stale.


```python
stanza.jupyter.core.list_sessions() -> list[dict[str, typing.Any]]
```

List active notebook sessions with log metadata.

**Returns:**

List of dictionaries, each containing: notebook_path, log_path,
size_bytes, line_count. Empty list if no server is running.


```python
stanza.jupyter.core.kill_kernel(notebook_name: str) -> None
```

Kill kernel for notebook via Jupyter API.

**Parameters:**

<ParamField path="notebook_name" type="str">
  Name of the notebook (case-insensitive substring match)
</ParamField>

**Raises:**

RuntimeError: If no server is running, notebook not found, or API call fails