Skip to content
Sakura Lang
pre-alphaM0 to M2 run on JavaScript

Code that keeps its promises.

Sakura Lang is the language agents write. Every signature declares its effects, errors and contracts, and the compiler holds the code to them.

agents GET /llms.txt, or any page + .md

The signature is the contract.

Five lines a person can review. The compiler holds the body to every one of them.

src/accounts.sakura
  1. fn withdraw(acct: Account, amount: Cents)

    Takes.Typed inputs. Cents is a refinement: an Int that is never negative.

  2. -> Account

    Returns.The updated account. Nothing else comes back.

  3. ! {Ledger, Fail<Overdrawn | Frozen>}

    May do.Only Ledger: no network, files or clock. It fails in exactly two named ways.

  4. requires positive: amount > 0

    Requires.The caller's duty. Breaking it is the caller's defect, D020.

  5. ensures result.balance == acct.balance - amount

    Ensures.The promise, checked on every return in every build, D021.

  6. { … }the body: checked against the clauses above, then out of the way
Reviewed by
a person, reading five lines
Held by
sakura check, on every change

Review promises, not diffs.

An agent can rewrite six hundred lines before you finish your coffee. Nobody reviews that well. In Sakura Lang, everything a function is allowed to do lives in its signature, so review shrinks to the lines that change a promise.

agent/billing-retries

5 files +612 −388

  • src/billing/retry.sakurakept
  • src/billing/ledger.sakurakept
  • src/billing/charge.sakurapromise changed

    Removed: pub fn charge(card: Card, amount: Cents) -> Receipt ! {Payments, Fail<ChargeError>}

    Added: pub fn charge(card: Card, amount: Cents) -> Receipt ! {Http, Payments, Fail<ChargeError>}

    charge now makes HTTP calls. That is a decision for a person, so the diff surfaces it, and nothing else.

  • src/billing/webhooks.sakurakept
  • test/billing_test.sakurakept
Illustrative review of an agent's change. The tooling is part of the design, not a shipped product.

Effects are requirements. Handlers answer them.

signup says it needs a database, a clock and a way to fail. It never says which. Whoever calls it installs handlers, so a test swaps the database for memory with no mocking library and no change to the code.

with sql_db() { Serve.listen(router, addr) }

sql_db()

clauses call Sql.sqlite

Db.exists(…)

Clock.​host()

reads the system clock

Clock.now()

try/catch

turns it into a 409

fail EmailTaken
DbClockFail

signup(email, pw) · the body is the same in both

EffectsHandlersHandlers are tail-resumptive: a clause returns the result once. No resume, no Async.

Authority only narrows.

An effect says what a function needs. The handler around it decides how much it gets. Root handlers come from the host, capped by sakura.toml; every with below can narrow that, and nothing can widen it. There is no ambient authority to import.

hosteverything the machine can do

sakura.toml [permissions]fs.read = ["./data"], net = [], the ceiling

main() ! {Console, Cli, Fs, …}root handlers for these effects only

with Fs.rooted(Dir.subdir(…, "data"))paths resolve inside ./data

word_counts(text) -> Map<String, Int>pure: no row, no authority at all

Scopes of authority for the CLI example in design §15.6, outermost first.
  • Fs.read("../.ssh/id_ed25519")FsErroroutside the rooted directory; symlink escapes are rejected too
  • main declares Http, net = []exit 75refused at startup, not at first use
  • a captured Dir outlives its withV6002capabilities cannot escape the scope that made them
  • Log.event(Level.Info, "{token}", [])V2031Secret<String> is not Show, so it can never be logged
Capabilities and security

Every claim says how it is known.

Sakura Lang never calls a program verified because it compiled. Each obligation gets exactly one status, and the tools report it.

  1. proved

    the type and effect checker, on every build

    • every effect has a handler
    • every Fail tag is caught or declared
    • every match is exhaustive
    • no null, no unchecked index
  2. runtime_checked

    a check at the boundary; a violation is a defect

    • requires ordered: lo <= hi
    • where it >= 0 && it <= 100
    • Int overflow
  3. tested

    sakura test, on the inputs that ran

    • property "normalize is idempotent"
    • sakura test --contracts
    • snapshots
  4. trusted

    assumed, and listed in the build manifest

    • @external bindings
    • @trust("reason")
    • host handlers

In v0 every contract is runtime_checked, in every build including --release. From M4, sakura verify can move a single obligation to proved and drop only that check. Contracts

How an agent works with Sakura Lang.

The compiler is the agent's other half. Every answer it gives is data a model can act on, and every change it would make says how far it reaches.

  1. writeagent

    drafts the body, leaves ?holes where it is unsure

  2. sakura check --jsoncompiler

    diagnostics and hole records as JSON Lines

  3. apply fixesagent

    local fixes go in; signature changes go to a person

  4. sakura testcompiler

    deterministic handlers, fixed seed, shrunk failures

  5. ↺ until check and test are clean
