Skip to content
javimoschPublic

About

MFL — a machine-first language: as terse as Python for an AI agent to write, but compiles through C to a single tiny native binary with HTTP, SQLite, and crypto built in. C/Rust-class speed, zero runtime, zero deps.

Resources

Contributing

Stars

13 stars

Watchers

0 watching

Forks

Latest commit

 

History

582 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

machin

Version License Go Native Compiles itself

machin ⎯ Machine-First Language (MFL)

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.

🧬 machin is written in machin — a self-hosting compiler

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. See selfhost/ and BOOTSTRAP.md.

machin: write a REST+SQLite service, compile to a tiny native binary, run it

Same service, measured

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.

Why

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.

Measurement

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 guide for the complete, version-exact feature surface — every keyword, every builtin with its signature, the core idioms, and the gotchas, as JSON (--text for prose). Emitted from the compiler's own catalog; can't drift from the implementation. Depth lives in SPEC.md and AGENTS.md.

The form

.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.

Install

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.

Use it from Claude Code

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.

Use

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

Capabilities

  • Concurrency: goroutines + channels + select; per-goroutine arena GC + scoped arena{}; --safe checks
  • 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: machweb HTTP 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_decompress over raw bytes
  • C FFI: extern blocks, by-value structs, opaque handles — real raylib 3D games

Full surface and grammar: SPEC.md. Runnable programs: examples/.

Ecosystem

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.

Performance

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.

License

MIT — Javier Leandro Arancibia

Built with machin

  • Crevisto — 100+ AI image tools, pay-per-use, no subscription. CLI + web app.

About

MFL — a machine-first language: as terse as Python for an AI agent to write, but compiles through C to a single tiny native binary with HTTP, SQLite, and crypto built in. C/Rust-class speed, zero runtime, zero deps.

Resources

Contributing

Stars

13 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages