One command to herd every JupyterLab on the laptop
The Jupyter UX assumes you have one project. Notebooks, kernels, JupyterLab server, one port. Eight thousand eight hundred and eighty-eight, by tradition. The moment you have two projects, the assumption falls apart: both servers want port 8888, the second one fails or quietly grabs 8889, your terminal scrollback is now the only record of which port belongs to what. Close a terminal and the server doesn't always die with it. Now you have an orphan JupyterLab process holding a port you can't reach.
If you live in notebooks, this happens to you every other week.
JupyterManager is a single command that knows the answer. It discovers projects automatically, tracks which port each one has, and exposes a small set of verbs you actually need:
jupyter-hub status # who's running, who's stopped
jupyter-hub ports # allocation map across 8888-8899
jupyter-hub stop-all # graceful stop on everyone
jupyter-hub orphans # processes you forgot about
jupyter-hub kill-orphans # they don't survive
jupyter-hub which 8889 # which project owns this port?
jupyter-hub config # what does the manager think it's doing
The design choice that matters here is that the manager doesn't try to be your launcher — it observes, names, and (when asked) terminates. You still start individual servers however you start them: from VS Code, from a terminal, from a Makefile. The manager catches up to whatever state your machine is in and gives you words for it. The auto-discovery walks your filesystem for project markers (.git, pyproject.toml, anything with a notebooks/ directory) and matches running processes against that list, which is much cheaper than tracking lifecycle events would have been.
Shell, all of it. Maybe 300 lines. The configuration is a single environment file. The "port allocation map" is just a numbered range (8888–8899) with the manager refusing to start more than twelve simultaneously, because if you have more than twelve JupyterLab servers running you have a different problem than this tool can solve.
This is the kind of small tool that pays for itself the second time something goes wrong. The kind of thing that should ship inside JupyterLab and somehow doesn't. The reason it doesn't is that JupyterLab's authors quite reasonably consider this an OS-level concern; the reason it lives in this repo is that the OS quite reasonably considers it a JupyterLab concern; and so the user gets to write it.
What becomes possible: you stop counting terminals.