uv). No Terminal, no conda, no pain.MLX Forge covers the full model lifecycle: Discover โ Convert โ Quantize โ Evaluate โ Fine-tune โ Generate โ Serve โ Monitor โ Deploy. Three ideas hold it together:
mlx-lm, Swift MLX, CLI, or curl. Click around to learn; export code to productionize.uv; the app talks to them over JSON-RPC. You never manage a venv by hand.Navigate everything with the command palette โ โK.
Unified memory is the budget that matters on Apple Silicon. Estimate the footprint of a model before you download or quantize it:
Estimate includes weights + runtime overhead and a small KV-cache headroom; green = comfortable (โค75% of RAM). Long contexts need more.
The Discover view browses the Hugging Face hub in-app: search by name, filter by architecture and size, then pull a model with a resumable download. Everything lands in the Model Library โ your single organized inventory of base models, quantized variants and fine-tuned adapters, with disk usage and lineage for each.
The Conversion Studio turns compatible checkpoints into MLX format; the Quantization Studio then compresses them. Pick a bit-width, watch the size/quality trade-off, and read the exact command it maps to:
from mlx_lm import convert
convert(
hf_path="Qwen/Qwen3-14B",
mlx_path="./qwen3-14b-4bit",
quantize=True,
q_bits=4,
q_group_size=64,
)
mlx_lm.convert \
--hf-path Qwen/Qwen3-14B \
--mlx-path ./qwen3-14b-4bit \
-q --q-bits 4 --q-group-size 64
That code block above? That's the point โ the studio generated it from your clicks. Paste it in CI and the run is reproducible forever.
Before committing to a quantization, measure it. The Evaluation studio runs perplexity and benchmark suites against any model in your library and puts variants side by side:
Rule of thumb: 4-bit with group size 64 costs ~1โ3% perplexity on most 7B+ models โ usually invisible in chat, always visible in your RAM meter.
The Fine-tuning studio trains LoRA adapters on your own data with live loss curves and checkpointing โ the Datasets view handles importing, inspecting and splitting your training data first.
mlx_lm.lora \
--model ./qwen3-14b-4bit \
--train --data ./my-dataset \
--batch-size 2 --num-layers 16 --iters 1000 \
--adapter-path ./adapters/support-bot
{"messages": [{"role": "user", "content": "โฆ"},
{"role": "assistant", "content": "โฆ"}]}
Adapters live in the Model Library next to their base model โ fuse them or load them dynamically in the Playground and the server.
Chat and completion against any local model with full control: system prompt, temperature, top-p, max tokens, repetition penalty. Compare models side by side, and export any session as code. The Vision Lab, Image Studio and Audio Studio extend the same idea to multimodal models.
ForgeServer exposes any model on an OpenAI-compatible HTTP/SSE endpoint with generated API keys (mlxf-โฆ). The wire format is transcribed from the OpenAI OpenAPI specification and verified two ways: a golden test with the unmodified openai Python SDK completing a streamed chat, and structural golden-file comparison of response bodies.
from openai import OpenAI
client = OpenAI(base_url="http://localhost:8080/v1", api_key="mlxf-โฆ")
stream = client.chat.completions.create(
model="qwen3-14b-4bit",
messages=[{"role": "user", "content": "Hello!"}],
stream=True,
)
for chunk in stream:
print(chunk.choices[0].delta.content or "", end="")
curl http://localhost:8080/v1/chat/completions \
-H "Authorization: Bearer mlxf-โฆ" \
-H "Content-Type: application/json" \
-d '{"model": "qwen3-14b-4bit", "stream": true,
"messages": [{"role": "user", "content": "Hello!"}]}'
import OpenAI from "openai";
const client = new OpenAI({
baseURL: "http://localhost:8080/v1",
apiKey: "mlxf-โฆ",
});
const stream = await client.chat.completions.create({
model: "qwen3-14b-4bit", stream: true,
messages: [{ role: "user", content: "Hello!" }],
});
Manage everything from the Servers view: start/stop endpoints, rotate keys, watch request logs live.
The Cluster view discovers other Macs on your network via Bonjour (ForgeCluster) and fans work out to them โ turn a desk of Apple Silicon machines into one lab. The Pipelines view chains stages (convert โ quantize โ evaluate โ serve) into repeatable recipes, and Projects keeps each experiment's models, datasets and runs together.
Every studio has an Export code action producing the exact equivalent of what you just did visually, in four dialects:
| Target | Use it for |
|---|---|
Python mlx-lm | Notebooks, CI pipelines, training scripts |
| Swift MLX | Embedding inference in your own macOS/iOS apps |
| CLI | Shell scripts and quick reproduction |
| curl | Hitting your served endpoints from anything |
This is the app's core philosophy: the GUI teaches you the tool; the generated code makes it reproducible.
For the curious โ the app is a thin SwiftUI layer over a scriptable engine:
MLXForge.app (SwiftUI) โ Features โ ViewModels โ ForgeCore protocols
โ
LocalOrchestrator (actor) โ routes every job, owns queue & progress
โโโ ForgeEngine MLX Swift inference (in-process)
โโโ ForgeBridge Python runtimes over JSON-RPC 2.0 (unix socket)
โโโ ForgeServer OpenAI-compatible HTTP/SSE (Hummingbird 2)
โโโ ForgeCluster remote Macs via Bonjour
โ
forge_runtime (Python) โ mlx, mlx-lmโฆ one process per env,
spawned & supervised by the app
MLX Forge ships two programmatic companions:
mlxlab CLI (Swift) โ drive the lab from the shell: list models, launch jobs, query servers.mlxlab) โ talks to the app's local API for scripted workflows and integration into your existing tooling.import mlxlab
lab = mlxlab.connect() # talks to the running app
for model in lab.models.list():
print(model.name, model.size_gb)
uv. You'll never activate a venv, and different features can use isolated environments without conflicts.mlxf-โฆ) gate access. Point any OpenAI SDK at http://your-mac:8080/v1.