What changed · what broke · what's new

The changelog.

Every release. Every breaking change. Every fix. Pre-1.0 means we move fast — semver is respected, but minor versions may carry breaking changes until we tag stable.

Jump to version

Agents, guards & HTTP servers.

The biggest release since v0.1.0. Four new compiler-enforced primitives — agent, guard, server, and first-class fn — bring safe AI agents, typed HTTP, and policy enforcement into the language core. Structured LLM output ships with compile-time schema extraction.

★ Highlights
  • Four new primitivesagent for tool-using LLM loops, guard for pre-flight policy checks, server for declarative HTTP, fn as a first-class keyword.
  • Structured LLM output — annotate a struct, get a typed value. The compiler lifts JSON Schema out of your types and deserializes responses automatically.
  • Three new stdlib packagesstd/server, std/supervisor, std/memory — bringing the total to 15.
  • 826 tests passing across 11 internal packages, up from 626.
  • VS Code extension with syntax highlighting for .cleat files, published to the marketplace.
+ Added
  • agent primitive with declarative model, tools, max_turns, and system prompt 1a22e30
  • guard primitive with Allow / Deny / Transform return types and composition 3f8b91c
  • server primitive — declarative HTTP routes with typed handlers and middleware 7e42a0d
  • fn promoted to first-class keyword with explicit effect declarations b09f112
  • Compile-time JSON Schema extraction from struct types for structured LLM output c44ea80
  • @description annotation for steering LLM field generation d91c7a2
  • Correlation IDs propagated automatically across tool, agent, and chain boundaries f1028bb
  • std/server stdlib package with JSON request/response helpers 52c6f89
  • std/supervisor for agent retry, timeout, tracing, and execution summaries a704d13
  • std/memory namespaced KV store with context injection into agents 88e2049
  • VS Code extension with syntax highlighting, published as cleat-lang.cleat-vscode 60a1bef
  • Six new example programs covering agents, guards, and HTTP servers ff3e812
~ Changed
  • std/llm now returns typed structured values when the call site has a known struct type 4b9a7d1
  • Diagnostic output for effect mismatches now includes the full needs-inheritance trace 2daf906
  • cleat run now loads .env files by default; disable with --no-env 71e33cc
✓ Fixed
  • State machine reachability analyzer no longer reports false positives on mutually recursive guards 9c40211
  • Tool timeout parameter now correctly propagates through supervisor retry loops 5fa8e42
  • Formatter preserves blank lines between @description-annotated struct fields a0bc339

The first public alpha.

We're cutting the first version of Cleat that the world gets to look at. The compiler, formatter, test runner, and standard library all ship in this release. The language is alpha — usable for real programs, not yet stable for production.

★ Highlights
  • First-class primitivestool, stream, state, and chain are now compiler-enforced keywords.
  • Effect system — every function declares side effects with needs { ... }; the type checker enforces it.
  • 12 stdlib packages shipped in the binary — json, http, fs, strings, math, env, log, os, io, crypto, time, llm.
  • Built-in toolingcleat run, cleat build, cleat test, cleat fmt, cleat check.
+ Added
  • chain primitive with Ed25519 signing and configurable retention policies a3f12c7
  • using clause for typed mock substitution inside test blocks b7e891d
  • Pipe operator |> with full type inference across stages 19f0a44
  • String interpolation: "hello, ${name}" with arbitrary expressions cc4d3b1
  • Pattern matching with exhaustiveness checks for enums and Result types e2d9f8a
  • Maps: map[string]int with .keys(), .values(), .contains() 4b1c7e0
  • Default and named arguments for tool and function declarations 7a8e2f3
  • --no-warn flag to suppress warnings on build and test for CI f3c1098
~ Changed
  • Diagnostic renderer rewritten in Rustc style with squiggly underlines and span highlighting 9d4e22b
  • Result[T, E] error propagation operator narrowed: ? now requires explicit return type 2f6a103
  • Stream buffer parameter is now required (default behavior was too easy to footgun) 81bd9c4
✓ Fixed
  • Effect inference no longer drops needs across method calls on struct receivers c5e7811
  • Formatter preserves trailing commas in multi-line struct literals df21044
  • Test runner now exits with non-zero code on any failure (was previously 0) 6629a3e
  • Multi-package import resolver no longer caches stale versions across cleat run calls b8c91f7
! Breaking
  • Tool decoration syntax moved from comments to first-class keywords. Migration: // timeout: 30stimeout: 30s outside the tool body block 7e3df01
  • std/llm now requires an explicit backend selection. Previously defaulted to mock; now must call llm.use_mock() in tests a14f9b2

State machines land.

The state primitive ships with reachability and deadlock detection. Plus the formatter learned to handle long match expressions without going feral.

+ Added
  • state primitive with declarative transitions, guards, and terminal states 3c9ff21
  • Compile-time reachability analysis for state machines (unreachable states are errors) 5a8e042
  • Deadlock detection across when guards and external triggers e1b3c84
  • std/time with deterministic test clocks and wall-clock access 22f790a
~ Changed
  • Formatter wraps match arms across multiple lines when total width exceeds 80 cols 7d44b91
  • Loader now reports cyclic imports with the full cycle path, not just the entry edge 198cda7
✓ Fixed
  • Type inference no longer panics on empty struct literals f44e10b
  • Codegen produces correct Go for Result types nested 3+ levels deep cc81023

Streams & backpressure.

First-class stream primitive with typed yields and bounded buffers.

+ Added
  • stream keyword with yield expressions and explicit buffer sizing 11ee03f
  • Stream consumers via for x in stream with backpressure semantics 8f12ab9
  • std/llm with mockable prompt and stream APIs a0c4d51
✓ Fixed
  • Lexer now correctly handles UTF-8 identifiers in error spans d7fa118
  • cleat fmt -w no longer rewrites files when no formatting changes are needed 3c2906e

The effect system arrives.

The single largest design change in Cleat's life so far: needs becomes a first-class part of the type system, not an annotation.

+ Added
  • needs { ... } clause on functions, tools, and methods — required when calling effectful operations 2bb44e0
  • Effect inference for top-level fn main() with helpful diagnostic when missing 61a039c
  • Effect aliases via type io = needs { fs, log } for grouping common combinations c4d7e88
! Breaking
  • All stdlib packages that touch the outside world now require effect declarations. Migration is mechanical but every existing program will need updates bb71f29

Test runner improvements.

Quality of life on the testing path — better filtering, better output, better failures.

+ Added
  • cleat test --filter "pattern" for selective test execution a91e220
  • Test output now groups by package with a per-package pass/fail summary 4f7e88c
✓ Fixed
  • Failing assertions now print expected vs actual values, not just "false" 7c20e93
  • Test discovery no longer skips files with leading underscores e88af19
¶ Docs
  • Added testing guide and cookbook of common patterns to docs site
  • Standard library reference now includes effect requirements for every function

Multi-package modules.

Cleat learns to look across files. Loader, import resolver, and the foundations of the standard library all land in this release.

+ Added
  • Multi-file package loader with deterministic import resolution 90a3c7f
  • import "std/json", "std/http", "std/strings" as the first stdlib packages 2c8e144
  • tool primitive with timeout and retry as comment-form decorations (later promoted to keywords in 0.1.0) 5e62a99
  • Public/private visibility based on identifier capitalization f1bca37
− Removed
  • The single-file-only mode is gone. All programs now use the multi-package model, even one-file scripts 3a78d20
Earlier releases (0.0.1 – 0.0.4) available in the GitHub release archive