a thin orchestrator over a C ABI
The Python boundary
Python authors views and orchestrates. The engine is C++. The line is sharp: every model operation crosses one C ABI, and nothing that has to be fast, correct, or shared with the native app lives in Python.
Where Python stops
Python authors views and orchestrates. The engine is C++. The line between them is sharp and deliberate: anything that has to be fast, correct, or shared with the native app lives in C++; Python is the thin layer that drives it.
your app (Python) view(state) → a kinogaki.view tree; the CLI; the server loop
│
the C ABI kinogaki_* one stable seam; every model operation crosses it
│
the C++ libraries Core (model), Platform (runtime + transport), UI (render)
The binding
pip install kinogaki is a ctypes binding over the C ABI from the seams. A Document in Python is a handle to a C++ Document; doc.append(path, type), doc.eval(slot, time), and doc.diff(other) each call straight through kinogaki_*. No model logic is reimplemented in Python: the binding marshals arguments and hands back native values. Because the C ABI is version-agnostic C, the binding works on any CPython 3.x without recompiling per version.
The three packages
The library-to-package mapping is one to one:
| Package | Wraps | Gives you |
|---|---|---|
kinogaki | Core | the model: Documents, Elements, Values, codecs, queries |
kinogaki.platform | Platform | the runtime and the SDUI transport (SduiChannel, the WebSocket framing) that drive serve |
kinogaki.ui | UI | the native render of a view-Document, the toolkit in a window (run) |
kinogaki and kinogaki.platform are portable and ship on every OS. kinogaki.ui is macOS only; off macOS it degrades to a clear ImportError and kinogaki run prints a message, while serve works regardless. How each is built and tagged is in building and shipping.
What stays in C++
The document model, the evaluator, the codecs, the diff and overlay, the WebSocket framing and the SDUI protocol, the widgets and their reconciler: all C++. A Python program never parses Prism bytes, never computes a diff, never reconciles a widget tree. It says what the view is; the C++ underneath decides what to send and how to draw it. That is why the same view renders in a browser and in a native window with no Python on either render path, and why a slow language on the authoring side costs nothing on the rendering side.