Pyrelune is a Python execution kernel for interactive notebooks in Vix Note.
It allows Vix Note to execute Python cells through the vix-note-extension-1 protocol while capturing standard output, standard error, execution failures, diagnostics, and rich MIME outputs.
- Execute Python cells from Vix Note
- Capture
stdoutandstderr - Return structured Python errors
- Report syntax and runtime diagnostics
- Display the value of the final Python expression
- Support configurable Python executables
- Support custom working directories
- Enforce execution timeouts
- Install as a standard Vix package
- Integrate with the Vix Note extension registry
- Use a lightweight one-shot runtime without external C++ dependencies
Pyrelune requires:
- C++20 compiler
- CMake 3.20 or newer
- Python 3
- POSIX-compatible operating system for the current process runner
The initial process implementation supports Linux and macOS.
Windows process execution is not yet implemented.
Install Pyrelune globally:
vix install -g softadastra/pyreluneThe global Vix binary directory must be available on PATH:
export PATH="$HOME/.vix/global/bin:$PATH"Verify the installation:
command -v pyreluneVix Note can then discover the extension from the global package installation.
Clone the repository:
git clone https://github.com/softadastra/pyrelune.git
cd pyreluneConfigure the project:
cmake -S . -B build \
-DCMAKE_BUILD_TYPE=ReleaseBuild:
cmake --build build -jRun the tests:
ctest --test-dir build \
--output-on-failureConfigure and build using Vix:
vix buildBuild every available target:
vix build --build-target allRun the test targets:
vix testInstall into the default CMake prefix:
sudo cmake --install buildInstall into a custom prefix:
cmake --install build \
--prefix "$HOME/.local"The installation contains approximately:
bin/
βββ pyrelune
include/
βββ pyrelune/
βββ error.hpp
βββ kernel.hpp
βββ protocol.hpp
βββ pyrelune.hpp
βββ python_process.hpp
βββ request.hpp
βββ response.hpp
βββ result.hpp
βββ version.hpp
lib/
βββ libpyrelune.*
share/
βββ pyrelune/
βββ pyrelune-runtime.py
βββ icon.svg
Pyrelune is declared as a standard Vix package with a Note extension:
{
"extensions": {
"note": {
"api": "1",
"icon": "assets/icon.svg",
"runtime": {
"protocol": "vix-note-extension-1",
"command": "pyrelune",
"mode": "oneshot"
},
"cellTypes": [
{
"id": "python",
"label": "Python",
"language": "python",
"executable": true,
"aliases": ["py"]
}
]
}
}
}After installation, Vix Note should expose Python as an available cell type.
Launch Vix Note:
vix noteList discovered extensions:
vix note --list-extensionsPyrelune implements:
vix-note-extension-1
It uses a one-shot process model:
Vix Note
β
starts pyrelune
β
writes one JSON request to stdin
β
Pyrelune executes Python
β
writes one JSON response to stdout
β
process exits
The full protocol is documented in:
docs/protocol.md
Send a request directly to the runtime:
printf '%s' '{
"protocol": "vix-note-extension-1",
"requestId": "manual-1",
"cellId": "cell-1",
"source": "print(2 + 3)",
"workingDirectory": ""
}' | ./build/pyreluneExpected response:
{
"ok": true,
"requestId": "manual-1",
"stdout": "5\n",
"stderr": "",
"error": "",
"outputs": [],
"diagnostics": []
}Pyrelune displays the value of the final Python expression.
Example:
value = 10
value * 2The final expression produces a MIME output similar to:
{
"mime": "text/plain",
"data": "20"
}Expressions that evaluate to None do not produce a rich output.
Python output written with print() is captured separately:
print("Hello from Pyrelune")Response:
{
"stdout": "Hello from Pyrelune\n"
}Text written to standard error is also captured:
import sys
print("Something happened", file=sys.stderr)Response:
{
"stderr": "Something happened\n"
}Python exceptions produce structured diagnostics.
Example source:
def greet(name)
print(name)Possible diagnostic:
{
"severity": "error",
"message": "expected ':'",
"code": "SyntaxError",
"line": 1,
"column": 16
}Runtime exceptions are also returned:
raise ValueError("invalid value")Vix Note can provide a working directory with each request:
{
"workingDirectory": "/home/user/project"
}Python code then executes from that directory:
import os
print(os.getcwd())Overrides the Python executable used by Pyrelune.
PYRELUNE_PYTHON=/usr/bin/python3.13 pyreluneThis can also point to a virtual environment:
PYRELUNE_PYTHON="$HOME/project/.venv/bin/python" pyreluneOverrides the Python runtime script path:
PYRELUNE_RUNTIME_SCRIPT=/opt/pyrelune/pyrelune-runtime.py \
pyreluneThis is mainly useful during development and testing.
Overrides the Python executable used by the test suite:
PYRELUNE_TEST_PYTHON=/usr/bin/python3 \
ctest --test-dir build --output-on-failureThe complete public API is available through:
#include <pyrelune/pyrelune.hpp>Individual components can also be included directly:
#include <pyrelune/kernel.hpp>
#include <pyrelune/protocol.hpp>
#include <pyrelune/python_process.hpp>Example:
#include <pyrelune/kernel.hpp>
#include <pyrelune/version.hpp>
#include <chrono>
#include <filesystem>
int main()
{
pyrelune::Kernel kernel{
pyrelune::KernelOptions{
.python_executable = "python3",
.runtime_script =
std::filesystem::path{
"/usr/local/share/pyrelune/"
"pyrelune-runtime.py"},
.timeout = std::chrono::seconds{30}}};
pyrelune::Request request{
.protocol =
std::string{pyrelune::note_extension_api},
.request_id = "request-1",
.cell_id = "cell-1",
.source = "print(2 + 3)",
.working_directory = {}};
auto result = kernel.execute(request);
return result && result.value().ok ? 0 : 1;
}pyrelune/
βββ CMakeLists.txt
βββ LICENSE
βββ README.md
βββ vix.json
β
βββ include/
β βββ pyrelune/
β βββ error.hpp
β βββ kernel.hpp
β βββ protocol.hpp
β βββ pyrelune.hpp
β βββ python_process.hpp
β βββ request.hpp
β βββ response.hpp
β βββ result.hpp
β βββ version.hpp
β
βββ src/
β βββ kernel.cpp
β βββ main.cpp
β βββ protocol.cpp
β βββ python_process.cpp
β
βββ scripts/
β βββ pyrelune-runtime.py
β
βββ tests/
β βββ kernel_test.cpp
β βββ protocol_test.cpp
β
βββ examples/
β βββ hello.py
β
βββ docs/
βββ protocol.md
The protocol test verifies:
- valid request parsing
- optional working directories
- escaped multiline source
- protocol validation
- required fields
- invalid JSON input
- response serialization
- MIME outputs
- diagnostic serialization
The kernel test verifies:
- successful Python execution
- standard output capture
- Python exceptions
- request validation
- missing runtime scripts
- working-directory handling
Run all tests:
ctest --test-dir build \
--output-on-failureRun a specific test:
ctest --test-dir build \
-R pyrelune.protocol \
--output-on-failurectest --test-dir build \
-R pyrelune.kernel \
--output-on-failurePyrelune executes arbitrary Python code.
Only execute trusted notebooks and trusted source code.
The current implementation does not provide:
- Python sandboxing
- filesystem isolation
- network isolation
- memory limits
- package restrictions
- system-call filtering
- operating-system user isolation
For untrusted execution, run Pyrelune inside a dedicated security boundary such as:
- container
- restricted operating-system user
- virtual machine
- application sandbox
- process isolation environment
Pyrelune should not be treated as a security sandbox.
The initial release uses a one-shot Python process for every execution.
It does not yet provide:
- persistent state between cells
- interrupt support
- streaming outputs
- interactive standard input
- debugger integration
- package environment management
- rich Python display hooks
- asynchronous execution events
- Windows child-process execution
Planned future work includes:
- persistent Python kernels
- state shared between cells
- execution interruption
- streaming output events
- HTML and JSON display hooks
- image outputs
- virtual environment discovery
- Python dependency information
- Windows process support
- stronger resource limits
- richer diagnostics
- kernel lifecycle controls
Pyrelune is licensed under the MIT License.
See LICENSE for details.
Pyrelune is developed and maintained by Softadastra.
Softadastra builds modern tooling for C++ development and native applications.
- Installs
pyrelune-runtime.pyunder<prefix>/share/pyrelune/. - Resolves the real executable path when launched from
PATH. - Preserves rich MIME outputs for final Python expressions.
- Declares Python cell default source metadata for Vix Note.