Two free LLMs came with your Mac.
apple-llm calls both.
The on-device model behind Apple Intelligence and, on macOS 27, the server model Siri AI runs on. Call them from Node.js or Python with no API key, no account and no model download. Your Mac's voices and speech recognition come with them.
npm install apple-llm
M1–M4 only? Check in 5s: npx apple-llm probe — will it run on my Mac?
$ apple-llm probe on-device variant AFM 3 Core Advanced context 8192 tokens supports guidedGeneration, toolCalling, vision use cases general, contentTagging cloud (private cloud compute) quota belowLimit $ apple-llm run --use-case contentTagging --schema tags.json "A recipe for sourdough…" {"tags": ["sourdough", "rye starter", "cast iron", "dutch oven", "recipe"]} $ apple-llm count --system "You are terse." "The quick brown fox…" 64 tokens of 8192 (1%)
help + Enter — it runs in your browser.- API cost
- $0
- On-device call, warm
- 0.3–2s
- Context, device / cloud
- 8k / 32k
- Runtime dependencies
- 0
01 What macOS 27 changed
macOS 27 is when the free models got good.
macOS 26 introduced the on-device model. macOS 27 doubled its context window, gave it eyes and tools, and swapped the cloud model for a much bigger one. apple-llm supports all of it.
macOS 26 still works, with a 4,096-token window and without these additions.
-
cloud
Siri AI's model, in the cloud tier
Golden Gate replaced the cloud model with Apple's next-generation server model, the one Siri AI runs on. It reasons, reads images, holds 32,768 tokens and can search the live web.
-
device
Twice the context
4,096→ 8,192 tokensEnough for a long email thread, a meeting transcript or a few documents in a single prompt.
-
device
Images, on device
Pass a photo, scan or screenshot by path. Nothing leaves the machine.
-
device
Apple's own tools
The model can call Apple's on-device OCR, barcode reader and Spotlight's semantic index, which gives you local RAG over your own files.
-
device
Tokens you can count
Count a prompt before you send it, and get input, output and cached token usage back from every call.
-
both
A framework that describes itself
probe()reports the model variant, what it supports and whether your cloud quota is spent, read straight from the framework rather than from the docs.
02 The cloud model
Apple's big model, from a plain Node or Python script. No other package we found gets there.
On macOS 27, PrivateCloudComputeLanguageModel is public API and reports itself available. Then every call fails with ModelManagerError 1046, unless your binary carries a managed entitlement that Apple grants only to signed apps in the App Store Small Business Program.
apple-llm takes a different route. Shortcuts already holds that entitlement, so apple-llm setup-cloud builds a shortcut and signs it on your Mac. Nothing is pre-signed, hosted or downloaded, and there's no developer account.
Direct API
- your script
PrivateCloudComputeLanguageModel- ✕ ModelManagerError 1046
apple-llm
- your script
- a shortcut, signed on your Mac
- ✓ Private Cloud Compute
- Reasoning
- Yes
- Images
- Yes
- Context
- 32,768 tokens
- Web search
- Optional
- Price
- Free, per-device quota
- Privacy
- Your prompt leaves the Mac
apple-llm setup-cloud --web-search # once: builds and signs the shortcut
apple-llm run --tier cloud "Plan a 3-day Lisbon trip on a budget."
03 Speech
Your Mac can also talk and listen.
The voices and speech recognition built into macOS, from the same package. Apple Intelligence can be off, there's no quota, and it all runs on your Mac.
Text to speech
- Every voice on your Mac, by name
- Out loud, or to WAV, M4A, AAC or FLAC
- Speed, pitch, volume and SSML
- The time of every word
- 30 minutes of audio rendered in 18 seconds
Speech to text
- Recordings, audio or video, any length
- The microphone, live
- 68 languages, downloaded on first use
- Word timings and SRT or VTT subtitles
- 30 minutes transcribed in 28 seconds
apple-llm speak "Hello there" # out loud, in your System voice
apple-llm speak "Hello" --voice Samantha --speed 1.2
apple-llm speak --file book.txt -o book.m4a # save it, any length
apple-llm voices # the voices you have
apple-llm transcribe meeting.mp4 # audio or video to text
apple-llm transcribe meeting.mp4 -o meeting.srt # subtitles
apple-llm listen # the microphone, live
import { listen, speak, synthesize, transcribe } from 'apple-llm';
await speak('Hello there', { voice: 'Samantha', speed: 1.2 });
const { audio } = await synthesize('Hello there', { format: 'wav' });
await synthesize(longArticle, { voice: 'Samantha', out: 'article.m4a' });
const { text, segments } = await transcribe('meeting.mp4');
const said = await listen(); // returns when you pause
from apple_llm import listen_once, speak, synthesize, transcribe
speak("Hello there", voice="Samantha", speed=1.2)
audio = synthesize("Hello there", format="wav").audio
synthesize(long_article, voice="Samantha", out="article.m4a")
result = transcribe("meeting.mp4") # .text, .segments
said = listen_once().text # returns when you pause
from openai import OpenAI
client = OpenAI(base_url="http://127.0.0.1:11436/v1", api_key="unused")
speech = client.audio.speech.create(model="tts-1", voice="Samantha", input="Hello there")
speech.write_to_file("hello.aac")
client.audio.transcriptions.create(model="whisper-1", file=open("hello.aac", "rb")).text
On apple-llm serve, from the npm package. macOS can't encode MP3, so a request for it gets AAC, with a Content-Type that says so.
Check the licence before you ship audio. Apple's licence allows its system voices for your personal, non-commercial use and rules out recording or publishing them in a profit, non-profit, public-sharing or commercial context. That covers every voice, and it's Apple's rule rather than ours. The clause, and what it means →
Siri voices. Apple doesn't let apps choose them. Where macOS lists one under the System voice setting, you can pick it there and speak should use it; we haven't been able to test that yet. Timings are from an M4 MacBook Air on macOS 27.2.
04 Compared
How it stacks up.
Good packages exist for the on-device model, and the table gives them their due. Apple's cloud model is the part none of the others reach.
| Feature | apple-llmNode + Python | apple-fm-sdkApple · Python | tsfm-sdkNode | apple-on-device-aiNode | afmCLI + HTTP server |
|---|---|---|---|---|---|
| On-device model | Yes | Yes | Yes | Yes | Yes |
| Apple's cloud model (PCC) | Yes, free, no entitlement | No | No1 | No | No |
| Library for Node.js | Yes | No | Yes | Yes | Via HTTP |
| Library for Python | Yes | Yes | No | No | Via HTTP |
| OpenAI-compatible server | Yes | No | No | No | Yes |
| Vercel AI SDK provider | Yes, v6 & v7 | No | No | Yes | No |
| Text to speech, Apple's voices | Yes, in the library | No | No | No | Yes |
| Speech to text, on device | Yes, in the library | No | No | No | Yes |
| Runs other models (MLX) | No | No | No | No | Yes |
1 tsfm has merged Private Cloud Compute support on a branch, unreleased as of 30 Sep 2026. It needs the com.apple.developer.private-cloud-compute entitlement on a signed host app, so it doesn't work from plain node. Apple's own fm command-line tool needs a machine-wide sudo fm license first.
Checked against each project's README, npm and PyPI on 30 September 2026, and the speech rows on 5 November 2026. Spotted a mistake? Open an issue.
For speech alone: afm does both over its own CLI and HTTP server, and yap is a good Swift CLI for transcription. On PyPI, mac-speech-analyzer and macbook-ai also wrap parts of this. What apple-llm adds is speech and Apple's LLMs in one library, for Node and Python, with no dependencies.
Not in the table: Ollama, LM Studio and MLX run open-weights models that you download and choose. They're the better pick for code and long reasoning. apple-llm uses the models already on your Mac, and plenty of people run both.
05 Code
Five ways in.
A library for each language, a drop-in OpenAI endpoint, a Vercel AI SDK provider and a CLI. One client covers both tiers, and auto prefers the device.
import { AppleLLM, tool } from 'apple-llm';
import { z } from 'zod';
const llm = new AppleLLM(); // 'auto': the device when it can, else the cloud
// Guaranteed shape on device: the decoder cannot produce anything else
const Contact = z.object({ name: z.string(), email: z.string().email() });
const contact = await llm.json('Reach Grace at grace@navy.mil', { schema: Contact });
// Your own functions, called mid-generation
const getWeather = tool({
name: 'getWeather',
description: 'Current weather for a city',
parameters: z.object({ city: z.string() }),
execute: async ({ city }) => ({ city, tempC: 21, sky: 'sunny' }),
});
await llm.text('Do I need an umbrella in Paris?', { tools: [getWeather] });
// Stream; breaking out of the loop stops the model
for await (const delta of llm.stream('Write a haiku about bridges')) {
process.stdout.write(delta);
}
from apple_llm import AppleLLM
from pydantic import BaseModel # optional: pip install 'apple-llm[pydantic]'
class Person(BaseModel):
name: str
born: int
with AppleLLM(tier="device") as llm:
person = llm.json("Ada Lovelace, born 1815.", schema=Person)
print(person.born) # 1815, a validated Person rather than a dict
llm.text("Read the total.", images=["receipt.png"], tools=["ocr"])
llm.stream("Count to three.", on_delta=print)
with AppleLLM(tier="cloud") as cloud: # after: apple-llm setup-cloud
cloud.text("Solve this step by step: ...")
npx apple-llm serve # OpenAI-compatible API at http://127.0.0.1:11436/v1
# options: --port 11436 --api-key <key> --cors <origin> --tier cloud
from openai import OpenAI
client = OpenAI(base_url="http://127.0.0.1:11436/v1", api_key="unused")
client.chat.completions.create(
model="apple-on-device", # or "apple-private-cloud"
messages=[{"role": "user", "content": "Tag this: sourdough with a rye starter"}],
)
Works with the official SDKs, LangChain, LlamaIndex, Open WebUI and editor plugins. It supports streaming, tools, JSON Schema response_format and images, and binds to localhost only.
import { generateText } from 'ai';
import { apple } from 'apple-llm/ai-sdk';
const { text } = await generateText({
model: apple(), // on device; apple('cloud') for Private Cloud Compute
prompt: 'Write a one-line release note for a bug fix.',
});
AI SDK 6 and 7: generateText, streamText, generateObject, multi-step tools, images and abort signals.
apple-llm chat # interactive, streamed
apple-llm run --schema person.json "Ada, 1815" # guaranteed JSON
apple-llm run --tool ocr --image receipt.png "Read the total."
apple-llm run --session trip "My cat is Biscuit."
apple-llm rewrite "gonna grab a bite" # also proofread, summarize, draft
apple-llm ask-screen "Summarize what is on this schedule."
apple-llm count --system "You are terse." - # tokens before sending
apple-llm speak "Hello there" # out loud
apple-llm transcribe meeting.mp4 # audio or video to text
The pip and npm packages install the same apple-llm command; chat and serve come with npm.
06 Fit
Small model, right jobs.
The on-device model is roughly 20B sparse with 1–4B active. Used for what it's good at, it's fast, private and free. No amount of prompting makes it good at the rest.
Reach for it
- Classifying, tagging and extracting topics
- Pulling fields out of text into guaranteed JSON
- Reading receipts and screenshots
- Rewriting, proofreading and summarising
- Private data that shouldn't leave the Mac
Reach past it
- Writing code: use a bigger model
- Long reasoning: use the cloud tier
- Inputs over 8k tokens: use the cloud tier
- Linux, Windows or Intel Macs: not supported
07 Field notes
Fifteen constraints, found the expensive way.
The package is mostly these, written down as working code so nobody has to find them again. Six of them:
-
Never set
temperature: 0Greedy decoding under a schema degenerates. One run padded an array forever, then wrote 2.7KB of
"tasks-tasks-tasks-…"inside a single string.2s→ 20s per call. Default is 0.4. -
One process, not one per call
Spawning a helper per request makes every call pay for loading the model again. One long-lived helper keeps it resident.
~17s → ~1.5s per call
-
Concurrency buys nothing
Apple serialises inference. Four concurrent requests took as long as four sequential ones, so the queue serialises on purpose.
29.19s parallel vs 29.45s sequential
-
Every
patternis rejectedEven
^[A-Z]{3}$fails withUnsupportedGuide, and Zod adds one to.email(). Patterns are stripped for the decoder and checked on the reply instead.1 of 9 schema-dialect rules
-
A schema mistake is invisible
Collapsing a number-or-string union to
stringmade it impossible for the model to emit a status code. It wrote": 201"instead, with no error anywhere.Wrong answer, no warning
-
WFLLMPrompt, notWFInputWith the wrong key, the shortcut imports fine, silently discards the prompt, then blocks forever on an interactive panel.
The most expensive bug available
08 Questions
- Is it really free?
- Yes. The on-device model has no key and no limits. The cloud tier is free too, within a per-device quota from Apple;
probe()reports whether you're under it, and running out raises aQuotaError. - Is it private?
- The device tier is: nothing leaves your Mac. The cloud tier sends your prompt to Apple's Private Cloud Compute.
autouses the device whenever it can. - What do I need?
- macOS 26 or 27 on Apple Silicon, with Apple Intelligence on for the models (speech doesn't need it), plus the Xcode Command Line Tools (
xcode-select --install). Full Xcode isn't needed. On anything else it installs but reports why it can't run. - Does Python have everything Node has?
- Not yet. Python has text, JSON with pydantic, streaming, sessions, images, Apple's built-in tools, the writing presets and all of speech. Your own function tools, Zod, the server and the AI SDK provider are npm-only for now.
- Is long audio a problem?
- No. On an M4 MacBook Air, 60 minutes of speech renders in 40 seconds and 30 minutes transcribes in 28. A read-aloud runs as long as your text does.
- Can it use Siri's voice?
- Apple doesn't let apps choose Siri voices, and asking for one by name gets the default voice. Where macOS lists one under the System voice setting, you can pick it there and
speakshould use it, though we haven't been able to test that yet. The other voices on your Mac all work, by name. - Can I use the audio in a product?
- Check Apple's licence first. It allows system voices for personal, non-commercial use and rules out recording or publishing them in a profit, non-profit, public-sharing or commercial context. Here's the clause. Speech recognition isn't covered by it.
Try it in thirty seconds.
npm install apple-llm && npx apple-llm probe
# or: pip install apple-llm && apple-llm probe
If it saves you an API bill, a star helps other Mac developers find it.
Star on GitHub ★ 10