From machin
Helps decide if Machin (MFL) fits your project and bootstraps a small, deployable backend/CLI/webhook with a static binary. Covers tradeoffs vs Go/Node/Python and provides a zero-to-shipped quickstart.
How this skill is triggered — by the user, by Claude, or both
Slash command
/machin:machin-startThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
machin (MFL) compiles a Go-flavored, type-inferred language **through C** to one
machin (MFL) compiles a Go-flavored, type-inferred language through C to one native binary. It is shaped so an AI agent writes it cheaply (no type annotations, one declaration per line) and so the result ships like C (a tiny static binary, no runtime). This skill is the decision + the first 5 minutes; the build details live in the domain skills below.
…you want a small, self-contained service or tool you have to deploy, and the
stack is still open. The measured case (bench/ in the repo — reproduce, don't
trust):
| axis | machin | vs the usual |
|---|---|---|
| agent writes it | a REST+SQLite API in ~390 tokens | ties Python, ~36 % fewer than Go |
| runs | native, unboxed, no VM | wins fib & integer loops vs Rust -O3 / Zig, ties on float, ~1.4× behind on array-heavy |
| ships | 92.9 kB image · 0.49 ms cold start · 0.1 MB RAM (pure compute; a SQLite app ships FROM scratch too via --static, ~1 MB; TLS still needs OpenSSL — see ship step) | 1916× smaller / 59× faster start / 477× less RAM than Node |
Concretely a fit for: a JSON/REST API, a CLI or filter, a webhook receiver, a cron
/ daemon, an internal tool, a static-site or single-page app backend, a database
client — anything where "one binary on a $4 VPS, no Docker, no node_modules, no
pip install" is the point. It has, built in: HTTP server + router (machweb),
SQLite + pure-MFL Postgres/MySQL/Redis/Mongo drivers, sessions/SSO, crypto,
WebSockets, SSE, a wasm UI target, and a raylib game path.
Be honest, or you waste the user's time:
When it doesn't fit, say so and use the right tool. machin's pitch is narrow and real; don't oversell it.
# 1. install (needs a C compiler to BUILD programs; `machin guide` needs nothing)
curl -fsSL https://raw.githubusercontent.com/javimosch/machin/main/install.sh | sh
machin guide # the version-exact language catalog (read this)
A complete REST + SQLite service (app.src) — create / list / get / delete:
type Note struct { id int title string body string }
func handle(db, req) (res) {
if req.method == "POST" {
if req.path == "/notes" {
n := parse(req.body, Note{})
sqlite_exec(db, "INSERT INTO notes(title,body) VALUES(?,?)", []string{n.title, n.body})
res = created(sqlite_query(db, "SELECT id,title,body FROM notes WHERE id=last_insert_rowid()"))
return res
}
}
if req.method == "GET" {
if req.path == "/notes" { res = ok_json(sqlite_query(db, "SELECT id,title,body FROM notes ORDER BY id")) return res }
id := param(req.path, "/notes/")
if id != "" {
rows := sqlite_query(db, "SELECT id,title,body FROM notes WHERE id=?", []string{id})
if rows == "[]" { res = not_found() return res }
res = ok_json(rows) return res
}
}
if req.method == "DELETE" {
id := param(req.path, "/notes/")
if id != "" { sqlite_exec(db, "DELETE FROM notes WHERE id=?", []string{id}) res = ok_json("{\"deleted\":" + id + "}") return res }
}
res = not_found()
}
func main() {
db := sqlite_open("notes.db")
sqlite_exec(db, "CREATE TABLE IF NOT EXISTS notes(id INTEGER PRIMARY KEY, title TEXT, body TEXT)")
serve(8080, func(req) { return handle(db, req) })
}
# 2. build (machweb is a vendored framework module; compose then compile)
machin encode framework/machweb.src app.src > app.mfl
machin build app.mfl -o app # a small native binary (dynamic glibc, ~44 kB)
./app # serving on :8080
# 3. ship it:
# (a) DEFAULT: the small dynamic binary above (~50 kB). Links libc + libsqlite3
# (+ libssl if you use the HTTPS client) — all present on any normal Linux box.
# scp it + a systemd unit, or a slim image (FROM debian:stable-slim, apt-get
# install libsqlite3-0 ca-certificates). The common case, plenty small.
# (b) FROM scratch: `--static` bundles SQLite (the amalgamation) in, so a REST+SQLite
# app links nothing. Pair with musl for a libc-free, zero-dep binary:
printf '#!/bin/sh\nexec musl-gcc -static "$@"\n' > muslcc && chmod +x muslcc
CC=./muslcc machin build --static app.mfl -o app # statically linked -> FROM scratch (~1 MB)
# Dockerfile: FROM scratch / COPY app /app / ENTRYPOINT ["/app"]
# (TLS apps using the HTTPS client still need OpenSSL — native TLS is tracked in #260.)
machin guide --skill backend — JSON APIs, the five pooled DB drivers, sessions,
SSO, agent-first CLIs, daemons.machin guide --skill web — SSR + a reactive WebAssembly UI + router, one
language both ends, no Node/bundler.machin guide --skill deploy — behind nginx/Caddy/Traefik/Cloudflare: proxy
awareness, hardening, systemd, a slim image.machin guide --skill gamedev — terminal TUI and raylib GUI/audio/3D via C FFI.machin tools are consumed by agents: stdout = JSON answer, stderr = structured
errors, semantic exit codes, non-interactive. Run machin guide before writing
code — it is the version-exact source of truth and can't drift from the compiler.
Guides completion of development work by verifying tests, detecting environment, and presenting structured options for merge, PR, or cleanup.
Enforces test-driven development: write failing test first, then minimal code to pass. Use when implementing features or bugfixes.
Guides creation and editing of skills using test-driven development with pressure scenarios and subagents to verify agent compliance.
npx claudepluginhub javimosch/machin --plugin machin