Open-source project
joouha/euporie avatar
joouha/euporie

Euporie's terminal Jupyter suite, and the SSH hub that only the dev group installs

Jupyter notebooks in the terminal

2,672 stars58 forksPythonMIT

At a glance

What is it?
Euporie is seven packages published from one uv workspace: a metapackage, three apps, a core library, a UI toolkit and a multi-user SSH server. The metapackage declares no license in its metadata, pins no versions on the three apps it depends on, and advertises a hub command that only the dev dependency group brings along.
Who is it for?
Euporie is worth reading before it is worth installing, because the packaging tells you what the project considers settled and what it does not. The apps are small, the split between console, notebook and preview is clear, and the hub is the component to look at hardest: it turns any host with a Jupyter kernel into a multi-user SSH service, so the authorization boundary is a file of public keys and nothing finer.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 5 days ago.
What is it written in?
Mainly Python, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 5, 2026, and from our analysis. They are not legal advice.

Editorial analysis

The metapackage carries a commented out license line and unpinned dependencies

Open the project's pyproject.toml and the first thing you find is a license that is not declared. The project table names euporie, marks the version dynamic, and carries a license key with the whole line commented out:

toml
# license = "MIT"

A LICENSE file does sit at the top level of the tree, so the grant exists, but nothing in the installed distribution records it. The classifier list runs from a Beta development status marker through Python 3.10 to 3.14 and carries no license classifier either. The dependency list is three bare names with no version bounds:

toml
dependencies = ["euporie-notebook", "euporie-preview", "euporie-console"]

euporie-core, which holds the config system, kernel client, LSP client, shared widgets and rich output rendering that every app uses, is not named there at all and arrives transitively. With no minimum version stated anywhere, an older euporie-notebook can resolve next to a newer euporie-console, and nothing in the file objects.

Three permanent install commands, and a launcher that fronts four apps

For permanent use the guide offers three routes, in order of preference:

console
$ uv tool install euporie
$ # OR
$ pipx install euporie
$ # OR
$ python -m pip install --user euporie

The first two give each tool an isolated environment; the third writes into your user site directory, and the guide adds nothing about whether the scripts it leaves there land on your PATH. Once installed, one command fronts all the apps:

console
$ euporie notebook notebook.ipynb
$ euporie console
$ euporie preview notebook.ipynb
$ euporie hub

That fourth line is where the packaging and the documentation disagree, and the packages section is the escape hatch. Because each app is its own distribution, you can install one and skip the rest, as the guide shows with uv tool install euporie-notebook. Installing the metapackage instead pulls the console, notebook and preview apps together, which is convenient and also gives you three programs you may never launch.

euporie hub is a dev dependency that the launcher list still advertises

The launcher block lists euporie hub as if it came with the suite, but euporie-hub appears only in the dev dependency group, so installing the metapackage does not bring the server along. The direct command is where the real configuration shows:

console
$ euporie-hub --port 8022 --host-keys=ssh_host_ed25519_key --client-keys=authorized_keys

It is a multi-user SSH server, and the three flags are the whole surface the guide describes: a port, a path to the ed25519 host key, and a path to a file of client public keys allowed to connect. That framing is honest, and it is also the entire authorization model. Anyone holding a key in that file gets a session backed by a Jupyter kernel on the host, so what they can reach is whatever the kernel process can reach: files under its account, outbound network, environment variables holding credentials. No per-user scoping of what a kernel may touch, and no mention of anything sitting in front of the port. The tree does carry a Containerfile at the top level, so a container is one of the shapes this repository supports.

The default branch is dev and the newest tag stopped in February 2026

The repository's default branch is dev, and the last commit on it is dated 1 October 2026. The tag history is a different clock: v2.10.4 was published on 23 February 2026, v2.10.3 on 19 December 2025 and v2.10.2 on 15 December 2025, so the releases stopped roughly seven months before the branch moved on. An install from a package index therefore gets the February tree rather than the one the documentation describes. The version itself is dynamic, read from a VERSION file at the top level instead of being written into pyproject.toml, which is why the two can drift without either looking wrong. The logo asset in the documentation points at refs/heads/dev as well, so the documentation renders from the moving branch while your installed copy sits on a tag.

packages/ holds the workspace, src/ sits beside it with no explanation

The development section calls euporie a uv workspace mono-repo whose individual packages live under packages/. The top level listing carries more than that: alongside packages/ there is a src/ directory, a scripts/ directory, a root conftest.py, DEVELOPMENT.rst, CONVENTIONS.rst, a Containerfile, a readthedocs configuration and a pre-commit configuration. Nothing in the visible configuration says what src/ holds, so a second source root sits next to the workspace root without comment. The dev dependency group explains most of the rest: python-lsp-server for the language server behind contextual help, ruff and codespell for linting, prek and pre-commit-hooks for the hooks file, taskipy for task aliases, and towncrier for the changelog directory of fragments that sits next to the rendered CHANGELOG.rst. The lint group is only partly visible, stopping mid-entry at ruff. Setup is three commands:

Kernel facing work rides on one shared core and one bundled toolkit

Every app sits on euporie-core, which owns the config system, the kernel client, the LSP client, shared widgets and rich output rendering. The terminal UI itself comes from apptk, a prompt_toolkit extension that lives in the same repository under packages/, so the widget layer and the toolkit underneath it move together. Against a kernel, the feature list claims images through terminal graphics over sixel, iterm or kitty protocols, interactive Jupyter widgets, and rich output for markdown, tables, images, LaTeX, HTML, SVG and PDF. Those last two are the claims to try first on your own setup, because they depend on which graphics path your emulator and fonts actually support. Notably absent from the dependency list is any Jupyter package: the project declares a Jupyter framework classifier and talks to kernels, but nothing here installs one.

Every app takes a path argument, and two of them have a keyboard way in

Each app can be reached three ways: through the launcher, as its own command, or through uvx with no install at all. The per-app commands take the notebook path or URI as an argument:

console
$ euporie-notebook notebook.ipynb
$ euporie-console
$ euporie-preview notebook.ipynb

Launch euporie-notebook with no argument and you get a file menu instead, with Open bound to Ctrl+O. euporie-console takes no arguments at all, connects to a kernel and binds Ctrl+Space to its command palette. Key bindings come in Micro, Vim and Emacs styles. Line suggestions and contextual help come from the language server client in euporie-core, which pairs with python-lsp-server on the development side. One feature changes how you would actually use the suite: a console session can be converted to a notebook, so exploratory work done interactively can be written back to a file instead of being retyped.

The Python floor is 3.10, the classifier ceiling is 3.14, and PyPy has no version

The requirement is a floor rather than a ceiling: requires-python is greater than or equal to 3.10, and the compatibility note says Python 3.10 or later on Linux, Windows and MacOS. The classifiers enumerate 3.10, 3.11, 3.12, 3.13 and 3.14, then add CPython and PyPy as supported implementations. The PyPy marker is the loose end: it is an implementation classifier with no version classifiers attached, so support for PyPy is asserted without being tied to any specific release. That gap matters more than it looks, because a language server client and a graphics protocol both behave differently across interpreters, and none of the visible configuration records a matrix. Since no Jupyter package is a dependency, the interpreter on the far side of the kernel is yours to choose and to keep current.

Editorial conclusion

Euporie is worth reading before it is worth installing, because the packaging tells you what the project considers settled and what it does not. The apps are small, the split between console, notebook and preview is clear, and the hub is the component to look at hardest: it turns any host with a Jupyter kernel into a multi-user SSH service, so the authorization boundary is a file of public keys and nothing finer. Install one app rather than the metapackage if you want a smaller dependency surface, check what your terminal can actually display before relying on the rich output claims, and treat the absence of version bounds as your problem to manage in whatever environment you run it.

Frequently asked questions

Does installing euporie also install Jupyter?

No. The dependency list of the metapackage names only euporie-notebook, euporie-preview and euporie-console, and no Jupyter distribution appears in it. The project declares a Jupyter framework classifier and ships clients that talk to kernels you start yourself.

Which Python versions does euporie claim to support?

The requirement is Python 3.10 or later, and the classifiers enumerate 3.10 through 3.14 with CPython and PyPy as implementations. The PyPy marker carries no version classifiers, so that support claim is not pinned to a release.

Does the euporie metapackage install the hub server?

No. euporie-hub sits in the dev dependency group rather than in the project dependencies, so uv tool install euporie does not bring it along even though the launcher section lists euporie hub as one of the commands. You need euporie-hub installed directly to run it.

How do I try euporie without installing anything?

With uvx, if uv is installed. The guide shows four invocations, launching the notebook editor with or without a file, an interactive Jupyter console, and a preview that renders a notebook to the terminal. A browser demo is also linked from the documentation and needs no installation.

What license does the euporie distribution declare?

None in its metadata. The license key in pyproject.toml is present but commented out, no license classifier appears in the list, and a LICENSE file does sit at the top level of the repository. The repository record says MIT.

What does the euporie repository say about where its name comes from?

Nothing. The project description, the keyword list and every package description in the guide describe function only, and no file in the tree records an origin for the name.

Official sources

  1. joouha/euporie on GitHub
  2. License: MIT
  3. Project website
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/joouha-euporie.svg)](https://hysenlabs.com/projects/joouha-euporie)