日本語版 README · 📘 Documentation: https://i2y.github.io/yokan/
Yokan is a compiler: it takes a statically typed subset of Python to native code.
A subset — but not a lookalike language. What you can write is a
slice of Python, and inside that slice your code behaves exactly as
Python. While you develop, the whole app runs on real CPython; when
you ship, the same source becomes a machine-code executable.
Whether the two behave the same is something you can check, with
yokan gate.
Three more languages live in this repository, on the same engine:
Wakakusa (Ruby,
wakakusa/), Rakugan
(Perl, rakugan/) and Gomamochi
(Go, gomamochi/). Each has a tour, demos and a gate of its own.
First, what it looks like: OpsBoard, a bundled dashboard demo —
charts, a virtualized list, theme switching — written entirely in
Python (source: crates/yokan/demo/opsboard/).
And here is the smallest complete app:
# /// script
# requires-python = ">=3.14"
# dependencies = ["yokan"]
# ///
from yokan import State, button, column, run, text
count: State[int] = State(0)
def view():
with column(spacing=12, padding=16):
text(f"count: {count()}", size=34)
button("+1", on_click=lambda: count.set(count() + 1))
if __name__ == "__main__":
run(view, title="counter")Run it with uv run app.py and this window opens (the renderer is
gpui, the engine behind the Zed editor):
Edit the running app's source and save, and the app updates in place — views and handler behavior alike — with the state intact. The GIF below is that moment (editing another small demo) — note the tick counter never stops.
What doesn't fit the subset can stay real Python: mark the function
with @py and it runs on CPython — numpy and friends included.
And where you want native speed of your own, declare a Rust crate
and call it — the same implementation serves both the development
run and the release build.
And when something can't be compiled, you get an error saying what
and why. Behavior never changes silently.
Shipping is yokan build app.py --release. If the app uses no
@py, the executable contains no CPython at all — zero links to
Python, 14.7 MB (11.3 MB stripped), millisecond startup. Apps that
do use @py ship CPython embedded via --bundle or --onefile
(one file: about 17 MB stdlib-only, about 21 MB with numpy). Add
--app and either shape becomes a macOS .app bundle — Dock name,
icon, double-click launch. Either way, the person receiving it
needs no Python and no pip.
The shape — hot reload while you develop, AOT-compiled native when you release — is close to what Flutter and Dart give you. Yokan does it with Python, and hands you a way to check that the two runs behave the same.
Desktop apps, full stop. From a few-screen internal tool to a data-facing application of forms, tables, and charts — written with Python's feel, shipped as a native app.
There are 36 UI elements (text, buttons, a full set of form controls, tables, charts, virtualized lists, modals, and a pixel canvas you paint command by command), plus styles, light/dark themes, and animation; virtualized lists stay smooth at a hundred thousand rows. State comes in exactly three shapes, and the language tour walks the whole surface in one pass. There are 70 bundled demos, all screenshotted in the gallery.
Two of those demos are ports of apps written in Python, and they sit at opposite ends of how much Python the shipped app carries.
Pyxel's example games are ported almost line for line: the same pixel
canvas, the same thirty frames a second, the same keys read while
they are held. The binary carries no Python at all. A script of
keystrokes and frames replays both runs, so the gate compares every
frame of the game — including the ones where the score moves
(crates/yokan/demo/shooter.py, crates/yokan/demo/jump.py).
At the other end is Buzz's screen and its flow: drop a recording,
pick a model and a language, watch it work, read the segments, export
TXT / SRT / VTT. The transcription is Whisper — real Python, running
on an embedded CPython through @py — and --bundle --app makes a
.app that carries its own runtime, so the person receiving it needs
nothing installed. The gate compares the transcript and the SRT it
writes, byte for byte (crates/yokan/demo/transcribe/).
One source, two roads to run it.
Both roads stand on the same Rust foundation, which is what makes the final comparison meaningful.
That foundation is pixie, the substrate language Yokan compiles through, and the .pix in the middle of the release road is its readable source — open the generated .pix and you can see, with your own eyes, what your app compiled to.
The last box of the diagram. Yokan calls it the gate:
$ yokan gate app.py --script "click:+1,input:Momo"
GATE OK — 2 dump lines identical in both runsHand it a sequence of clicks and input; it replays them on the CPython build and on the machine-code build, then byte-compares the resulting screens. The standard library (files, SQLite, HTTP, and friends) is one implementation in both — that is what makes the comparison meaningful. And what Yokan cannot do yet is listed at the end of the tour, each item with its reason.
Today: macOS on Apple silicon and Linux, Python 3.14+.
Everything you develop with arrives via uv run app.py
(the three-line comment in the example above declares the
dependency). In a project, uv add yokan; for the yokan command,
uv tool install yokan — plain pip works too, and yokan init app.py writes a first file to start from. The window, live
reload, headless runs: no Rust needed so far.
Only the native build (yokan build / yokan gate) needs more: a
Rust toolchain, and the crates it compiles against, which live in
this repository. yokan check and yokan translate start no
compiler, so they run without any of it.
$ yokan gate app.py --script "click:+1"
$ yokan build app.py --release --onefile-
Install Rust via rustup; the compiler version is pinned by the repository and fetched automatically on the first build.
-
On macOS you also need Xcode's Metal toolchain (the GPU engine builds shaders).
-
On Linux the engine draws through Vulkan and opens its window on Wayland or X11, so the build needs a C compiler and the libraries it links against. On Fedora:
$ sudo dnf install gcc alsa-lib-devel fontconfig-devel freetype-devel \ libxkbcommon-devel libxkbcommon-x11-devel libxcb-devel \ vulkan-loader mesa-vulkan-drivers python3-devel
Other distributions carry the same libraries under their own names.
python3-develis only for apps with@pyescapes, whose build embeds CPython. -
The first native build fetches the checkout matching your version into
~/.cache/yokan/(about 11 MB), so there is nothing to clone by hand. Inside a checkoutyokanuses that one;PIXIE_REPOpoints it anywhere else. -
That first build compiles the engine and takes a few minutes; later builds are incremental.
-
Packaging follows the platform:
--appwrites a macOS.appor a Linux AppDir, and--appimagepacks that AppDir into one.AppImage.--bundleand--onefilecarry CPython in Apple's layout, so they name themselves and stop off macOS.
Measured (macOS/arm64, release): 4.7 ms start, ~1 ms live reload; sizes as in the shipping paragraph above.
skills/yokan/SKILL.md is a guide for an
agent: the whole dialect in one file, with every refusal and what to
write instead. Put it where your agent looks for skills — for Claude
Code that is ~/.claude/skills/:
$ curl --create-dirs -o ~/.claude/skills/yokan/SKILL.md \
https://raw.githubusercontent.com/i2y/yokan/main/skills/yokan/SKILL.mdAn agent that has read it gets the subset right the first time, instead of learning it from refusals at build time.
The loop it works in — three commands, and what each hands back — is written up here.
- The documentation site — installation, the tour and the demo gallery, browsable (日本語)
- Language tour — one pass over how apps are written, closing with what does not work yet (日本語版)
- crates/yokan/README.md — how to build, product details
- docs/PIXIE.md — pixie, the substrate language
(the
.pixside of the story)
For editor completion and type checking, use Pylance / pyright (type stubs ship with the package).
The name is the Japanese confection — yokan (羊羹), a dense solid block made to be sliced and handed out. Which is what your app becomes.
Yokan is 0.x: the API can change between minor versions.
License: MIT OR Apache-2.0. The vendored vendor/gpui_macos is
derived from Zed's gpui and remains Apache-2.0 (attribution and the
list of local changes are in that directory).





