Skip to content
mlx-bun 1.0.0 is beta and actively developed. APIs may change; breaking changes will be called out in release notes.

Local AI on Apple Silicon

mlx-bun is an MLX inference engine, an OpenAI and Anthropic compatible server, a browser app, and TypeScript libraries for Bun. Bit-exact with mlx-lm on validated configurations. No Python.

curl -fsSL https://mlx-bun.dev/install.sh | sh

Runs on Apple Silicon Macs with macOS 14 or later. MIT licensed.

One command downloads models, serves them, generates, quantizes, trains and transcribes. The map above is the whole product.

  • Inference engine

    Runs the model graph on the GPU through MLX and Metal. The Neural Engine programs a model uses are compiled by the installer, or before the first model load that needs them. Validated configurations reproduce mlx-lm’s logits bit for bit.

  • Local server

    Chat and text completions, Anthropic Messages, OpenAI Responses, embeddings, audio transcription and decisions on localhost:8080, over one continuous batching scheduler with paged and quantized KV caches, speculative decoding and runtime LoRA adapters. Every route is in the HTTP API reference.

  • Browser app

    Chat with tools and saved sessions, manage and download models, transcribe audio, quantize checkpoints, train adapters, generate datasets, and watch metrics and benchmarks. It opens when the server starts.

  • Libraries

    @mlx-bun/mlx, inference, quantize, training and hub on npm: loading and generation, plus the kernels, layers, graphs, state, sampling and training they compose. Start with the library guide.

  • Terminal

    get, serve, generate, embed, convert, train, fuse, transcribe and fit. Every command and flag is in the CLI reference, generated from the source.

Requires an Apple Silicon Mac running macOS 14 or later. Every option provides the mlx-bun command.

Terminal window
curl -fsSL https://mlx-bun.dev/install.sh | sh

Downloads the signed, notarized bundle with its runtime and native libraries, then compiles the Neural Engine programs your Mac’s models use. See the installer options.

  1. Serve a model. Download one from Hugging Face and serve it, or run mlx-bun with no arguments to serve a cached model, downloading a starter on first run.

    Terminal window
    mlx-bun get mlx-community/gemma-4-e4b-it-OptiQ-4bit
    mlx-bun serve e4b
  2. Send a request. The browser app opens on port 8080, and the API answers beside it.

    Terminal window
    curl http://localhost:8080/v1/chat/completions \
    -H 'Content-Type: application/json' \
    -d '{"messages": [{"role": "user", "content": "Hello!"}], "max_tokens": 128}'
  3. Or generate once, without a server.

    Terminal window
    mlx-bun generate e4b "Write a haiku about Apple Silicon."

The quickstart continues from here.

Built to be trusted first, then embedded.

  • Bit-exact numerics

    Validated configurations reproduce mlx-lm’s logits bit for bit, and mlx-optiq’s for mixed-precision KV. Correctness is a published contract with evidence, not a benchmark table.

  • Native on your Mac

    Metal does the math. The standalone bundle is signed, notarized and ships its own runtime, so there is no Python environment to manage and no API key to keep.

  • Nothing to rewrite

    Chat Completions, Messages, Responses, embeddings and transcription keep their wire formats. Existing agents, tools and SDK code keep working after changing one URL.

  • Composable

    Every layer is a public subpath: kernels, layers, graphs, caches, sampling, generation. The caller owns weights and state, and using disposes them. The whole server embeds with mlx-bun/server.

  • Memory aware

    Fit estimates before a model loads, residency by memory budget across models, paged and quantized KV, prompt caches that persist to SSD, and continuous batching for every request.

  • Private by default

    Downloaded models stay in the Hugging Face cache on your Mac; converted models, adapters, chats and KV state live under ~/.mlx-bun. Nothing leaves your Mac unless you fetch or upload something yourself.

Use Jev or OpenAI Decisions-compatible endpoints with any supported local language model, sharing the same loaded weights as generation.

