Xyntetik Runner – a GGUF runtime in plain C that proves what it runs Xyntetik Runner, a GGUF model runtime written from scratch in plain C, is now available as a free Apache 2.0-licensed engine that serves, verifies, scores, adapts, and trains GGUF models deterministically, with support for CPU (x86 AVX2/FMA, ARM NEON), CUDA, and Metal. The project, built in Sweden and bootstrapped by consulting and enterprise work, emphasizes verifiable claims and compatibility with llama.cpp formats, including adapters that score identically (1.000 on held-out eval) when served by stock llama.cpp. One binary is the whole model runtime: it serves, verifies, scores, adapts and trains GGUF models - deterministically, with every claim tied to a measurement you can re-run. Written from scratch in plain C. No Python, no pip, no third-party runtime, no ggml. CPU x86 AVX2/FMA, ARM NEON , CUDA, and Metal. curl -LO https://github.com/Joakimpalm-Zen/xyntetik-runner/releases/latest/download/runner-macos-arm64 curl -LO https://github.com/Joakimpalm-Zen/xyntetik-runner/releases/latest/download/SHA256SUMS shasum -a 256 --check --ignore-missing SHA256SUMS chmod +x runner-macos-arm64 && mv runner-macos-arm64 runner curl -L -o model.gguf https://huggingface.co/ibm-granite/granite-4.1-3b-GGUF/resolve/main/granite-4.1-3b-Q8 0.gguf ./runner -m model.gguf --serve curl localhost:8080/v1/chat/completions \ -d '{"messages": {"role":"user","content":"Say hello in one sentence."} }' Linux: the asset is runner-linux-x86 64 and the check command is sha256sum -c --ignore-missing . Windows: runner-windows-x86 64.exe . The checksum line is not decoration - this project's whole culture is receipts, and it starts at the download. The model above is the smallest that passes this project's fidelity gate against its own BF16 parent; alternatives and the reasoning are in the quick start build-from-source below. macOS note: the binaries are not yet notarized. A curl download runs as shown; a browser download gets quarantined by Gatekeeper - clear it with xattr -d com.apple.quarantine runner or right-click → Open once. Testing Runner? The project is pre-1.0 and hardware coverage is still limited - that is an invitation, not an apology. If you have an NVIDIA/Apple setup, an unusual GGUF, a coding agent, or a model family not in the support matrix support-matrix , the result is genuinely wanted, success or failure alike: open an issue /Joakimpalm-Zen/xyntetik-runner/issues with runner --version , runner --caps , the model's exact filename and the load log. Independent reproductions of the determinism claims get credited in the docs, as the first one already is. Contents: try it sixty-seconds-to-a-served-model · why Runner why-this-and-not-llamacpp · what it adds what-runner-adds · training adaptation · models models-and-conversion · APIs serving-and-apis · support matrix support-matrix · CLI reference command-line-reference Xyntetik Runner is independent and bootstrapped: the engine is free forever under Apache 2.0 - consulting and enterprise work fund the hardware. Built in Sweden, runs on your hardware; your data never leaves the building. Use llama.cpp - it is the ecosystem, and Runner deliberately rides its formats rather than competing with them: GGUF in, llama.cpp-convention adapter files in and out. An adapter Runner trains scores identically 1.000 on its held-out eval served by stock llama.cpp, and community F16 adapters load straight back into Runner - both measured, not assumed. What Runner adds is not a longer feature list; it is a set of contracts the ecosystem does not make. Determinism as a hard promise: the same executable and inputs reproduce the same sampled tokens across runs and thread counts, and training reproduces the same adapter file sha256, gated in CI. Independent rebuilds are explicitly outside that byte-identity claim because compiler and ISA libm can differ. Scope as a promise: supported architectures are named, unknown ones are refused, and every backend claim is tied to an executable gate and pinned model evidence. Honesty as an artifact: the benchmark tables below include the rows where Runner loses, and the docs keep the failed experiments. If you want maximum architecture coverage and raw speed, use llama.cpp and we mean that sincerely. If you need to prove what your model said, what it learned from, or what you actually shipped - that is what this runtime is for. For release history and benchmark narratives, see CHANGELOG.md /Joakimpalm-Zen/xyntetik-runner/blob/main/CHANGELOG.md and docs/benchmarks.md /Joakimpalm-Zen/xyntetik-runner/blob/main/docs/benchmarks.md . Download a prebuilt binary from the latest release /Joakimpalm-Zen/xyntetik-runner/releases/latest for Linux, macOS, or Windows, or build from source: git clone https://github.com/Joakimpalm-Zen/xyntetik-runner cd xyntetik-runner make ./runner --version - runner 0.3.0 CUDA builds and releases need only an NVIDIA driver at runtime. The CUDA toolkit is needed only by developers regenerating the embedded PTX. GPU driver requirement - raised.GPU execution now requires an NVIDIA driver withCUDA 13.0 support or newer the R580 driver series . The embedded PTX is generated by the CUDA 13.0 toolchain PTX ISA 9.0 to add the BF16 and Q2 K device kernels; older drivers - the previous floor was the CUDA ~11.8 era - will fail to JIT it, and the runner then reports the failure andfalls back to CPUrather than computing wrong. CPU-only execution is unaffected. Check your driver's CUDA level with nvidia-smi top-right "CUDA Version" . Release archives name the binary for their platform - runner-macos-arm64 , runner-linux-x86 64 , runner-windows-x86 64.exe - so either rename it to runner or substitute that name in the commands below. A source build produces runner directly. If you have no GGUF handy, the measured recommendation at 8 GB is an 8-bit small model, not a 4-bit larger one. granite-4.1-3b Q8 0 3.6 GB, first-party IBM file is the smallest model that passes this project's fidelity gate against its own BF16 parent 100% margin-qualified top-1 / 0.0024 mean KLD, 2026-08-14; every 4- and 5-bit quant measured to date fails on distributional distance : curl -L -o model.gguf \ https://huggingface.co/ibm-granite/granite-4.1-3b-GGUF/resolve/main/granite-4.1-3b-Q8 0.gguf For the fastest possible smoke test on a small machine there is also a 2.63 GB option - know what it is: measured against its own BF16 parent it agrees on 77.75% of tokens mean KLD 0.286 , a try-the-runner artifact, not a faithful gemma-4-E2B; its card carries the full numbers. curl -L -o model.gguf \ https://huggingface.co/Joakimpalm-Zen/gemma-4-E2B-it-Q4 0-GGUF/resolve/main/gemma-4-E2B-it-Q4 K M-Q4 0-mix.gguf Run a GGUF: ./runner -m model.gguf -i ./runner -m model.gguf -p "Explain prefix caching" --temp 0 ./runner -m model.gguf --serve --parallel 2 ./runner -m model.gguf -p "Return a status object" --json ./runner -m model.gguf -f big-document.txt -c 8192 -n 200 ./runner -m big.gguf --draft small.gguf -p "Continue this code" Pre-1.0 APIs, model coverage and certification envelopes may change between releases. CI builds and smoke-tests Linux, macOS, and Windows, but the project still has limited hardware coverage. Include 0.3.0 . runner --version , runner --caps , the model's exact filename, and the load log in issue reports. Read SECURITY.md for the threat model and CONTRIBUTING.md for the required correctness gates. The contracts above, made concrete. The two capabilities that matter most have their own sections below; the rest follow as a list, ordered by how much difference each makes in practice. When a tool call runs past its token budget, most engines return an empty or malformed tool calls - commonly finish reason: "length" with nothing usable, or truncated JSON the caller cannot parse and has to repair or retry. Runner closes the call to the smallest schema-legal document instead, so the arguments still parse. This is forced-truncation recovery , not ordinary JSON-Schema constrained decoding: once a document starts, Runner emits a legal ending when the budget expires. On local models, where context is tight and generation is slow, it is the difference between an agent loop that finishes and one that retries from scratch - burning tokens, time, and context window. What each engine hands the caller when the token budget cuts a tool call short - same box, same tool schema, same prompt, tool choice:"required" , temperature 0, budgets 1→64: | engine | budget too small 1–16 tokens | enough budget 64, control | |---|---|---| Runner | executable tool calls , arguments parse | completes | | vLLM 0.27.1 | no call; protocol framing leaks into content | completes | | llama.cpp b10488 | no call; leak, then tool calls with unparseable args | completes | | Ollama 0.32.14 | no call; empty content, then HTTP 500 | completes | | TensorRT-LLM 1.2.1 † | no call;