One wire, three languages
Almost everything before this part was Rust (Tic-tac-toe, VI
borrowed these faces ahead of time), and the model never depended on it. A resolution is
a request and a representation crossing a boundary, and the boundary is a wire protocol
with a version number: ikigai-ipc speaks it over a Unix socket in Rust, and so do two
other implementations of the same codec — ikigai-python
(standard library, and one dependency: blake3, for the digests in a served door’s contract IRIs) and ikigai-deno
(TypeScript, with one dependency, @std/crypto, for the same digests, and zod only for its optional ./zod entry point). Each is both halves at once: a client that drives a
running kernel, and a servable peer that a Rust host mounts as a space.
That pairing is called L0 of the polyglot ladder, and the name is honest about what it
is. A Python or TypeScript process can resolve any name a kernel binds, be described,
be cached and traced by that kernel, and be refused by its capabilities. What it cannot do
is what a Rust endpoint does with inv.source(..) — reach back into the kernel from
inside its own invocation. An L0 peer is a leaf: it answers, it does not compose. There is
no back-channel yet, and the two tracks below say so where it bites rather than pretending
the ladder is taller than it is.
The two tracks
Both tracks mirror Part I chapter for chapter, in a language with no kernel in it:
| Part I | in Python and TypeScript |
|---|---|
| Resolution | connect() and source(): a name resolved over the wire, a representation back |
| Hello, resource | an endpoint as a decorated function, served on a socket |
| Why an endpoint describes itself | the signature is the contract: ArgSpecs derived from annotations, describe() as data |
| Binding, and a host of your own | ikigai --mount urn:py:=<socket> — a mount is a binding, and the host owns the name |
| What resolution buys you | is_cached, source_traced: the kernel’s cache and trace, seen from outside |
| capabilities | a scoped connect(), and a typed DeniedError |
| Multi-verb endpoints | a family: one URI template, a contract per verb (Source, Sink, Delete, Exists), and which door answers a name |
Then a notebook: the catalog as a graph, in rdflib, with one SPARQL query. And for a whole application served this way, you have already seen the same game in Python and TypeScript: a store in each language under a Rust host, and an app in each language that serves the host’s board.
What you need
A running kernel to talk to — ikigai serve <socket>, from the CLI the front
door installed — and one of the two client packages. Neither is
published to PyPI or JSR yet; both install from a checkout (pip install <path>, or a Deno
import by path), and the listings in this part say so where it matters. The listings
themselves live in this repository under examples/, modeled on the sibling repositories’
own examples (read-only for this book) so that the book builds from a clone of this
repository alone. The client listings were run against ikigai-cli 0.1.18 as they were written
(one refusal line shown in the Python track carries a later kernel’s wording, and says so).
The steps that start a peer and mount it are replayed against the book’s pinned ikigai-cli
on every change to this repository, by scripts/polyglot-tracks.sh, and each track says which
those are.
⚠ Names under
urn:py:andurn:ts:in this part are served by your peer process and resolve only while it runs and is mounted. They are not in the CLI, and the book’s URN gate declares them as such rather than claiming otherwise.