Twenty minutes, nothing compiled
Two front doors, and this is the second. The first is already open: every Run button
in this book resolves against a kernel compiled into the page — Running
it says how — and it binds only Part I’s names. This
chapter is the other door: the full host, ikigai, on your machine, with everything it
links. Eight commands, no Rust, and by the end you have seen the whole model — a catalog,
a manifold, a pipe, a format change, a cache hit, a cut thread, and a trace.
0. Install
cargo install ikigai-cli --locked
ikigai --version
⚠ The crate is
ikigai-cli; only the binary is calledikigai.cargo install ikigaidoes not fail — it fetches an unrelated crate by another author.--lockedbuilds the dependency versions the release was tested with rather than whatever the registry resolves today.
Every command below is one-shot: -c runs a line and exits, --plain drops the
decoration. Run ikigai with no arguments for the REPL, which is the same grammar with
a memory — and the sixth command needs that memory, so it says so.
1. Everything resolvable
ikigai --plain -c 'source urn:kernel:catalog'
Every endpoint the host binds, describing itself, as one Turtle graph — several hundred lines on a full install. Nobody wrote this document; it is assembled from each endpoint’s own description, which is why it cannot be out of date.
2. Everything you may do
ikigai --plain -c 'source urn:kernel:actions'
One IRI per line: the endpoints the capability you hold may invoke. As root that is nearly everything. It is the same list an agent would be handed as its tools, computed from the same descriptions, and it narrows as authority narrows — the difference between this and the catalog is the whole capability model in one diff.
3. A pipe
ikigai --plain -c 'source urn:iki:fn:toUpper in="a b" | urn:iki:fn:reverseList'
A B
[2 computed]
The first resolution’s output became the second’s unnamed argument. [2 computed] is the
kernel counting: two resolutions, neither served from cache. There is no function call in
that line — two names, resolved in order.
4. Another format
ikigai --plain -c 'describe urn:iki:fn:toUpper text/turtle'
describe is the Meta verb, and the trailing type is as=: the same endpoint’s
description as a graph rather than as text. Try text/plain for the human face. A
resource does not have a format; it has whatever the kernel can reach.
5. A cache hit
This one needs the REPL, because the cache lives in the process and a -c run exits.
Start ikigai, then write a file into the workspace and read it back twice:
ikigai> sink urn:file:notes.txt remember the milk
wrote 17 bytes to notes.txt
[uncacheable]
ikigai> source urn:file:notes.txt
remember the milk
[computed]
ikigai> source urn:file:notes.txt
remember the milk
[cached]
ikigai> cache urn:file:notes.txt
cached
The second read came from the cache; the file was not opened. cache asks without
resolving — a probe, not a call. A write is never served from a cache, so the sink
says so.
6. Cut a thread
Still in the REPL. A golden thread is what a cached answer hangs from: the file
endpoint declared that its answer depends on a thread named after the file, and
urn:kernel:cut is the resource for cutting a thread by hand:
ikigai> sink urn:kernel:cut urn:file:notes.txt
cut urn:file:notes.txt
[uncacheable]
ikigai> cache urn:file:notes.txt
not cached
The cached read stopped being valid at that instant, and so would anything derived from it — a composite that had read the file inherits its thread. Writing to the file does the same cut without your help; this is the resource for doing it on somebody else’s behalf, which is what a filesystem watcher does when a file changes out from under the kernel.
Now the part the first draft of this page got wrong. Try the same cut on a pure function:
ikigai> source urn:iki:fn:toUpper in="a b"
A B
[computed]
ikigai> sink urn:kernel:cut urn:iki:fn:toUpper
cut urn:iki:fn:toUpper
[uncacheable]
ikigai> cache urn:iki:fn:toUpper in="a b"
cached
Still cached. A cut invalidates the entries whose declared threads include the one
you cut, and toUpper — a pure function of its arguments — declared none: same input,
same answer, forever, and no thread to hang that on. The entry is valid until the kernel
forgets it. Nothing was named wrongly here; there was simply nothing to invalidate, and
urn:kernel:cache shows exactly that:
ikigai> source urn:kernel:cache
cache
entries 3
urn:file:notes.txt text/plain 17 B 1 thread
urn:iki:fn:toUpper application/json 268 B 0 threads
urn:iki:fn:toUpper text/plain 3 B 0 threads
Two entries for toUpper — its description, fetched once to route the arguments, and the
answer — each with 0 threads. The file’s entry has 1 thread, and it is still
listed even though section 6 cut it and the probe said not cached: a cut bumps a
generation and nothing more, and a stale entry is evicted lazily, the next time
something resolves the name. cache only looks. Read the file again and the entry is
replaced.
7. Which threads have been cut
ikigai> source urn:kernel:threads
threads (cut generations)
urn:file:notes.txt gen 2
urn:iki:fn:toUpper gen 1
Every thread ever cut in this kernel, with its generation — the file’s twice (once by the
sink that wrote it, once by hand), toUpper’s once. A generation bumps whether or not
anything depended on the thread: cutting is cheap and blind, and validity is decided
lazily, when an entry is next looked up, by comparing the generation it was made at with
the one now.
8. A trace
ikigai> trace urn:iki:fn:toUpper in="a b"
trace urn:iki:fn:toUpper
client ikigai repl · capability: root (full authority)
transport embedded · in-process
urn:iki:fn:toUpper toUpper · cached · main · 0ms → 3b A B
One real resolution, recorded: who asked, under what authority, over what transport, and
then the tree — each node saying whether it was computed or served (served, here: the
cut in section 6 did not touch it), on which thread, how long it took. A composite shows its sub-resolutions as children. This is the same
issue_traced the book’s tests call, rendered.
What you have seen
A system that can list what exists and what you may do, resolve names into other names’ arguments, change a representation’s format on request, serve an answer without recomputing it, invalidate precisely — what declared the thread, nothing else, and never by timeout — and show you its own execution. None of it needed a line of Rust. All of it is what Resolution describes, and Part I is where you build an endpoint that gets every one of these properties for free.
Every name printed on this page is checked, on every commit, against a written-down
claim about the CLI (books/ikigai/cli-vocabulary.txt) — and that file is checked against
a real binary by a test that has to be run by hand, because CI has no ikigai. Every
transcript on this page is replayed against a real binary by another
(cargo test -p book-urns --test book_transcripts -- --ignored), which is how the first
draft’s section 6 was caught claiming a cut had invalidated something it had not. If a
command here fails on a newer CLI, those two are where to look first.