The model layer
New in 1.0 — offer more than one model, without creating your own provider abstraction
The 0.8 SDK gives your native macOS app a real MCP client, the
Calendar / Reminders / Contacts / Location connectors, ready-made Tools, and
Keychain-backed OAuth — all still here, all unchanged. 1.0 adds the piece you reach for
when which model becomes a real question in your app.
Start from working code
Every API on this page is exercised by a small, runnable example you can clone and build — use the closest one as a starting reference rather than writing from scratch. For the model layer, three of them, smallest to fullest:
| Example | Start here if you want… |
|---|---|
repo-qa-local |
the smallest "download and run an open-weight model" — one file, a CLI that answers questions about a GitHub repo through an MCP server. About 20 lines different from the Apple-model version next to it. |
code-buddy |
the full pattern: a CLI coding agent with .heavy /
.light routes to two local models (one kept warm), Core's Workspace
tools, an MCP docs server, streamed output, and two host-owned Process
tools the SDK deliberately doesn't ship. Every API below has a
"→ code-buddy uses this" pointer in the guide. |
workspace-buddy-local |
a sandboxed GUI app running a downloaded model — the Mac App Store shape. Folder picker + security-scoped bookmark, the model edits files, and the model download works inside the App Sandbox container. |
Each folder has a README with copy-paste setup and a real "verified live" transcript.
All examples →
— the MCP-client and connector ones (repo-qa, plate-today,
components-demo) need no model download.
annotated-examples.md
walks every one line by line.
Four providers, one protocol
| Provider | Backs | Ships in |
|---|---|---|
SystemModelProvider | Apple's on-device model | Core |
PCCModelProvider | Apple Private Cloud Compute — not functional in this beta, see beta notes | Core |
ClaudeModelProvider | Claude (your API key or auth) | Core |
MLXModelProvider | Open-weight models you download and run locally | Inference |
Register the providers you want on a LocalLMLab instance (the optional front
door that also bundles the MCP manager and the connector facades), name models with
routes, and make a session. Adoption is small — this is
repo-qa-local's
entire change over the Apple-model repo-qa next to it; the rest of
the two files is identical:
let mlx = MLXModelProvider(residentModelLimit: 1)
let lab = LocalLMLab(configuration: .init(providers: [mlx, SystemModelProvider()]))
let modelID = ModelID(scheme: "mlx", rest: "mlx-community/Qwen3-8B-4bit")!
lab.models.route(.local, to: modelID)
if case .notDownloaded = lab.models.availability(for: modelID) {
_ = try await mlx.validate(modelID.rest) // fits this Mac's RAM? MLX format?
for try await event in mlx.download(modelID.rest) { … } // stream progress %
}
let session = try lab.makeSession(route: .local, tools: tools, instructions: instructions)
for try await partial in session.languageModelSession.streamResponse(to: task) { … }
makeSession merges your tools with the enabled MCP tools; .events
is a side-channel for tool-call and context-compaction progress; contextBudget
and retryOnContextOverflow carry a long session.
The memory story
MLXModelProvider isn't "load and go" on a constrained Mac:
validate preflights a model (MLX format? architecture supported? weights vs.
this Mac's RAM?) with no download; download streams progress;
capabilityProbe is the authoritative check of whether a downloaded model can
actually tool-call. residentModelLimit caps how many models stay in RAM —
switching routes evicts the other — and residencyEventStream reports it.
For a starting shortlist of which open-weight models tool-call and which don't, see
tested-models.md.
Two binaries
LocalLMLabSDKCore is the engine — link it always. LocalLMLabSDKInference
is the MLX runtime (~49 MB, the whole stack statically linked) — link it
only if you use MLXModelProvider. Both are
binaryTargets on the same GitHub release, both Developer-ID signed and
notarized. See
code-buddy's Package.swift
for the two-binary manifest shape.
Migrating from 0.8.x
- Platform:
platforms: [.macOS("27.0")]and the Xcode 27 beta. - One source-break:
MCPConnectionStatusandMCPServerErrorare non-frozen now — an exhaustiveswitchneeds@unknown default. That's the only break for an MCP-only consumer. Nothing was renamed or removed. - Point
knownSDKReleasesat1.0.0-beta.1with the checksum from the release's.sha256asset.
Docs
- sdk-guide.md — the full guide; §6a is the model layer.
- migrating-to-1.0.md — 0.8.x → 1.0.
- tested-models.md — which open-weight models tool-call.
- api-surface.md — the machine-generated public API list.
- annotated-examples.md — every reference app's source, SDK touchpoints marked inline.
- CHANGELOG.md
Contact
Building something on this, or hit a rough edge? neuron@thisbrain.ai or the Discord.