jupyterlab_kernel_terminal_workspace_culler_extension
[!TIP] This extension is part of the stellars_jupyterlab_extensions metapackage. Install all Stellars extensions at once:
pip install stellars_jupyterlab_extensions
Automatically cull idle kernels, terminals, and workspaces after configurable timeout periods. Helps manage system resources by cleaning up unused resources that accumulate during long JupyterLab usage.
Features
- Idle kernel culling - Shut down kernels idle beyond timeout (checks
execution_stateandlast_activity) - Idle terminal culling - Close terminals with no WebSocket activity beyond timeout
- Workspace culling - Remove stale JupyterLab workspaces (auto-0, auto-k, etc.) based on last modified time
- Configurable timeouts - All timeouts adjustable via JupyterLab Settings
- Notifications - Optional toast notifications when resources are culled (requires
jupyterlab-notifications) - Server-side detection - Uses tornado PeriodicCallback for accurate activity tracking
Default Settings
| Setting | Default | Description |
|---|---|---|
| Kernel timeout | 60 min (1 hour) | Idle kernels culled after this period |
| Terminal timeout | 60 min (1 hour) | Inactive terminals culled after this period |
| Disconnected only | enabled | Only cull terminals with no open browser tab |
| Workspace culling | enabled | Cull stale workspaces (default workspace protected) |
| Workspace timeout | 10080 min (7 days) | Stale workspaces culled after this period |
| Check interval | 5 min | How often the culler checks for idle resources |
| Notifications | enabled | Show notification when resources are culled |
How Idle Detection Works
Kernels: Checked for execution_state (busy kernels are never culled) and last_activity timestamp. A kernel is idle when it's not executing and hasn't had activity beyond the timeout.
Terminals: A terminal referenced by any existing workspace is never culled - the workspace must be culled first, which releases its terminals unless another surviving workspace still references them (the cascade). Beyond that, only terminals with no active browser tab are culled by default (controlled by "Only Cull Disconnected Terminals" setting). When a terminal tab is open, it maintains a WebSocket connection and won't be culled regardless of idle time. Once the tab is closed or disconnected, the terminal becomes eligible for culling one full idle timeout later. A terminal counts as culled only once the server has actually removed it: a terminal whose shell has exited but whose pty is still held open by a surviving process is closed the way an end-of-file would have closed it, and a terminal that survives a cull anyway is attempted once and then left alone.
Workspaces: Based on the workspace file's last_modified timestamp. JupyterLab creates auto-named workspaces (auto-0, auto-k, etc.) when you open multiple windows. Only auto-named workspaces are culled - the default workspace and named workspaces are never culled. Culling a workspace releases the terminals it referenced, so they can be culled in the same pass (the cascade).
Note: Terminal culling signals the terminal's own shell, starting with SIGHUP and escalating through SIGINT and SIGTERM to SIGKILL if it does not exit. Processes started with
nohup,screenortmuxare detached from that shell and survive culling.
Installation
Requires JupyterLab 4.0.0 or higher.
pip install jupyterlab-kernel-terminal-workspace-culler-extension
Configuration
Open JupyterLab Settings (Settings -> Settings Editor) and search for "Resource Culler" to adjust timeouts and enable/disable culling for each resource type.
Logs
Culling actions are logged at INFO level with [Culler] prefix:
[Culler] CULLING KERNEL abc123 - idle 65.2 minutes (threshold: 60)
[Culler] Kernel abc123 culled successfully
[Culler] CULLING TERMINAL 1 - idle 62.1 minutes (threshold: 60)
[Culler] Terminal 1 culled successfully
Run JupyterLab with --log-level=INFO to see culling activity.
FAQ
Q: My long-running calculation was killed. How do I prevent this?
Two options:
- Increase timeout: Go to
Settings->Settings Editor->Resource Cullerand increase the kernel/terminal timeout - Use a terminal multiplexer: Run calculations inside
screenortmux- these survive terminal culling
# Using screen
screen -S mysession
python long_calculation.py
# Detach with Ctrl+A, D
# Using tmux
tmux new -s mysession
python long_calculation.py
# Detach with Ctrl+B, D
Q: Will closing my browser tab kill my running process?
For terminals: By default, terminals are only culled when the browser tab is closed (disconnected). After closing the tab, the terminal will be culled once the idle timeout expires. Foreground processes receive SIGHUP. Use nohup, screen, or tmux for processes that must survive.
For kernels: The kernel continues running. Activity is tracked server-side, so a busy kernel won't be culled even if the browser is closed.
Q: What happens to processes started with nohup?
They survive terminal culling. nohup makes processes ignore SIGHUP, which is the signal sent when a terminal closes.
Q: How do I disable culling entirely?
Go to Settings -> Settings Editor -> Resource Culler and uncheck "Enable Kernel Culling" and "Enable Terminal Culling".
Q: Can I see when resources were culled?
Yes. Run JupyterLab with --log-level=INFO to see [Culler] log messages. If you have jupyterlab-notifications installed, you'll also see toast notifications.
CLI
The extension includes a command-line tool for listing and culling resources from the terminal.
# Show help
jupyterlab_kernel_terminal_workspace_culler
# List all resources and their idle times
jupyterlab_kernel_terminal_workspace_culler list
# List as JSON
jupyterlab_kernel_terminal_workspace_culler list --json
# Show what would be culled (dry run)
jupyterlab_kernel_terminal_workspace_culler cull --dry-run
# Cull idle resources
jupyterlab_kernel_terminal_workspace_culler cull
# Cull and output as JSON
jupyterlab_kernel_terminal_workspace_culler cull --json
# Custom timeouts (minutes)
jupyterlab_kernel_terminal_workspace_culler cull --kernel-timeout 30 --terminal-timeout 120
# Cull workspaces idle > 1 minute (default is 7 days)
jupyterlab_kernel_terminal_workspace_culler cull --workspace-timeout 1
# Also cull terminals that still have an open browser tab (default: skip them)
jupyterlab_kernel_terminal_workspace_culler cull --include-connected
By default cull skips terminals with an open browser tab, matching the extension's disconnected-only behavior. Pass --include-connected to cull them anyway.
The CLI auto-discovers running Jupyter servers. You can also set environment variables:
JUPYTER_SERVER_URL- server URL (e.g.,http://localhost:8888/)JUPYTER_TOKEN- authentication token
Uninstall
pip uninstall jupyterlab-kernel-terminal-workspace-culler-extension
Release files for jupyterlab-kernel-terminal-workspace-culler-extension 1.0.25
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| jupyterlab_kernel_terminal_workspace_culler_extension-1.0.25.tar.gz | 1.6 MB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| jupyterlab_kernel_terminal_workspace_culler_extension-1.0.25-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 1.7 MB
Release files / jupyterlab_kernel_terminal_workspace_culler_extension-1.0.25.tar.gz
| Download URL | jupyterlab_kernel_terminal_workspace_culler_extension-1.0.25.tar.gz |
|---|---|
| Size | 1.6 MB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
4aacf78e7bc31142913dd500a589dc14571633c79bbff9253239141a31904cb3
|
|
BLAKE2b-256 checksum How to use checksums |
83c2ea4ba1208b2f9163a2351d2565901a5c2e89e97a711b2051a72c3ab9e569
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.15
|
Release files / jupyterlab_kernel_terminal_workspace_culler_extension-1.0.25-py3-none-any.whl
| Download URL | jupyterlab_kernel_terminal_workspace_culler_extension-1.0.25-py3-none-any.whl |
|---|---|
| Size | 50.0 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
8e7a21be93e1b2eb0f251c8e6c37af923898b0c4ccc2e25e4c2851394de2f223
|
|
BLAKE2b-256 checksum How to use checksums |
b9c801214439a1adc50d36cfb3a29b4c860288d2c32d28d4269d61463309d9db
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.15
|