ilo
A programming language AI agents write, not humans. Named from Toki Pona for "tool".
Experimental pre 1.0 language, expect breaking changes. See STABILITY.md for what's stable vs in-flight. Open-sourced February 2026.
Python ilo
───── ───
def total(price, quantity, rate): tot p:n q:n r:n>n;s=*p q;t=*s r;+s t
sub = price * quantity
tax = sub * rate
return sub + tax
4 lines, 30 tokens, 90 chars 1 line, 10 tokens, 20 chars
0.33× the tokens. 0.22× the characters. Same semantics. Type-verified before execution.
Why
AI agents pay three costs per program: generation tokens, error feedback, retries. ilo cuts all three:
- Shorter programs - prefix notation eliminates parentheses; positional args eliminate boilerplate
- Verified first - type errors caught before execution; agents get
ILO-T004not a stack trace - Compact errors - one token, not a paragraph; agents correct faster, fewer retries
Install
|
The installer downloads the release binary plus its checksums-sha256.txt from the matching GitHub release and refuses to install if the SHA-256 doesn't match. Source: scripts/install/install.sh.
iwr -useb https://ilo-lang.ai/install.ps1 | iex
Same checksum verification as the Unix installer. Source: scripts/install/install.ps1.
# or run without installing
WASM mode: interpreter only. HTTP builtins (
get,$,post) require the native binary.
Uses the skills npm package (396K+ installs). Installs the ilo Agent Skill into Claude Code or any compatible agent.
| Agent | Install |
|---|---|
| Claude Code | /plugin marketplace add ilo-lang/ilo then /plugin install ilo-lang/ilo |
| Claude Cowork | Browse Plugins → Add marketplace → ilo-lang/ilo → install |
| Other agents | Copy skills/ilo/ into your agent's skills directory |
Quick start
# Inline
# From file
# Verb form (cargo / go / zero style; bare positional still works)
Tutorial: Write your first program →
Editor support
Syntax highlighting, snippets, and -- comment handling for .ilo files ships in extensions/vscode/. Install into Cursor with cd extensions/vscode && npm run install:cursor. VS Code marketplace publish is tracked separately.
Versioning
CalVer. Releases are YY.M (e.g. 26.5), patches within a month are YY.M.P (e.g. 26.5.1). The version string carries recency: an agent loading ilo spec --json ai knows which spec applies from the version alone, no changelog lookup needed. Token-conservative (manifesto principle 1) vs semver's 0.12.1.
Branches
| Branch | Purpose | Tags |
|---|---|---|
main |
Current release line, patches | 26.5, 26.5.1, 26.5.1-dev.N |
next |
Next release | 26.6-dev.N, then clean 26.6 on cut |
Universal scheme: -dev.N is the only in-flight marker on either branch. Clean (no suffix) means soaked, ready, published. No RC tag.
Release flow (next release)
- Work lands on
next - Iterations tagged
26.6-dev.1,26.6-dev.2, … - When soaked: merge
next→main, cut clean26.6tag onmain nextcontinues for26.7-dev.1
Patch flow (current release fix)
- Fix lands on
main(direct or short-lived fix branch) - Iterations tagged
26.5.1-dev.1,26.5.1-dev.2, … - When soaked: cut clean
26.5.1tag onmain - Merge
main→nextto carry the fix forward (auto viasync-next.yml)
Migration from 0.x
Last semver release: 0.12.1. First CalVer release cuts on the next breaking change as 26.X. Hard cut, no 0.13 bridge. The file version pragma ships with the CalVer cut and is optional — existing 0.x files have no pragma and verify without a diagnostic.
File version pragma
Optional. ilo source files may declare the minimum required runtime with a top-of-file sigil:
^26.5
-- rest of file
- Sigil-led (principle 4), ~3 tokens (principle 1)
^carries "at minimum" semantics — agents read it correctly without a spec lookup- First-class syntax, not a magic comment
- Position: first line, no leading whitespace
Verifier behaviour:
| Case | Result |
|---|---|
| Pragma absent | Assume latest installed runtime, no diagnostic |
| File targets older than runtime, breaking change between | Fail with migration pointer |
| File targets newer than runtime | Fail asking to upgrade |
Tooling: ilo --version-of <file> reads the pragma (returns nothing when absent); the formatter canonicalises position when present, never inserts one.
What it looks like
Guards - flat, no nesting:
cls sp:n>t;>=sp 1000 "gold";>=sp 500 "silver";"bronze"
Pipes - left-to-right composition:
run x:n>n;x>>dbl>>inc
Data pipeline - fetch, parse, filter, sum:
fetch url:t>R ? t;r=($!url);rdb! r "json"
proc rows:L ?>n;clean=flt pos rows;sum clean
pos x:?>b;>x 0
Sum types - discriminated unions with exhaustive matching:
type Shape = Circle n | Rect n n
area s:Shape>n;Circle r=s;*r r Rect w h=s;*w h
defer / errdefer - guaranteed cleanup regardless of exit path:
open-file path:t>R t;f=open! path;defer close f;read! f
Auto-unwrap ! - eliminates Result matching:
Batteries included - the standard library covers what real programs need without leaving ilo:
- Math:
sqrt,pow,exp,log/log10/log2,sin/cos/tan,atan2,clamp,rou - Stats:
median,quantile,stdev,variance,cumsum,frq - Linear algebra:
transpose,matmul,dot,solve,inv,det,fft/ifft - Lists:
at,take/drop,zip,enumerate,range,chunks,window,flatmap,partition,setunion/setinter/setdiff - Text:
upr/lwr/cap,padl/padr,chars,ord/chr,rgxall,rgxsub - Time:
now,sleep,dtfmt/dtparse(strftime, UTC) - JSONL:
rdjlfor line-by-line parsing - Concurrent HTTP:
get-many(up to 10 parallel) - Parallel:
par-mapgeneral fan-out with chunking; native VM opcode - Tokens:
tokcountapproximate cl100k_base token count
What shipped in 0.13
Highlights from the 0.13 cycle:
- Sum types — discriminated unions, generics, recursive, exhaustive matching (examples/sum-types.ilo, examples/generic-sum-types.ilo)
- Generics — bounded type parameters, multi-bound, VM/JIT dispatch (examples/generics-bounded.ilo)
- Modules — re-exports, conditional imports, lazy loading
- Effect sets — declare and enforce side-effect budgets (examples/effect-sets.ilo)
- World / capability —
world/world-no-netbuiltins; static enforcement (examples/capability-world.ilo) - defer / errdefer — structured cleanup (examples/defer-basic.ilo, examples/errdefer.ilo)
- Gleam-style syntax —
use<-chain,todo/panic, match alternatives, multi-subject match - ilo httpd — embedded HTTP server (examples/httpd-hello.ilo)
- run family —
run-bg(fire-and-forget),run-full-env(inherit env) - Bitwise ops — 32/64-bit; native
U32/U64/I64types - Package registry —
ilo addinstalls packages from the registry - Fix plans + ilo apply — structured agent-writable repair workflow
- ilo trace — execution tracing for debugging and observability (examples/trace-demo.ilo)
- JS compile target MVP — emit JavaScript from ilo source
- WASM HTTP fetch —
$/getbuiltins work in WASM via fetch (examples/wasm-fetch.ilo) - Cranelift TCO — tail calls via
return_call; no stack overflow on deep recursion - tokcount — token counting builtin backed by tiktoken-rs
- Numeric / signal / text utility batches — extended stdlib coverage
Teaching agents
ilo ships as an Agent Skill. Install the plugin and the agent learns ilo automatically.
For manual context loading:
Key docs
| Introduction | What ilo is and why |
| Installation | All install methods |
| Tutorial | Write your first program |
| Types & Functions | Core language guide |
| Prefix Notation | Why prefix saves tokens |
| Guards | Pattern matching without if/else |
| Pipes | Function composition |
| Collections | Lists and higher-order functions |
| Error Handling | Result types and auto-unwrap |
| Data & I/O | HTTP, files, JSON, env |
| MCP Integration | Connect MCP servers |
| CLI Reference | Flags, REPL, output modes |
| Builtins | All built-in functions |
| Error Codes | ILO-XXXX reference |
| SPEC.md | Full language specification |
| examples/ | Runnable examples (also test suite) |
Benchmarks
Per-call time (ns) across 8 micro-benchmarks. Lower is better. Full results →
| Language | numeric | string | record | mixed | guards | recurse | foreach | while | pipe | file | api |
|---|---|---|---|---|---|---|---|---|---|---|---|
| Rust (native) | 496ns | 3.7us | n/a | 9.9us | 1.8us | 18.8us | 44ns | n/a | 254ns | 9.3us | 159.0us |
| Go | 705ns | 17.2us | 107ns | 6.2us | 738ns | 21.5us | 162ns | 30ns | 31ns | 19.0us | 200.0us |
| C# (.NET) | 6.2us | 14.6us | 554ns | 29.9us | 6.8us | 24.7us | 1.2us | 417ns | 610ns | 22.7us | 228.8us |
| Kotlin (JVM) | 492ns | 8.2us | 265ns | 7.8us | 1.0us | 17.4us | 1.2us | 168ns | 226ns | 18.6us | 183.4us |
| LuaJIT | 513ns | 19.0us | 149ns | 9.8us | 3.5us | 28.7us | 676ns | 48ns | 85ns | 14.7us | 63.2us |
| Node/V8 | 569ns | 1.3us | 354ns | 5.3us | 1.0us | 46.7us | 480ns | 81ns | 191ns | 12.4us | 284.5us |
| TypeScript | 427ns | 1.2us | 236ns | 5.4us | 1.0us | 45.9us | 421ns | 75ns | 167ns | 12.7us | 310.2us |
| ilo AOT | 1.8us | 12.9us | 1.1us | 33.0us | 5.3us | 37.3us | 1.1us | 148ns | 126ns | n/a | n/a |
| ilo Cranelift | 1.3us | 5.0us | 504ns | 26.2us | 3.2us | 37.2us | 935ns | 150ns | 125ns | 16.5us | 1.7ms |
| ilo VM | 11.3us | 10.5us | 3.1us | 31.6us | 53.5us | 528.3us | 2.4us | 1.2us | 7.0us | 16.9us | 171.1us |
| Lua | 4.0us | 39.8us | 7.5us | 49.2us | 27.0us | 339.1us | 3.8us | 967ns | 4.3us | 16.1us | 54.3us |
| Ruby | 19.8us | 26.0us | 8.7us | 18.4us | 38.5us | 373.0us | 3.2us | 2.3us | 6.3us | 19.6us | 269.2us |
| PHP | 6.4us | 4.0us | 4.0us | 8.2us | 25.8us | 552.9us | 1.1us | 767ns | 6.7us | 15.3us | 173.9us |
| Python 3 | 28.1us | 12.0us | 8.5us | 28.0us | 63.3us | 717.2us | 2.1us | 2.7us | 11.0us | 20.9us | 12.2us |
| PyPy 3 | 1.2us | 2.0us | 445ns | 20.5us | 4.3us | 107.1us | 605ns | 286ns | 470ns | 24.7us | 2.0us |
10000 iterations, Darwin arm64, 2026-03-14
Community
- ilo-lang.ai - docs, playground, and examples
- hello@ilo-lang.ai - get in touch
Principles
- Token-conservative - every choice evaluated against total token cost
- Constrained - small vocabulary, one way to do things, fewer wrong choices
- Self-contained - each function declares its deps; no globals, no ambient state
- Language-agnostic - structural tokens (
@,>,?,^,~,!,$) over English words - Graph-reducible - load only the relevant subgraph per task
See the manifesto for full rationale.
Author
Built by Daniel John Morris. ilo is the language I wanted while building with LLMs and AI agents.