A language shaped for AI agents to write and edit cheaply: zero type annotations, one canonical declaration per line, every design choice measured for token cost. Compiles through C to a single native binary — C/Rust-class speed, unboxed values, no runtime.
Spec · Language tour · Agent guide · Contributing · Ecosystem → awesome-machin · Landing · Releases
Write MFL, hit Run — it compiles to WebAssembly and runs client-side. No install.
The whole toolchain — lexer, parser, type checker, C code generator, and
encode/build/run— is written in machin (selfhost/, ~4k lines). It compiles its own source back into itself, and the rebuild reproduces itself byte-for-byte — a genuine compiler fixpoint — at ~0.9× the original's speed. A language mature enough to build itself from scratch, verified to the byte. Every stage was built against a byte-diff oracle, which flushed out three real compiler bugs along the way. CI enforces it on every push — the fixpoint, a 415-program codegen oracle diffed against the reference compiler, and the embedded runtime being in sync — so this is a checked claim, not a milestone someone once reached. Seeselfhost/andBOOTSTRAP.md.
The pitch in one table. The same REST + SQLite API (POST / GET / DELETE /notes) written idiomatically in each language, then measured for what actually
costs an AI agent: tokens to write, and tokens to edit. All three build and
pass the same CRUD test (bench/rest-sqlite).
| author tokens | edit tokens | ships as | |
|---|---|---|---|
| machin | 388 | 290 | 44 KB static binary · 0 deps |
| Go | 527 · 1.36× | 329 · 1.13× | 14.8 MB binary + module deps |
| Python | 383 · 0.99× | 332 · 1.14× | source + CPython interpreter |
machin is as terse as Python to write, ~36 % cheaper than Go, lowest on
edit cost — and the only one that ships as a single 44 KB native binary with
SQLite, the HTTP server, and the router built in. No interpreter, no go mod,
no container. Write it like a script, ship it like C. That combination — not a
raw token count — is the whole idea. (o200k_base; cl100k_base gives the same
ranking. Reproduce: python3 bench/rest-sqlite/measure.py.)
…and then it ships in a way an interpreter can't (bench/cold-start):
| same HTTP server | deployable image | cold start | idle RSS |
|---|---|---|---|
machin (static, FROM scratch) |
92.9 kB | 0.49 ms | 108 kB |
Node (.js + node:alpine) |
178 MB · 1916× | 28.9 ms · 59× | 51 MB · 477× |
Python (.py + python:alpine) |
47.6 MB · 512× | 49.1 ms · 100× | 17.9 MB · 166× |
A 92.9 kB image — the binary and nothing else — that's serving traffic in half a millisecond on ~0.1 MB of RAM.
Every mainstream language was designed for human ergonomics — readable syntax, explicit types, multi-line formatting. For an AI agent, every output token costs, and that human-friendly ceremony taxes the writer without adding meaning. machin measured this: tools/tokcost.py showed base64 source costs ~2.5× the tokens to output; whitespace alone costs ~13%. The canonical one-line-per-declaration form, with every type inferred, is the end of that measurement — the smallest token surface that still produces C/Rust-class native code with zero runtime overhead.
The form should be measured, not asserted. tools/README.md is the entry point to the instruments behind that: tools/tokcost.py (write/edit token cost of a source form), tools/tokmin.py (where MFL spends tokens and what a minimization would save), and tools/reliability/ — the other half of the metric, since real cost is tokens × tries: it measures whether a syntax change makes a model write the code wrong more often, not just whether it's shorter.
Agents: run
machin guidefor the complete, version-exact feature surface — every keyword, every builtin with its signature, the core idioms, and the gotchas, as JSON (--textfor prose). Emitted from the compiler's own catalog; can't drift from the implementation. Depth lives inSPEC.mdandAGENTS.md.
.mfl is plain canonical text: one normalized declaration per line, whitespace tightened. Greppable, diffable, no type annotations. A minimal illustration (not a transcript of any specific file — see examples/demo.mfl for a fuller runnable program):
func fib(n){if n<2{return n}return fib(n-1)+fib(n-2)}
func main(){println(fib(10))}
A dense machin pack form exists for distribution; machin run reads either.
curl -fsSL https://raw.githubusercontent.com/javimosch/machin/main/install.sh | sh
machin guide # learn the language (version-exact catalog, JSON)Installs the latest release binary to ~/.local/bin (override with MACHIN_INSTALL).
machin compiles MFL through C, so building programs needs a C compiler (cc
by default — set CC to override it, e.g. CC=clang machin build app.mfl -o app); the
--target wasm web target additionally needs zig. Building
web apps? See the machin-web skill.
Prefer to fetch the binary yourself? Every release
ships static linux/darwin × amd64/arm64 binaries plus a SHA256SUMS.txt:
curl -fsSLO https://github.com/javimosch/machin/releases/latest/download/machin-<tag>-<os>-<arch>
curl -fsSLO https://github.com/javimosch/machin/releases/latest/download/SHA256SUMS.txt
sha256sum -c SHA256SUMS.txt --ignore-missing # verify before running
chmod +x machin-<tag>-<os>-<arch>The C compiler requirement above still applies to a downloaded binary — it's needed
at run/build time regardless of how machin itself got installed.
Install machin's agent skills as a Claude Code plugin, so an AI agent reaches for machin at the right moment — in any project:
/plugin marketplace add javimosch/machin
/plugin install machin@machin
You get machin-start (when to reach for machin, and a zero→running→shipped
quickstart, with the measured benchmarks as decision criteria) plus the web / backend
/ gamedev / deploy how-tos — they auto-activate by intent. For any other agent runtime,
machin skill install writes the same skills to a vendor-neutral ~/.agents/skills.
make build # …or build from source (needs Go 1.22 + a C compiler)
bin/machin run examples/demo.mfl # compile to native + execute
bin/machin build app.mfl -o app # standalone native binary
bin/machin build app.mfl --emit-c # print the generated C
bin/machin build app.mfl --safe # + bounds / div-zero / overflow checks
bin/machin build|run app.mfl --race-safe # refuse to build if a data race is inferred
bin/machin encode a.src b.src > app.mfl # mint canonical .mfl from loose Go-like text
bin/machin pack app.mfl # dense base64 form (distribution)
bin/machin guide --text # print the full feature catalog for agents- Concurrency: goroutines + channels +
select; per-goroutine arena GC + scopedarena{};--safechecks - Networking: TCP client/server, native TLS, WebSocket client + server (RFC 6455)
- Databases: SQLite builtins; pure-MFL Postgres / MySQL / Redis / MongoDB clients — no C libs, connection pooling
- Web:
machwebHTTP framework (router, cookies, SSO, SSE streaming, file uploads, proxy hardening) + reactive wasm frontend - CLI:
flags.src— a composable flag parser (short/long flags, bools,=/space values) - Crypto: SHA-256, HMAC, HKDF, Ed25519, X25519, AES-GCM/CBC — binary and text paths
- Compression:
zlib_compress/zlib_decompressover rawbytes - C FFI:
externblocks, by-value structs, opaque handles — real raylib 3D games
Full surface and grammar: SPEC.md. Runnable programs: examples/.
Things built with machin — the curated list is awesome-machin:
- machin-mail — SMTP send + local catch/sink (à la MailHog), pure MFL over TCP
- machin-rooms — real-time WebSocket chat server, one binary
- machin-deploy — production reference (systemd, Docker, nginx/Caddy)
- machin-healthcheck — concurrent HTTP status/latency checker
- machin-ssg — static-site generator (markdown → HTML)
Built something? Add it to awesome-machin.
machin compiles through C, so it runs in the native tier, not the scripting tier.
On four kernels with byte-identical output, timed interleaved against Rust -O3 and
Zig ReleaseFast (min of 9 rounds, this machine):
| fib(40) | mandelbrot 1000² | sieve 10⁷ | intsum 10⁹ | |
|---|---|---|---|---|
| machin | 214.7 ms | 724.2 ms | 202.0 ms | 3079.7 ms |
Rust -O3 |
289.7 ms | 720.1 ms | 142.9 ms | 3223.8 ms |
| Zig fast | 292.9 ms | 702.8 ms | 137.9 ms | 3189.7 ms |
Wins 1, ties 2, and the sieve now ties Rust too (it still trails Zig by ~1.19×).
Unboxed values, no interpreter, no VM. The sieve gap was never slice indexing —
that loop always tied Rust; it was append copying into a fresh block on every
growth, fixed in #578 by proving
a slice unaliased and then growing it in place. The table above predates that fix.
Where machin beats Rust: binary size — 14 kB stripped vs 335 kB, both dynamic.
Read that as a fixed offset (Rust starts ~320 kB ahead), not a ratio: machin's hello
world and its fib are the same size to the byte, so both numbers measure each
toolchain's floor. It does not beat Zig here — Zig 0.15.2's fully static binary
is 16 kB, and machin's own --static build is 940 kB.
And compile-time bug reports — a guaranteed deadlock that rustc and zig
accept silently and then hang on, machin reports as DL001 before you run it.
Where it loses: build time (Rust ~57 ms vs machin ~100 ms) and default
runtime safety (machin, like Zig ReleaseFast, omits bounds checks unless you
pass --safe; Rust traps by default).
Full numbers, methodology, and the losses in detail: docs/BENCHMARKS.md.
MIT — Javier Leandro Arancibia
- Crevisto — 100+ AI image tools, pay-per-use, no subscription. CLI + web app.

