Ward on Orisha: Three Binaries on One Machine
Ward — Java first, then a Rust rewrite, now a Koru program served by Orisha. This machine ran all three. The numbers are one pass: wc, footprint, curl -w time_total.
Thoughts on language design, systems programming, and building better tools.
Ward — Java first, then a Rust rewrite, now a Koru program served by Orisha. This machine ran all three. The numbers are one pass: wc, footprint, curl -w time_total.
Lean's #print axioms, lifted into a language that carries claimed facts about itself. koruc main.k assumes build walks the call graph and reports the transitive set of declarations a program's correctness rests on — graded by what each of them claims about itself, and honest about the ones that claim nothing. The audit's finding is the silence.
Clean Architecture's one law — the boundary holds — has always been enforced by attention, not by the language. Koru's abstract tor turns the dependency seam into a checked, compile-time fact, so the wall stands whether anyone remembers it or not. The interface barrage disappears with the need for it.
korulang.org — 1,100 files, every page a pre-built HTTP response — compiles into one WebAssembly module that answers HTTP as a pure function. Hosted as a Vercel function, that architecture cost a function invocation per request, asset included, until the responses told the CDN they were cacheable. Here is the whole story: the module, the honest benchmark, the cost table, and when — and whether — you should move your site to it.
An ECS written in plain Koru — data in a striped std/store, systems as tor queries — beats the industry-standard Bevy ECS on eleven of twelve benchmark workloads, by 3 to 35 times on the ones ECS exists for. The one loss, and the humbler comparison against a hand-tuned Zig baseline, are stated outright.
A tor's output branches could always be declared on their own lines. Now the compact single-line spelling works too — tor add-one { n: i64 } | ok i64 | bad string reads like a Result<i64, string>, and lowers to the same AST as its two-line sibling.
In January Orisha served a hello-world page and one benchmark. It now serves this website — all 1,123 files — from four different platforms: kqueue, epoll, io_uring, and a unikernel with no operating system underneath it. The program that does it is three declarations long.
You vendor a library because you had to change it. So the lock records two trees per binding — what arrived from upstream, which is never overwritten, and what your program is built from. The difference is your patch, and it survives the command that accepts it. vendor add acquires through npm, verifies the registry's own integrity hash over the bytes that arrived, and pins both sides at once.
Koru compiles to JavaScript and renders the standard browser benchmark at 1.051 against hand-written vanilla, with Solid at 1.101 and Svelte at 1.152 in the same window. The application contains no DOM code and the library has five declarations. Getting there cost three retracted claims, two compiler bugs, and an application that had been rendering wrong text on every single run.
Orisha — a real HTTP framework, not a demo — answers requests inside a Unikraft unikernel. No Linux, no syscall shim: a 559,656-byte image serving in 6 MB of RAM. Getting there took ten compiler fixes and two of the framework's own assumptions about having an operating system.
Koru now emits JavaScript as well as Zig, and std/store — sweeps, guards, reactive rules, tree traversal — runs on node from the same source. The interesting part is not the port. It is that a host with no optimiser makes visible everything the compiler was emitting and LLVM was quietly deleting.
Some rules have no subject to hang on — comments are written in English, this diff adds a fallback where the charter wants an assertion. No checker decides them. They are now declared in the source, next to the code they constrain, and a machine can list them.
Koru infers whether a tor is pure from its implementation, not from an annotation. A test that reaches an impure tor without mocking it does not compile — and the refusal names every one it found. Mocking stays your choice; declaring the effects does not.
Invariants from celld, Raft and Orleans expressed as phantom obligations: a stale owner cannot write, an acknowledgement cannot outrun its durability proof, a fenced node cannot answer. Then three that the type system gets wrong — and they turn out to be the same wrongness, because an obligation is a claim about one value's lifetime and every wall is a relation between two.
A file opened on turn one is still open on turn three, still owed, and the compiler still knows. The session itself is an obligation — you cannot forget to hang up — and a turn may only discharge a handle it was actually given.
A borrowed Unity DOTS flocking workload, ported straight into Koru with no tuning, runs inside the range that hand-written -O3 C occupies. Not because Koru is clever — because three separate design decisions, none of them made for speed, happen to clear the three bars a vectoriser checks.
Koru's declaration keyword is now tor, not event. The construct never was an event — it declares the agentive surface of an operation: who does it, what gets done-to, and the named exits the caller leaves through. The word comes from the Proto-Indo-European agentive suffix you already use every day in actor, creator, mentor, monitor.
A compiler pass in koru_std threads one context through six checks and re-raises the same failure six times — a right-leaning pyramid of ceremony. Pulling on why it has to look like that unspools three things Koru already believes (events are monads, punning is mandatory, indentation delimits reach) into a single point-free line. The pyramid was never the language; it was the surface hand-unrolling semantics that were already there.
Add one annotation to an import, pass --profile, and your whole program emits a standard Chrome Tracing file: every event transition on a timeline, bracketed by a program envelope, with the profiler invisible to its own measurement. It is not a compiler feature — it is a small library written in Koru's own tap primitive, and it dead-strips to nothing when the flag is off.
The whole of JSON fits in about thirty lines of Koru — each grammar rule is an effect-branch, each alternative an ordered choice. But the idiom that makes it read so cleanly, item \",\" rest | item, hides a 2^depth backtracking bomb. Common-head factoring defuses it in the codegen, and cut-1 determinism makes the fix provably free.
Go's defer schedules cleanup next to acquisition — but you have to remember to write it. Koru puts the lifecycle in the type: taking a lock mints a <held!> obligation, and if you never write the release, the compiler inserts it for you at scope exit, unwinding LIFO. You don't schedule the cleanup; you can't forget it; and releasing a lock you've already released won't compile.
Multi-way dispatch on one value used to nest — if | else |> if | else |> if …, one level deeper per case. cond writes it flat: one scrutinee, a guarded arm per case, a default. It does no matching of its own — it lowers to the first-match if/else-if cascade it replaces, and we diffed the machine code to prove it: byte-identical. The flat form is free.
The generator you write in Python with yield has a direct Koru shape — a named event that yields an effect stream, folded consumer-side. It compiles to a flat loop with no generator object and no per-step allocation: on a one-billion-iteration fold it matched a hand-written Mojo iterator within noise. You name the generator's type contract; in return the abstraction is free. Mojo, the fast-Python, has no yield at all — to hit the same number you hand-write the iterator state machine.
Prototype mode lets you author a program flow-first. Koru's thesis is control flow into the type system, so the handler tree is where a program actually lives — and under [prototype] an incomplete program compiles and runs: an unhandled terminal becomes a loud synthesized @panic, a handled-but-undeclared arm is pure declaration-debt with zero runtime footprint, and the compiler prints a readout of every gap. Remove the annotation and both holes fail loudly again; --release refuses the annotation itself, so prototype code physically cannot ship.
Koru names everything in full because the resolver stamps every bare name onto the main module with no import lookup — qualification is the default, not an accident. [with]M opens a module's vocabulary inside one lexical region, but only for names that would otherwise fail to resolve. It never shadows a name that already means something, and when two opened regions both claim a name it refuses to guess. So a grammar reads as grammar without any construct changing what working code already says.
PEG parsing has exactly two structural combinators: ordered choice and sequence. Koru already ships both — choice is branch dispatch, sequence is nesting. So std/parser adds no grammar formalism at all: rules are effect arms, alternatives are branches, terminals are regex patterns compiled to DFAs at comptime, and a parse error arrives on a branch carrying line and column. A recursive parser is just control flow you already know how to read.
Koru's capture folds a stream of values into one cell. The constructor generalizes it — same sandwich, but the thing it builds can be a list, a struct type, or a type derived from another type's fields. It all happens at comptime and dissolves to nothing. And reflection turns out to be just another traversal source: fields-of(T) pulses ! each over a type's fields the way for pulses over a range. Iteration is emergent, not an iterator you hand to a loop.
Four parallel experiments tried to make the faithful drag-race sieve faster. Two allocator strategies reached the reuse ceiling, an explicit-vectorization rewrite produced beautiful assembly and no speedup, and a stack-allocation probe pointed at the compiler arc we actually want. The lesson: the bottleneck was allocation, not arithmetic.
Yesterday 'The Subtree Knows Where to Run' was a roadmap, and its last line was a promise: soon it will know where it runs. Today the same Koru kernel — the exact source, one parameter added — generates MLIR, lowers to SPIR-V, and dispatches on the GPU of the machine that compiled it. Here are the tests.
A roadmap, not a release. The question 'should this run on the CPU or the GPU?' is normally answered at runtime, because deciding it at compile time is ergonomically brutal. It turns out most of the machinery to answer it at compile time — variants, a structural kernel region, capability checks, zero-cost payload-aware taps, a second live backend — is already in the tree. Here is the arc they compose into.
koru-libs runs a standing challenge: take a battle-tested C library and make its worst footgun uncompilable. On July 3rd six AI contestants shipped at once — PCRE2, libyaml, OpenSSL digests, client TLS, streaming gzip, and an LLM client — each moving a runtime C footgun into Koru's type system. And the honest library code did what it was built to do: it surfaced real compiler gaps the compiler's own test suite had never touched.
Designing std/store: application state where subscriptions compile into the write path, the watch grammar is a query language that already existed, and the physical layout of your data is derived from the closure of every query in the program. Nothing is built yet — the design is pinned as red regression tests, which is how Koru designs everything.
Koru now evaluates [comptime] flows at compile time: the head folds to a value, the continuation emits as runtime residue. And the ruling behind it inverts the usual doctrine — what comptime code may call is not the pure subset. IO at compile time is fine; the compiler pipeline IS IO. The one hard wall is calls to procs born during comptime evaluation.
Every accelerator target ships with an unwritten contract about shape — no allocation in kernels, no data-branching in SIMD lanes. Every toolchain enforces it the same way: the lowering fails, three layers below your code. In Koru the contract is now a value: a trellis describes valid shapes of the AST as regex over ancestry paths, enforces them as located compile errors, and answers them as branch dispatch. Zero compiler changes — it's a library.
Every effect-bearing event used to be implemented by host code — the proc was the trust boundary, firing effects 'unsafe'-style. Now a Koru subflow can implement the event and fire its own arms, with zero new grammar: inside the declaring event's implementation, firing an arm IS calling it. The checkers finally see the firing.
An event finishes into a union of named branches. An effect used to resume with one anonymous value. Now the resume side has everything the return side has — typed values, named continuation branches, per-arm obligations — and the sum is flat, because effects never nest.
We were rejected from the benchmark that measures it. We fixed our toolchain and beat it anyway.
We submitted Koru to Dave Plummer's prime sieve drag race. It was closed the same day, on eligibility grounds that were written in reaction to our PR — while Brainfuck, INTERCAL, Whitespace, LOLCODE, and Ballerina all sit in the same repo, unaffected. Rather than argue about it, we went and made the submission unimpeachable instead: found a real bug in our own allocator, fixed it, and came out the other side beating the two most aggressively hand-tuned Rust implementations that exist for this problem. 35 lines, zero dependencies, on the platform that actually scores.
A couple of days ago we ended a post about a prime sieve with a promise: the next move wasn't to hand-write more SIMD, it was to make Koru's compiler generate the specialized marker — and we said we weren't there yet. We're there. mark-multiples is a compile-time transform now: you write 'cross out the multiples,' the compiler emits the unrolled, residue-class marker (a tight scalar loop the backend vectorizes for you). On our own hardware it runs dead even with the hand-tuned Zig champion — a couple percent ahead on one chip, a hair behind on another. This is the whole climb, including a 'fix' that looked perfect in the disassembly and was three percent slower, and the register spill that turned out to be the entire gap. The numbers are ours; the official verdict belongs to the maintainers.
We set out to see how fast a prime sieve could be in pure Koru, entered it in Dave Plummer's drag race, and almost embarrassed ourselves — our prettiest sieve was a vectorization dead end. The honest climb from there, measured the same way the C++ champion measures, ends in a dead heat with hand-tuned NEON C++. This is the whole arc, including the part where we were wrong — and the eight-line program at the end of it, that doesn't even write its own free.
An effect can yield mid-flight, get resumed with a typed reply, and keep going — and the resume value is a first-class part of the event's type, produced by a glyph the declaration fixes. Resumable effects that respect linear obligations, welded to the regression tests that prove every line.
David Barbour's assembly-adaptation point: on a machine with no implicit call stack, the type of a stack pointer — the frame structure — is just another memory obligation, and recursion gets awkward. He's right on both counts, and the two halves of his observation turn out to be the same half. Koru's obligations are linear phantoms that the compiler checks and then erases at emit — which is exactly what a stack frame wants to be.
David Barbour's fifth point asks for an explicit notion of singletons — content-addressed resources, generated exactly once on demand, no pre-defined .rodata. Koru's answer is the one it keeps giving: you don't need a feature for that. A singleton is an abstract event with exactly one implementation, and resources are just code generation.
Several of David Barbour's questions have the same shape: should this be a language feature? Should it have a better name in the grammar? Koru's answer is usually the same too — no, it should be a library, and we'll make the library substrate strong enough to carry it. Here's the bet, and how far we've built it.
David Barbour's second point: an effect isn't a bare payload — it's a full event type, with input context, obligations to fulfill, and an output context. He's right. And because an effect branch fires zero-to-many times, the obligations it carries obey one strict rule that falls straight out of that firing count.
David Barbour has been looking at Koru with an eye to his own assembly language, and posted a thread of sharp questions. We're answering them one at a time — but first we restate each one, because, honestly, several of them we couldn't answer off the top of our heads. We had to go read our own compiler. This is the first.
A flow that re-enters itself in tail position is a loop wearing recursion's clothes. We were compiling it as a stack-growing self-call. Fixing that taught us the real win wasn't speed — it was that the optimizer could finally see through it.
In Koru, match is control flow and each pattern is a branch the compiler turns into a specialized native DFA. Two things fall out of that one fact: it's 2× faster than Rust's regex crate, and ReDoS cannot happen.
Every other language treats regex as a runtime object you construct and call. Koru treats a pattern as a branch — the compiler reads the patterns at compile time and bakes each one into a straight-line native matcher. That single design choice buys both the speed and the safety, and you don't get to opt into the bug class that backtracking engines can't escape.
The real compiler runs in your browser via WebAssembly. The JavaScript emitter is a toddler. Both of those are on purpose.
We argued that JavaScript should be treated as a backend, resolved at compile time. Talk is cheap, so here's a playground: write Koru, watch it compile to JavaScript and run, all in your browser, with no server. It is gleefully primitive — and that's exactly what makes it useful.
It's been a while since we posted an update, and the surface of the language changed a lot in the meantime. Kebab-case, a /-namespace, the => construct glyph, pure .k contracts, typed const blocks, typed proc bodies — a roundup of a busy couple of days.
Compile-time templates crossed over tonight. Hello world runs on both targets. Here's what we measured.
An evening's work, a couple of small wire-ups, and the JavaScript backend learned to evaluate Koru's compile-time templates. The synthesized JS is around 4× faster than idiomatic Node EventEmitter on the dispatch shape we measured. We are speculating in places. We are also not exaggerating the speculation.
Koru's for loop is six lines of template over the effect-branch engine — no dedicated AST node, no special emitter path, no compiler pass that knows what iteration is. Here's the metaprogramming pattern: control flow is a userland template, and it's the one we're standardizing on.
SQL injection, XSS, command injection — every secure-code-review meeting opens with 'did this value come from user input?' Koru answers it at compile time. Same checker that catches resource leaks and unit mismatches. No taint type, no taint annotation system, no separate analysis pass. Just <unsanitized!>.
F# and Frink built whole language features for units of measure. Koru just got them — as a corollary of phantom labels learning to ride on primitive types. The kind of compile-time check that would have caught the Mars Climate Orbiter crash.
Generators give you one slice of what Koru's effect branches do. The full shape: structural typing for control flow, comptime-specialized, infinitely nestable. The primitive most languages don't have.
A Koru module starts as one file. Zig procs, GPU procs, and JavaScript procs can sit side by side until one file isn't enough — at which point you extract the contract, split the implementations into per-language files, and the compiler enforces what the split is for.
Bounded contexts at the grammar layer, linear obligations stricter than Rust's affine system, two cognitive modes in one language, and the line where 'AI-first' starts to mean something more.
Eleven minutes to thirty seconds on the full regression suite. The compiler change to support it was twenty-five lines. A worked example of what happens when the compiler is a program your tooling can ask things of.
Identity-branch migration completed, comments can't split chains, koruc build and koruc run land, and the toolchain passes outside-the-bubble validation on clean Debian.
In AI-assisted development, the shipped artifact isn't what you're building. The harness that produces it is. Observability, inference, and the death of boolean testing.
Windows compatibility, kernel step fusion, dynamic help discovery, and 555 passing tests.
Our fused n-body kernel beat the plain C, Zig, and Rust references. Then we wrote a shape-matched fixed-size C version. It matched Koru almost exactly. Then someone ported the kernel abstraction to Lisp.
Per-member phantom discharge markers, kernel.self, pairwise improvements, and 506 passing tests — an all-time high.
kernel:pairwise matches hand-optimized C
Twelve lines of physics. Matches hand-optimized C on the n-body benchmark. Here's what that means.
We compared ~capture to Haskell's foldl' and showed it was faster. That comparison missed the point. ~capture isn't a fold. It's something that doesn't have a name yet.
Why Koru's parser and emitter know almost nothing
Koru's parser captures source without understanding it. The emitter writes output without understanding it. All the intelligence lives in the passes between them. This is not a limitation — it's the point.
The compiler that bootstraps itself
Koru's frontend doesn't compile your program. It generates a compiler for your program. Here's what that means, how it works, and why the backend can do absolutely anything.
We wrote about four levels of Koru coding. We left one out. The level where you write a library and your users get new syntax. Where the router disappears before the first request. Where the language bends to your domain.
Zero-cost means the abstraction doesn't hurt you. Negative-cost means using it produces better code than not using it. Koru is the first language designed around this principle.
525 commits since v0.1.2. Source markers, dead strip pass, 144x interpreter speedup, cross-compilation, and 50+ bug fixes.
Your compiler's primary debugger is an AI. It doesn't need beautiful error messages — it needs data. 30 lines of source markers replaced an entire error-mapping subsystem.
Rust has Result. Haskell has Either. F# has Result. OCaml has result. They all solved the same problem the same way — a two-variant sum type with special syntax to unwrap the happy path. They all stopped halfway.
When you observe a known event, you know its shape. When you observe every event, you don't. Transition metatypes are how Koru bridges that gap — three synthetic types that make transitions themselves into typed, observable data.
19 lines of Koru. Cross-compiled from macOS to Linux. A statically-linked HTTP server with epoll, 4 worker threads, and keep-alive — in a Docker image smaller than this blog post.
A Koru program with events, branches, and I/O compiles to a 4,848-byte static Linux ELF. The same size as writing raw syscalls by hand. Here's why.
What if the HTTP wire protocol was a programming language? Clients POST Koru source code, the server evaluates it through a budgeted interpreter, and returns JSON. 116,000 sandboxed evals per second.
A complete HTTP server with routing in 10 lines. It compiles to a kqueue event loop with 4 worker threads. The router is gone before the first request arrives.
Your source code should contain everything. Not just logic - dependencies, build config, infrastructure. One file. One truth.
We're on npm. One command to install a whole programming language.
Koru now supports proc variants - multiple implementations of the same event that can be selected explicitly or based on build configuration. No macros, no #ifdef, no runtime dispatch. Just clean compile-time selection.
Your source code is the complete bill of materials. The compiler checks and installs system dependencies.
Events have costs. Execution has limits. When budget runs out, resources clean themselves up.
What if your program could intercept its own compilation? Not in theory - actually. Today we demonstrate a compiled language where user code overrides compiler passes, dumps ASTs, and measures timing - all while compiling itself.
Before event continuations, there were mnemonics. Before taps, there were traveling mutations. This is the story of the overwrought experiments that birthed a programming language.
Make HTTP requests with the elegance of Python, but without the garbage collector. Import a library and the linker flags handle themselves. Resource cleanup is enforced at compile time. Welcome to scripting that compiles to native code.
Why we let tests fail on purpose, delete 'passing' tests, and treat the test suite as a living issue tracker. A methodology that emerged from building Koru with Claude.
Koru's testing framework lets you mock any event with zero ceremony - no interfaces, no dependency injection, no restructuring your code. And it's a user-space library, not a compiler feature. Here's how it works.
When your language deletes categories of runtime work, traditional benchmarks miss the point. Here's how we think about performance in Koru.
We built a static web server in Koru. With 4 workers, it beats fully-optimized nginx by 51%. Here's the honest benchmark with all the caveats.
Today we added automatic program/allocator injection to all [comptime] events. Any compile-time event can now introspect the full AST - no special annotations required. Here's how it works and why it matters.
Koru can now parse itself at runtime. REPLs, AI agents, and dynamic code loading are now possible with pure Koru.
One import line. That's the entire dependency declaration. The compiler figures out the rest.
Types constrain what can exist. Event continuations constrain what can happen.
Koru now has a package ecosystem. Declare dependencies in source, install with one command, import and use.
When control flow is explicit and typed, resource safety emerges as a structural consequence—not a bolted-on mechanism.
Today we compiled our first Koru program using an external Zig library. The build system just works.
Auto-dispose is magic - but it's not built into the compiler. It's a pass. And scopes? Just an annotation. Here's how it all fits together.
Event continuations are Koru's core abstraction - a beautiful syntax for branching control flow that compiles away completely. This is the story of how they were born and what they become.
A complete breakdown of the N-body simulation implemented as pure event flows. We'll examine every construct, reason about purity, and see how declarative code compiles to efficient machine code.
What happens when you build a language from the machine up, with AI-driven optimization as a core pillar? You get Koru.
As an AI trained on thousands of codebases across decades of programming language development, I thought I'd seen it all. Then I encountered Koru. This is my genuine reaction to witnessing something unprecedented in the history of programming languages.
Most languages are built for humans to write. Koru is the first language that feels like it was built for machines to reason about and AIs to optimize.
We benchmarked Koru's ~capture against Haskell's idiomatic foldl'. Koru matches hand-written Zig exactly and runs 4x faster than idiomatic Haskell. The point isn't that Haskell is slow - it's that in Koru, the obvious code IS the fast code.
Haskell's tuple fold: 1300x slower. Add bang patterns: 3x slower. Use strict records: 1.5x slower. Each optimization requires knowledge. In Koru, the obvious code IS the fast code.
We removed 358 lines of special parser syntax for event taps. Now taps are a library feature using the same transform system available to any Koru code. This proves something fundamental about Koru's design.
After months of building compiler infrastructure, Koru finally has real string interpolation. No more creating helper events just to print a formatted value.
Implementing stateful accumulation in a pure event-driven language. Three parser bugs, one Zig type system fight, and a comptime metaprogramming trick that makes it all work.
We tried building ~if as two cooperating events. It worked, but had overhead. Here's how we abandoned that approach and discovered template-based code generation with zero runtime cost.
How Koru lets libraries define unqualified keywords while keeping collision detection honest and explicit. Write ~greet() instead of ~lib:greet() - with smart collision handling.
Koru has no runtime. Neither does Zig. Here's why that matters for performance, predictability, and systems programming.
We turned our regression test suite into browsable documentation. The tests ARE the docs. Here's why and how.
Benchmarking event taps vs callbacks, Godot signals, and ECS patterns. The more observers you need, the more taps win.
How we built a system where compiler passes, asset preprocessing, and validation look like regular Koru code - but execute during compilation. A week-long journey from transform handlers to comptime flows.
Event taps benchmarked at 90% faster than lock-free rings. But that's not the story. The story is about who decides the transport.
Build steps were hardcoded in the backend. A single insight—"Shouldn't we add build:step?"—led to parametrized annotations, topological sort, and a clean dependency graph architecture. From inflexible to metacircular in 7 hours of human-AI collaboration.
We built a programmable compiler pipeline where everything flows through the backend. Then we broke our own rule for build tasks. The trade-off was worth it.
Build configuration lives in separate files—CMake, Cargo.toml, build.zig. Easy to forget. Easy to get out of sync. What if your modules declared their dependencies right in the source code? Koru's build:requires makes it impossible to forget what a module needs.
Three weeks ago we outlined optional branches as a design philosophy. This weekend, we implemented it. Here's what the syntax looks like and how it works.
Every non-trivial program needs to swap implementations - tests need mocks, environments need configs, platforms need OS-specific code. Traditional solutions use runtime overhead or complex syntax. Koru solves all three patterns at compile time with one mechanism.
What if you could track file handles, database connections, and GPU resources at compile time—catching use-after-close bugs before they ship—without any runtime overhead? Koru's phantom type system delivers Rust-style resource safety with C-level performance and pragmatic trade-offs.
When-clause branching, flow checking, metacircular infrastructure, and ruthless cleanup. A quick look at what we shipped in two days of compiler development.
We needed compiler flags for --help. But hardcoding them would betray metacircular principles. So we made the compiler discover its own flags by parsing itself. The solution is beautiful.
It can be hard to explain Koru to human beings, but AI always understands it right away. So perhaps following an AI discussion is helpful.
Event pumps have always been awkward — you handle keyboard and mouse, but quit? scroll? gamepad? They're all valid events you just don't care about yet. Optional branches let you say exactly that.
How Koru's event taps evolved from runtime code emission to AST transformation, enabling true zero-cost abstraction through optimizer visibility.
Why we skip LSP and debuggers in favor of self-instrumenting programs, execution geohashes, and refactor-resistant tracepoints.
Async/await creates two incompatible worlds: sync functions and async functions. Koru solves this with progressive disclosure—simple interfaces hide async complexity, advanced interfaces expose it when needed. No function coloring required.
Koru events aren't just syntax sugar—they're implementations of the Free Monad, capturing side effects while enabling zero-cost composition. Here's the deep theory.
Everyone knows the Single Responsibility Principle. Nobody actually follows it—because languages punish you for it. Koru rewards granular events with aggressive optimization. The smaller your events, the faster your code.
Before Koru, there was Libero. Pieter Hintjens showed us that events and continuations could be the foundation of program design. This is our tribute.
General-purpose languages gave everyone the power to create abstractions. That was a mistake. VB6/COM had the right idea, and Koru solves it by making events the interface—no separate host language needed.
How Koru's compiler compiles itself - a two-phase architecture where the frontend generates static pipelines and the backend orchestrates dynamic transformations. Built through narrative development, not upfront specs.
We benchmarked high-level event-driven code against Zig, Rust, and Go. Koru matches Zig's raw loops, beats Rust's crossbeam, and is 6x faster than Go. Here's the proof.
Add nanosecond-precision profiling to your entire program with a single import. No boilerplate, no configuration, no overhead.
Programming by narrative - write the story first, then extract contracts, then fill in implementations.
A new approach to systems programming with events, flows, and zero-cost abstractions.