GET /llms.txt
# Sakura Lang > Sakura Lang is an agent-first programming language. Every signature declares its effects, errors and contracts, and the compiler seals them on every build. Sakura Lang is pre-alpha and nothing is released. The v0 language design is written (docs/design.md in the repository). The compiler builds from source and checks and runs M0 to M2 programs (effects, handlers, typed errors, holes) on JavaScript; the M3 standard library (http, sql, fs, cli, ai, task) is not built yet, so examples that use it do not run. Build it: https://sakura-lang.vercel.app/docs/quickstart - The core language for agents, in one file: https://github.com/icantcodefyi/sakura-lang/blob/master/docs/llms.txt- Every docs page is available as Markdown: append `.md` to its URL (for example https://sakura-lang.vercel.app/docs/tour/effects.md).- All docs in one file: https://sakura-lang.vercel.app/llms-full.txt ## Start- [Introduction](https://sakura-lang.vercel.app/docs): Sakura Lang is an agent-first, general-purpose programming language in which the signature is the contract.

Live from this site. Open llms.txt or llms-full.txt.

Diagnostic and hole records are what sakura check --json emits today; the MCP server is planned for M3.

Values, without a borrow checker.

Every value is independent: no aliasing, no lifetimes, no cycles. Native code (M5) counts references at compile time and updates a uniquely owned value in place. The JavaScript backend uses the host GC; the semantics are the same.

xs = List.push(xs, 4)1234rc = 1unique, so the buffer isreused in place: no copy

One binary for the whole loop.

Checker, runner, formatter and test runner already share one compiler library; packages, LSP and MCP join them in M3, with a standard library for HTTP, SQLite, JSON schemas, CLIs and typed LLM calls.

sakura check
types, effects, exhaustiveness, holes
sakura run
build to JavaScript and run main
sakura test
deterministic handlers, properties, snapshots
sakura fmt
one canonical format
sakura explain
any code, with a wrong and a fixed program
sakura prompt
the language guide for agents
sakura fix
fixes gated by impact classplanned
sakura mcp serve
the compiler as MCP toolsplanned

For code an agent writes, defaults decide.

Every language below can be written carefully. The question is what holds when nobody is being careful: what the compiler enforces by default.

  • Side effects in the signature

    Sakura Lang: Yes, checkedTypeScript: No, hiddenPython: No, hiddenRust: No, hiddenEffect-TS: Yes, R channel
  • Errors in the signature

    Sakura Lang: Yes, Fail<E> error unionsTypeScript: No, untyped throwPython: No, untyped raiseRust: Yes, ResultEffect-TS: Yes, E channel
  • No null, no exceptions

    Sakura Lang: YesTypeScript: Partly, strict nulls, throw remainsPython: No, None, raiseRust: Partly, Option, panics remainEffect-TS: Partly, JS throw remains
  • Memory without GC pauses or lifetimes

    Sakura Lang: Yes, native RC with reuse; JS GCTypeScript: No, tracing GCPython: Partly, RC plus cycle GCRust: Partly, no GC, lifetimesEffect-TS: No, tracing GC
  • Contracts and refinement types

    Sakura Lang: Yes, always checked at runtimeTypeScript: NoPython: No, runtime librariesRust: Partly, external verifiersEffect-TS: Partly, Schema, at runtime
  • Authority you grant, not ambient

    Sakura Lang: Yes, handlers grant authorityTypeScript: NoPython: NoRust: NoEffect-TS: Partly, services, not enforced
  • Taint and secret types

    Sakura Lang: Yes, Untrusted, SecretTypeScript: NoPython: NoRust: Partly, newtypes by conventionEffect-TS: Partly, Redacted
  • Diagnostics as data, with fixes

    Sakura Lang: Yes, fixes declare impactTypeScript: Partly, tsserver code fixesPython: Partly, varies by toolRust: Yes, JSON, applicable fixesEffect-TS: Partly, via TypeScript
  • One way to do each thing

    Sakura Lang: Yes, small grammarTypeScript: NoPython: Partly, by conventionRust: NoEffect-TS: No, many styles

enforced by default partly, or by convention or library not providedThe Sakura Lang column states design goals; the M0 to M2 parts run today.

Designed. Running in part.

The compiler checks and runs M0 to M2 programs on JavaScript today. M3 is under way, in the open, and nothing is released yet. Full roadmap

  1. M0Runs today

    Hello, effects

    Lexer, parser, Console, inference, CPS JavaScript, sakura run and sakura check --json.

  2. M1Runs today

    Pure language, typed errors

    Records, variants, exhaustive match, Fail with try/catch, std in Sakura Lang, tests, sakura fmt.

  3. M2Runs today

    Handlers and holes

    User effects and handlers, row variables, deterministic test handlers, typed holes.

  4. M3In progress

    Contracts and agents

    Runtime contracts, permissions, Secret and Untrusted, Task, Http, Sql, LSP and MCP.

  5. M4

    WASM and verify

    WASM backend; sakura verify discharges contracts with Z3 and drops proved checks.

  6. M5

    Native

    Cranelift backend with Perceus reference counting and in-place reuse.

Read the design. Then hold us to it.

The docs are written for people and for the agents that work with them. Every page is one fetch away as Markdown.