⚠️

Pre-Release Notice

This website is a work-in-progress preview. Content may be incomplete, inaccurate, or change significantly. Features described here may not be fully implemented yet. View implementation status →

Koru Logo

Koru

The Hyper-Performant AI-First Postmodern Zero-Cost Fractal Metacircular Phantom-Typed Auto-Disposing Monadic Event Continuation Language with Semantic Space Lifting and Event Taps

Get started

npm i -g @korulang/koru

Then: koruc depskoruc deps install

A Taste of Koru

~import "$std/io"

const name = "World";
const debug = true;
const count: i32 = 42;

~std.io:print.blk {
    {% if debug %}[DEBUG] {% endif %}Hello, {{ name:s }}!
    The answer is {{ count:d }}.
}

Runtime conditionals and templating with zero overhead—compiles to a single print call

View this example in the test suite →

AI-First

Bounded contexts through events, flows and procs make AI assistants incredibly effective—clear interfaces and explicit contracts guide code generation

Postmodern

Koru doesn't replace the host language, just adds language constructs on top with the ~ leader prefix

Zero-Cost

All abstractions compile down to efficient host language code with no runtime overhead—high-level expressiveness meets bare-metal performance

Fractal

The same patterns work at every level—events invoke events, creating flows within flows with self-similar composition

Metaprogramming

Access ProgramAST and Source parameters at compile-time—generate code, analyze flows, and transform programs

Templating

Liquid-style templates with runtime variable capture—conditionals, interpolation, and multi-line blocks that compile to zero-overhead format strings

Metacircular

Parts of the compiler pipeline is written in Koru itself, allowing the user program to override core functionality, like optimization and type checking

Phantom-Typed

Track state in the type system with zero runtime cost—catch use-after-close and state machine errors at compile time

Monadic

Event continuations chain with the |> operator—algebraic effects with explicit, type-safe control flow, where the flow is composed of free monads

Event Continuation

Events declare branches upfront—handle all cases explicitly with visible, traceable control flow and no hidden exceptions

Semantic Space Lifting

Elevate concepts into the type system and event space—validation, state machines, and workflows become first-class constructs

Purity Tracking

Transitive purity tracking at compile time—calling an impure event makes your event impure, enabling clear reasoning and optimization

Event Taps

Observe and intercept events transparently—composable logging, metrics, and tracing with zero coupling to business logic

Performance

Koru aims to be within 10% of the performance of the host language when doing apples-to-apples comparisons, often matching it exactly.

Abstractions as optimization

Koru abstractions often outperform similar abstractions in the host language by orders of magnitude.

Interactive Compiler (soon)

Koru has an interactive compiler that supports conversational optimization and AST rearragement, using CCP (Compiler Control Protocol)

AI-First

Koru's event-driven architecture creates natural bounded contexts that AI assistants understand intuitively. Each event declaration is a clear contract with explicit inputs and outputs, making it easy for AI to reason about code structure. Event boundaries provide perfect scoping for code generation—an AI can implement a proc knowing exactly what inputs are available and what outputs are expected, without needing to understand the entire codebase. The explicit branching and type safety mean AI-generated code is more likely to be correct on the first try, and errors are caught at compile time rather than runtime.

Koru's flows and subflows can be implemented in isolation and made available for tooling using a partial AST, creating another clear reasoning boundary.

Koru is implemented using AI (Claude Opus 4.1-4.5, Claude Sonnet 4.5) to do mainly AI-first development.

Postmodern

Koru doesn't try to replace Zig or reinvent the wheel. It's a respectful superset that embraces its host language—every .kz file is valid Zig, with Koru constructs marked by the ~ prefix. Rather than building yet another systems language, Koru adds a layer of event abstractions on top of Zig's proven foundations.

It's postmodern in the good sense: acknowledging what works, composing with existing tools, and showing humility about what actually needs to be new. You're not locked into a specific package manager, build system, or toolchain—use npm, cargo, or whatever fits your workflow. Work with the ecosystem, not against it.

We've picked Zig as our host language because of its compilation speed, runtime speed and huge offering when it comes to compiler targets and FFI. There is nothing that stops you from emitting Koru to C#, JavaScript or whatever, really, the parser and most of the toolchain is host-language agnostic.

Zero-Cost

Every abstraction in Koru compiles down to efficient Zig code. Events, continuations, phantom types—they all disappear at compile time, leaving only the essential machine operations. You get high-level expressiveness without runtime overhead.

~event compute { x: i32, y: i32 }
| result { sum: i32 }

~proc compute = result { sum: x + y }
// Compiles to pure Zig - no runtime overhead

Fractal

The same patterns work at every level. An event can invoke other events, creating flows within flows. This self-similarity makes complex systems comprehensible and composable at any scale.

Metaprogramming

Koru provides first-class access to program structure at compile-time through special parameter types. ProgramAST provides the entire program structure, and Source parameters let you access raw source code as compile-time strings.

This enables powerful metaprogramming: generate boilerplate based on flow structure, validate architectural constraints at compile-time, build custom DSLs on top of Koru, or create sophisticated code transformations. Because these are built into the type system, metaprogramming is type-safe and integrates seamlessly with the rest of the language—no separate macro system or preprocessor needed.

Templating

