v0.1 alpha · 626 tests passing

Forge AI backends
that prove what
they did.

Cleat is a compiled, statically typed language for auditable, stateful AI orchestration. Tools, streams, state machines, and provenance chains are compiler-enforced primitives—not library abstractions you hope someone wired up correctly.

626
Tests
12
Stdlib pkgs
23
Examples
9
Compiler pkgs
analyze.cleat
1tool analyze(repo: string, pr: int) 2 -> Result[Analysis, string] 3 needs { net } 4 timeout: 30s 5 retry: 2 6{ 7 let url = "https://api/${repo}/pr/${pr}" 8 let resp = http.get(url)? 9 let data = json.decode(resp.body)? 10 return Ok(data) 11} 12 13test "analyze can be mocked" { 14 using analyze = fn(r, p) { 15 return Ok(Analysis { ... }) 16 } 17 assert(analyze().IsOk()) 18}
[ 01 / PRIMITIVES ]

Four first-class primitives.
Enforced by the compiler.

Most languages bolt orchestration on through frameworks. Cleat bakes it in. tool, stream, state, and chain are keywords—and the type-checker has opinions about all of them.

tool

Typed callables, declared effects.

Tools have timeouts, retries, and explicit side-effect declarations. The compiler refuses to compile a tool that lies about what it touches.

tool fetch_data(url: string)
  -> Result[string, string]
  needs { net }
  timeout: 10s
  retry: 1
{ ... }
stream

Backpressured by default.

First-class streaming with typed yields and bounded buffers. No more wrapping callbacks in a Promise wrapped in a generator wrapped in regret.

stream tokens(prompt: string) -> string
  needs { llm }
  buffer: 16
{
  yield "chunk1"
  yield "chunk2"
}
state

Reachability, checked at compile.

Declarative state machines with deadlock and reachability detection. Unreachable states won't compile. Neither will deadlocks.

state PRReview {
  initial: Pending
  Pending -> InReview { when: assigned }
  InReview -> Approved { when: approved && ci_green }
  any -> Cancelled { when: closed }
  terminal: Merged, Cancelled
}
chain

Cryptographic provenance, native.

Append-only, signed records with retention policies. Every action your AI takes can be cryptographically attested without bolting on a separate audit pipeline.

chain AuditTrail {
  signing: ed25519
  @retention(7y)
  record Entry {
    source: string,
    hash: sha256,
    timestamp: time
  }
}
[ 02 / EFFECTS ]

Side effects? Declared.
Or the build fails.

Every function declares what it touches with needs. A pure function calling an effectful one is a compile error—not a runtime surprise found in production at 3am.

Tests use using to swap real effects for mocks. Type-checked, scoped, and impossible to forget to remove.

pure_transform.cleat compile error
fn pure_transform(s: string) -> string {
    http.get(s)
    ^─── missing needs effect: net
    return strings.to_upper(s)
}
fetch.cleat checked ✓
fn fetch(url: string)
  -> Result[string, string]
  needs { net }
{
    let resp = http.get(url)?
    return Ok(resp.body)
}
[ 03 / STDLIB ]

Twelve packages.
No npm required.

Everything you need to build a real backend, in the box. Each package declares its effects so callers know exactly what they're inheriting.

std/json
Encode, decode, pretty-print, validate.
needs ·
std/http
GET, POST, custom requests.
needs · net
std/fs
Read, write, list, exists, mkdir.
needs · fs
std/strings
19 string functions: split, join, trim…
needs ·
std/math
abs, min, max, clamp, floor, sqrt, pow.
needs ·
std/env
Environment variable access.
needs · io
std/log
Leveled logging to stderr.
needs · log
std/os
Process args, exit, getwd, hostname.
needs · io
std/io
Print to stdout.
needs · io
std/crypto
SHA-256 hashing, hex encoding.
needs ·
std/time
Wall-clock + deterministic test clocks.
needs · time
std/llm
LLM prompt & stream, mockable.
needs · llm
[ 04 / ERGONOMICS ]

Modern syntax.
No ceremony tax.

Pattern matching, pipes, string interpolation, named arguments. The things you actually want, without writing a 12-line type signature first.

01

Pattern matching

Exhaustive, with bindings. The compiler tells you what you forgot.

match expr { Ok(v) => v, Err(e) => 0, _ => -1 }
02

Pipe operators

Read left-to-right like the data flows. Compose without nesting hell.

xs |> filter(x > 0) |> map(x * 2) |> sum()
03

Result & ?

Errors are values. The question mark propagates them, no try/catch.

let data = risky_call()?
04

String interpolation

Templates with full expression support. No printf. No backticks.

"hello, ${name}! found ${items.len()} items"
05

Built-in test runner

Tests live next to code. cleat test just works.

test "low score is Low risk" { assert(...) }
06

Named & default args

Call sites that read like English. Defaults that document themselves.

analyze(repo: "acme", pr: 42)

Start forging.

Cleat compiles to native binaries through Go. One build step, zero runtime dependencies.

$ go build -o cleat ./cmd/cleat
requires go 1.22+ · macOS, linux, windows