Best local models for coding on an M-series Mac in 2026
Memory bandwidth, prefill speed and tool-calling reliability decide this, and the answer is very different at 16GB than at 128GB.
Short answer, so you can stop reading if that is all you needed. On an M-series Mac the models worth pointing a coding agent at are mixture-of-experts models in roughly the 20B to 120B total-parameter range, run at 4-bit, through MLX where a good MLX conversion exists. Below 32GB of unified memory you are realistically choosing among the small MoE coder models around 20B to 30B total parameters with 3B or so active. At 64GB the 70B-to-120B-class MoE models open up at 4-bit with room left for a long context. At 128GB and above you can hold one of those resident all day and still have memory for Xcode, a browser and a simulator.
The families I keep coming back to are the Qwen3-Coder line, OpenAI's gpt-oss open-weight models, the GLM Air-class releases, and Mistral's Devstral for agent-shaped work. Model names churn every few months and whichever list I write here will be stale by spring, so the more useful thing is the selection rule underneath it: pick the largest MoE you can hold in memory at 4-bit with headroom for context, check that its tool calling is reliable before you check whether its code is good, and measure prompt processing speed rather than the tokens-per-second number people quote on forums. The rest of this post is why each of those matters.
Memory bandwidth is the ceiling, not the GPU
Generating a token from a dense model requires reading every weight out of memory once. That makes generation bandwidth-bound, and it makes the arithmetic embarrassingly simple: divide your chip's memory bandwidth by the size of the model in memory and you have a rough upper bound on tokens per second. A 4-bit model is about half a gigabyte per billion parameters, so a 32B dense model at 4-bit reads roughly 16GB per token. Whatever your chip's bandwidth figure is, divide by 16 and you have your best case, before any real context is involved.
Apple publishes memory bandwidth per chip and the spread across the line is enormous. A base M-series chip has a small fraction of what a Max has, and the Ultra parts roughly double a Max. Look up the number for your exact chip before you decide anything, because two machines with the same 32GB of RAM can differ by a factor of three or four on generation speed. RAM tells you what fits. Bandwidth tells you whether it is usable.
This is why mixture-of-experts models changed local coding so much. A 30B model with 3B active parameters still needs all 30B resident in memory, but each token only reads the active slice. You pay for the big model in RAM and get something close to small-model speed. On Apple Silicon, where unified memory is generous and bandwidth is the scarce resource, that trade is close to ideal. If you are choosing between a dense 32B and an MoE of similar total size, take the MoE.
One practical note: macOS caps how much unified memory the GPU may wire down, and on a 64GB or 128GB machine that cap is what stops a model you thought would fit from loading. The knob is iogpu.wired_limit_mb via sysctl. Raise it deliberately, leave several gigabytes for the OS, and expect to reset it on reboot.
What fits, by machine
- 16GB: run an autocomplete-class model and nothing else. A 7B to 8B coder at 4-bit fills in code well and is genuinely fast, but it will not drive an agent loop. Do not fight this.
- 24GB to 32GB: the small MoE coder models around 30B total with ~3B active, at 4-bit. This is the entry point for real agent work. Expect to keep context modest and to close other memory-hungry apps.
- 48GB to 64GB: 70B-to-120B-class MoE at 4-bit, with enough left over for a 64k-plus context window. This is where local stops feeling like a demo for a meaningful share of tasks.
- 96GB to 128GB: the same class of model resident permanently, at longer context, alongside your normal working set. Quality per token is close to what mid-tier hosted models gave you a year or two earlier.
- 192GB and up (Ultra): the very large MoE releases become loadable at aggressive quantization. Generation is fine. Prefill on a huge agent prompt is still the thing that will disappoint you.
Prefill is what actually hurts
Everyone benchmarks generation speed because it is the number that scrolls past on screen. For coding agents the number that matters more is prompt processing, also called prefill: how long the model takes to read the input before it emits a single token. Prefill is compute-bound rather than bandwidth-bound, and Apple Silicon GPUs are comparatively weaker at compute than at memory bandwidth. That mismatch is exactly the wrong shape for this workload.
Consider what a coding agent sends. A system prompt with a dozen tool definitions, a project instructions file, several files read into context, a long tool-result transcript. Tens of thousands of tokens before your actual question, and it grows every turn. On a hosted model most of that prefix gets prompt-cached and you pay a fraction for it. Locally you get whatever KV cache reuse your runtime offers, which helps a great deal when the prefix is stable and helps not at all the moment something earlier in the conversation changes.
So before you commit to a setup, time one realistic agent turn end to end rather than a one-line chat prompt. If time-to-first-token on a 40k-token context is thirty seconds, you have a model that is technically excellent and practically unusable for interactive work, and you would rather know that on day one.
Tool calling is the pass or fail test
The failure mode of a local model inside a coding agent is almost never bad code. It is a malformed tool call, a hallucinated file path, a model that writes out what it intends to do instead of emitting the edit, or a model that cheerfully claims it ran the tests. Any of those poisons the conversation, and the agent then spends real tokens recovering from a mess it created.
This is why I rate models trained specifically for agent loops above models with better raw coding benchmarks. Devstral exists for this reason and it shows. The Qwen3-Coder models handle tool schemas reliably in my experience. The gpt-oss models are strong here too and their reasoning-effort setting is a real lever, because low effort on a mechanical task saves a lot of prefill.
My honest read after a lot of hours on this: local models on a Mac are good at the mechanical majority of agent traffic. Reading a file and summarising it, renaming things across a module, writing a test that mirrors an existing one, drafting a commit message, answering a question about code already in context. They are still meaningfully behind the frontier models on the hard part, which is holding a large unfamiliar codebase in mind and making a design decision that turns out to be right. Anyone telling you the gap has closed is measuring the easy half.
Runtimes: Ollama, LM Studio, MLX
Ollama is the easiest thing to install and the easiest thing to script against, and it runs GGUF through llama.cpp. LM Studio gives you an MLX backend, which is Apple's own array framework and is usually the faster path on Apple Silicon for the same model at the same quantization. Both expose an OpenAI-compatible endpoint, which is all your tooling needs. I run LM Studio for MLX builds when a good conversion exists and Ollama for everything else, and I do not think the choice is worth agonising over.
Quantization: 4-bit is the sweet spot and has been for a while. 8-bit costs you double the memory for a difference you will struggle to notice on coding tasks. Below 4-bit, instruction following and tool-call formatting degrade before prose quality does, which is precisely the capability an agent depends on. If a model only fits at 3-bit, run the next size down at 4-bit instead.
Where Probe0 fits
I built Probe0 because the interesting setup is not local instead of cloud, it is deciding per request. Probe0 is a local proxy on macOS that every coding agent CLI on the machine routes through, Claude Code and Codex and Cursor alike, via one proxy and a certificate installed once. There is no Probe0 server, so nothing about your prompts leaves your machine on account of it.
The module that matters for this post is Local Routing: send work to a model already running in Ollama or LM Studio, and automatically retry weak answers on the cloud. That last clause is the part that makes local viable in practice, because the cost of a bad local answer inside an agent run is not zero, it is a wasted loop. Alongside it there is an Exact Cache on local disk, a Semantic Cache with a strict similarity floor that refuses to match anything carrying tool calls, Request Coalescing for simultaneous identical calls, a Spend Guard that warns and then pauses at a cap, and a full request ledger recording model, tokens, real cost, latency and which process made each call. Every module is individually switchable and reports what it saved.
The ledger is the reason I would suggest running it before you buy more RAM. It tells you what share of your agent traffic is the mechanical stuff a 30B MoE handles fine, which is the only number that tells you whether a bigger Mac would pay for itself.
Limits, plainly: macOS only, private beta, single developer rather than a team gateway, and provider coverage is what coding agents actually call rather than a hundred-provider catalog. If you need a hosted multi-tenant gateway with team keys, a proxy that runs on your laptop is the wrong shape and you should look at the hosted gateways instead.
Buy the machine for bandwidth and the model for tool-calling reliability. Everything else is downstream of those two.
A setup I would actually recommend
- Pick the largest MoE that fits at 4-bit with at least 8GB of headroom left for KV cache and the OS.
- Run it through MLX if a maintained conversion exists, otherwise GGUF through Ollama. Do not spend a weekend on this.
- Test tool calling first. Give it ten small agent tasks that require file reads and edits and count malformed calls, not code quality.
- Time a realistic 30k-token turn to first token. If it is over about ten seconds, drop a size class rather than living with it.
- Route the mechanical majority locally and let the hard requests go to a frontier model, then read the ledger after a week and adjust the split from evidence instead of vibes.
The honest summary for 2026 is that a 64GB or larger M-series Mac now handles a real fraction of coding agent traffic locally, at zero marginal cost and with nothing leaving the machine, and that the fraction is large enough to change your monthly bill without being large enough to let you cancel your frontier subscription. Set it up expecting that split and it works well. Set it up expecting to go fully local and you will be back on the cloud within a week, annoyed.