Koru's templating system uses Liquid-style syntax for string interpolation with runtime variable capture. Use {{ var }} for interpolation and {% if var %}...{% endif %} for conditionals. Format specifiers like {{ name:s }} ensure type-safe output.

const debug = true;
const name = "Alice";
const count: i32 = 42;

// Inline templating with runtime conditionals
~print.ln("{% if debug %}[DEBUG] {% endif %}User: {{ name:s }}")

// Multi-line block syntax
~print.blk {
    === Report ===
    {% if debug %}Mode: Debug{% endif %}
    Count: {{ count:d }}
    ==============
}

The magic: conditionals are evaluated at runtime, but the template compiles down to a single std.debug.print call with inline conditional expressions—zero overhead, zero allocations.

Metacircular

The compiler is written in Koru itself, demonstrating the language's ability to reason about and transform its own constructs. This self-hosting nature ensures the language is powerful enough to build sophisticated tooling.

Phantom Obligations

Compile-time resource safety with semantic auto-dispose. The ! suffix tracks obligations you must handle, while ! prefix marks disposal paths. Every unclosed file, uncommitted transaction, and leaked connection becomes a compile error.

// Open connection - creates obligation
~pub event connect { host: []const u8 }
| connected *Connection[connected!]  // Must close this!

// Begin transaction - transforms the obligation
~pub event begin { conn: *Connection[!connected] }
| begun *Transaction[in_transaction!]

// Commit - consumes transaction obligation, returns connection
~pub event commit { tx: *Transaction[!in_transaction] }
| committed *Connection[connected!]

// Close connection - consumes connection obligation
~pub event close { conn: *Connection[!connected] }
| closed

// Usage: connect → begin → commit → close
~connect(host: "localhost")
| connected conn |> begin(conn)
    | begun tx |> do_work(tx)
        |> commit(tx)
        | committed conn |> close(conn)
            | closed |> _

Forget to close a connection? Compile error. Abandon a transaction? Compile error. The compiler enforces protocol obligations at zero runtime cost.

Monadic

Event continuations chain naturally with the |> operator. Each event can branch to multiple continuations, and the type system ensures all branches are handled—like algebraic effects with explicit control flow. Flows compose into subflows, creating a free monad where complexity emerges from simple, composable event chains.

// Events chain naturally with |>
~fetch(url)
| success data |> parse(data)
  | success ast |> validate(ast)
    | valid tree |> process(tree)
    | invalid err |> log(err, data)
  | error parse_err |> log(parse_err, data)
| error fetch_err |> retry(url)

This example uses the shorthand ~event(param) which expands to ~event(param: param), matching on param-name.

Event Continuation

Events declare their possible output branches upfront. When you invoke an event, you must handle each branch explicitly, making control flow visible and traceable. No hidden exceptions or unhandled cases.

// Define the event continuation
~event parse { input: []const u8 }   // Input payload
| success { ast: AST }               // Success branch continuation
| failure { message: []const u8 }    // Failure branch continuation

~parse(input: data)
| success s |> process(s.ast)
| failure f |> log(f.message)

Semantic Space Lifting

Transform how you think about problems by elevating concepts into the type system and event space. Validation, state machines, workflows—they become first-class language constructs rather than patterns buried in code.

With semantic space lifting you can target any existing C-library and remove defensive coding, knowing that errors will be caught at compile-time.

Purity Tracking

Koru tracks purity transitively—if an event calls an impure event, it becomes impure automatically. Pure events guarantee no side effects and can be aggressively optimized (memoized, reordered, or eliminated). You always know exactly which parts of your code have side effects, enabling fearless refactoring and clearer reasoning. The compiler tracks purity across the entire call graph, so you can see at a glance whether an event performs I/O, modifies state, or stays pure.

Event Taps

Observe and intercept events without modifying their flow. Attach logging, metrics, auditing, tracing, or debugging behavior transparently. Event taps compose, allowing sophisticated observability with zero coupling.

// Add full-program profiling
~[profile]tap(* -> *) | Profile p |> write_event(p.source, p.timestamp_ns)

Performance

Koru aims to, and mostly succeeds in, being on par with the performance of the host language when doing apples-to-apples comparisons, often matching it exactly, mostly within 2-6% deviation. Koru takes performance seriously. The main performance benefits comes from abstractions that are made possible by event continuations, like event taps, that don't really have a comparison in other languages, but typically outperform the same usecase in other languages. If a language in the host language is more performant than Koru, the host-language is just a `proc` away.

Interactive Compiler

In Koru, compilation is just another event—specifically compiler.coordinate. The entire compiler pipeline (analysis, pass planning, optimization, validation) is defined as a subflow that your program can completely override. Want domain-specific optimizations? Replace the default coordinator. Need to inject custom passes? Override individual compilation events. Every compilation phase is user-configurable. Koru compiletime is host-language runtime, so you can do anything the host language can do at compiletime.

The standard library provides compiler.coordinate.default so you always have a working baseline, but you can wrap it, extend it, or replace it entirely. Game engines can optimize for consistent frame timing. Trading systems can inline aggressively for minimal latency. Web servers can optimize for code size. Each program defines how it should be compiled—there's no separate "compiler plugin API" because the compiler is just events, and your program defines the subflows.