# JupyterManager Cross-project Jupyter instance manager. Discovers, monitors, and controls JupyterLab instances across multiple projects on the same machine. ## The Problem You have multiple projects with Jupyter notebooks. Each runs its own JupyterLab server. Without coordination: - Projects fight over port 8888 - Closing a terminal leaves orphan Jupyter processes - Orphans block ports for other projects - You can't tell what's running or which project owns which port ## What JupyterManager Does **`jupyter-hub`** is a single command that manages everything: ```bash jupyter-hub status # Show all projects (running/stopped) jupyter-hub ports # Port allocation map (8888-8899) jupyter-hub stop-all # Stop all Jupyter instances jupyter-hub orphans # Find untracked processes jupyter-hub kill-orphans # Kill them jupyter-hub which 8889 # Which project owns this port? jupyter-hub config # Show configuration ``` It discovers projects automatically by scanning configured directories for the `scripts/app.sh` convention. ## Installation ```bash git clone https://github.com/saymrwulf/JupyterManager.git cd JupyterManager bash install.sh ``` This creates a symlink at `~/bin/jupyter-hub` pointing to the repo's `bin/jupyter-hub`. Updates are just `git pull`. Ensure `~/bin` is in your PATH: ```bash # Add to ~/.zshrc or ~/.bashrc export PATH="$HOME/bin:$PATH" ``` ## Configuration Configuration lives at `~/.config/jupyter-hub/config.sh` (created by `install.sh`): ```bash # Port range to scan PORT_RANGE_START=8888 PORT_RANGE_END=8899 # Directories to scan for Jupyter projects SCAN_DIRS=( "$HOME/GitClone/ClaudeCodeProjects" "$HOME/GitClone/CodexProjects" "$HOME/Projects" ) ``` A project is recognized if it has `scripts/app.sh` AND either a `notebooks/` directory or `jupyter` in its `pyproject.toml`. ## Client Project Requirements For a project to be managed by `jupyter-hub`, it must follow the **Lifecycle Specification** documented in [`docs/LIFECYCLE_SPEC.md`](docs/LIFECYCLE_SPEC.md). The key requirements: 1. `scripts/app.sh` with: `bootstrap`, `start`, `stop`, `restart`, `status`, `logs` 2. Isolated Jupyter directories under the project root (not system-global) 3. Kernel installed with `--sys-prefix` (not `--user`) 4. Auto port allocation (scan 8888-8899 for free port) 5. PID file at `.logs/jupyter.pid` 6. Background + foreground modes 7. Graceful stop protocol (SIGTERM, wait, SIGKILL fallback) ### Current Client Projects | Project | Location | Status | |---------|----------|--------| | autoresearch-quantum | `ClaudeCodeProjects/` | Fully compliant | | QuantumLearning | `CodexProjects/` | Detected, partial compliance | | NTT-learning | `CodexProjects/` | Detected, partial compliance | ## For Coding Agents When instructing an AI coding agent to align a project with this specification, use the prompt in [`docs/AGENT_PROMPT.md`](docs/AGENT_PROMPT.md). ## Project Structure ``` JupyterManager/ ├── bin/ │ └── jupyter-hub The CLI tool ├── config/ │ └── defaults.sh Default scan dirs, port range ├── docs/ │ ├── LIFECYCLE_SPEC.md Client project specification │ └── AGENT_PROMPT.md Prompt for coding agents ├── tests/ │ └── test_jupyter_hub.sh Functional tests ├── install.sh Symlink installer └── README.md ``` ## Running Tests ```bash bash tests/test_jupyter_hub.sh ```