POST /v1/decisions accepts OpenAI’s Decisions request. POST /v1/systemone accepts the System One format of Jev, TypeSafe AI’s decision model. Ask predicate questions (yes or no; Jev calls them noul), choice questions and score questions about text, or about an image with a vision model, and get the answer, a probability for every option and a confidence.

Every answer is scored from the loaded model’s own likelihood of that answer. No token is sampled and nothing needs tuning. Keep the OpenAI or TypeSafe SDK and change baseURL; name a model that GET /v1/models lists with capabilities.decisions.

import OpenAI from "openai";
const openai = new OpenAI({ apiKey: "local", baseURL: "http://localhost:8080/v1" });
const { answers } = await openai.decisions.create({
model: "mlx-community/gemma-4-e4b-it-OptiQ-4bit",
input: "I was charged twice for my order.",
questions: [{
type: "choice", name: "department",
instructions: "Which department should handle this complaint?",
choices: [
{ value: "billing", description: "Payments, invoices, and refunds." },
{ value: "technical", description: "Problems using the product." },
{ value: "shipping", description: "Delivery and tracking." },
],
}],
});

The HTTP example and the SDK examples run against a local server; the HTTP API reference lists both routes.

The @mlx-bun/ packages are TypeScript on npm. They run on Bun 1.4.2 or later, with their native libraries inside the archives.

Terminal window
bun add @mlx-bun/inference
packages/inference/examples/qwen3-generate.ts
import { bindGraphCaches } from "@mlx-bun/inference/models";
import { phaseRowLimit } from "@mlx-bun/inference/models/graph";
import { loadModelConfig, Weights, loadTokenizer, generate, resolveComposition } from "@mlx-bun/inference";
import { Qwen3Model } from "@mlx-bun/inference/models/qwen3";
/** The caller chooses a Qwen3 checkpoint and owns its weights. */
export async function generateText(directory: string, prompt: string, maxTokens = 32) {
const config = await loadModelConfig(directory);
const tokenizer = await loadTokenizer(directory);
const weights = await Weights.open(directory);
try {
const graph = bindGraphCaches(new Qwen3Model(weights, config, phaseRowLimit(resolveComposition(config))), resolveComposition(config));
const generation = generate(graph, tokenizer.encode(prompt), {
maxTokens, temperature: 0, eosTokenIds: config.eosTokenIds,
});
const tokens: number[] = [];
for await (const { token } of generation) tokens.push(token);
return { text: tokenizer.decode(tokens), tokens, stats: generation.stats };
} finally {
weights.dispose();
}
}

The tested example from the inference package, rendered from its source at build time. The caller owns the model, the inputs and every resource’s lifetime.

  • @mlx-bun/mlx

    Arrays, operations and native resource ownership over MLX.

  • @mlx-bun/inference

    Graphs, loading, preprocessing, generation, embeddings, transcription and memory fit.

  • @mlx-bun/quantize

    Calibration, sensitivity, mixed-precision allocation, rotation and Trellis packing.

  • @mlx-bun/training

    LoRA and preference training, optimizers, losses and adapter production.

  • @mlx-bun/hub

    The local model registry and Hugging Face downloads and uploads.

  • mlx-bun/server

    The app’s server, engine and model selection as importable entries.

The library API lists every public subpath, export and signature.

Download any of them from Hugging Face with mlx-bun get. Compatibility claims apply to named artifacts and configurations.

Targeted graphs
Gemma 4, DiffusionGemma, GLM 5.2, Qwen 3, Qwen 3.5, Qwen 3 MoE, MiniCPM 5 and Whisper.
Generic dense graph
The architectures mlx-lm’s universal path knows: Llama, Mistral, SmolLM 3, Qwen 2, Gemma, Gemma 2, Phi 3, OLMo 2, GLM 4, Granite and StarCoder 2.

We publish Qwen3.8-27B-Trellis-3.2bpw, a 27B Qwen model in mlx-bun’s packed Trellis format. The full download is about 12.25 GB; running it needs additional memory for inference. This is an optional larger model, separate from the first-run starter. See the model card for requirements, evaluations and usage.

The CLI, HTTP and configuration references are generated from the code at build time, and the library API from the public exports.