fm is the command-line interface for Apple Foundation Models, built into macOS 27 for local prompting, structured generation, image understanding, interactive chat, and automation.
Warning
The default system model runs on-device. --model pcc sends the request to Apple's Private Cloud Compute service and requires a network connection. Do not pass secrets to PCC unless that is appropriate for the data.
Model output is untrusted input. Validate structured results and require human review before deleting files, sending messages, changing infrastructure, or taking other consequential actions.
# Verify that the model is usable
fm available
# Ask the default on-device model
fm respond 'Explain this shell error in plain English: permission denied'
# Start a conversation
fm chat --instructions 'Be concise and ask before making assumptions.'
# Use the larger Private Cloud Compute model
fm respond --model pcc 'Compare these two architecture options: ...'
# See the exact options installed on this Mac
fm --help
fm respond --help
fm schema object --help- macOS 27;
fmis preinstalled. - The default
systemmodel is on-device. - The
pccmodel uses Private Cloud Compute, requires connectivity, and has usage limits.
Check both availability and PCC quota before relying on a model in automation:
fm available
fm available --model pcc
fm quota-usage --model pccFor one-off private work, start with the on-device model:
fm respond \
--instructions 'Answer concisely. Separate facts from uncertainty.' \
'Why might this launch daemon repeatedly restart?'For scripts, prefer non-streaming, structured, repeatable output:
fm respond \
--no-stream \
--greedy \
--schema ./result.schema.json \
--instructions 'Return only the requested structured result.' \
'Analyze the supplied data.'--greedy reduces sampling variability, but it does not make an answer guaranteed or factual.
| Model | Select with | Best fit | Important difference |
|---|---|---|---|
| On-device system model | Default or --model system |
Private, offline, low-latency work | No request quota; 4,096-token session context |
| Private Cloud Compute model | --model pcc |
More complex tasks and larger inputs | Requires a network connection; usage limits; 32K context |
Use fm count-tokens before sending a large prompt:
fm count-tokens 'A prompt to measure'
fm count-tokens --quiet 'A prompt to measure'The prompt, instructions, transcript, and generated response share the available context. Leave room for the answer.
| Goal | Command |
|---|---|
| Generate one response | fm respond 'Prompt' |
| Hold an interactive conversation | fm chat |
| Count input tokens | fm count-tokens 'Text' |
| Build a generation schema | fm schema object ... |
| Check model availability | fm available |
| Check PCC quota | fm quota-usage --model pcc |
| Run a local Chat Completions server | fm serve --host 127.0.0.1 --port 8080 |
| Get command-specific help | fm <command> --help |
| Option | Purpose |
|---|---|
-i, --instructions <text> |
Set persistent instructions for the response |
--text <text> |
Add a text segment to the prompt |
--image <path> |
Add an image |
--schema <file-or-JSON> |
Constrain the response to a JSON schema |
--resume <file> |
Continue from a saved transcript |
--save-transcript <file> |
Save the resulting transcript |
--no-stream |
Wait and print the complete result; useful in scripts |
-g, --greedy |
Use greedy sampling for less variable output |
-v, --verbose |
Print diagnostic detail |
--model system|pcc |
Select the on-device or PCC model |
pbpaste | fm respond \
--instructions 'Summarize in five bullets. Preserve dates, owners, and decisions.'Piping avoids placing the clipboard contents directly in shell history. The default model keeps processing on-device.
fm respond \
--instructions 'Extract decisions, action items, owners, and deadlines. Mark missing owners or dates as unknown.' \
< meeting-notes.mdDo not let the model invent missing assignments; explicitly requesting unknown makes review easier.
git diff --cached --no-ext-diff | fm respond \
--instructions 'Write one imperative Git subject under 72 characters, then an optional concise body. Output only the commit message.'Review the result before committing. The staged diff may contain credentials or customer data; keep the default on-device model for sensitive repositories.
tail -n 250 ./service.log | fm respond \
--instructions 'Act as an incident responder. Identify the earliest likely cause, distinguish it from follow-on errors, quote relevant timestamps, and give three safe checks.'Bound the input with tail or another filter so logs do not consume the entire context window.
fm respond \
--image ./Screenshot.png \
'Describe the visible error, likely cause, and the safest next diagnostic step.'For a harder visual task, add --model pcc after checking that sending the screenshot to PCC is acceptable.
fm respond \
--image ./product-dashboard.png \
--instructions 'Write factual alt text under 160 characters. Do not infer identities or hidden meaning.' \
'Describe this image for a screen-reader user.'Verify names, numbers, and chart conclusions against the image.
Create a schema:
fm schema object \
--name IncidentSummary \
--string severity \
--description 'One of: low, medium, high, critical' \
--string probable_cause \
--string evidence --array \
--string next_checks --array \
> /tmp/incident-summary.schema.jsonGenerate and validate a result:
tail -n 250 ./service.log | fm respond \
--no-stream \
--greedy \
--schema /tmp/incident-summary.schema.json \
--instructions 'Analyze the log supplied on standard input. Do not invent absent evidence.' \
| tee /tmp/incident-summary.json \
| jq -e .A valid schema guarantees shape, not truth. Check values before acting on them.
fm schema object \
--name FileTriage \
--string final_files --array \
--string draft_files --array \
> ./file-triage.schema.json
printf '%s\n' ./* | fm respond \
--no-stream \
--schema ./file-triage.schema.json \
--instructions 'Classify the supplied names as likely final or draft. Return only names present in the input.' \
> ./triage-result.jsonFirst print the proposed actions:
jq -r '.draft_files[] | "WOULD ARCHIVE: \(.)"' ./triage-result.jsonOnly write a separate move or deletion step after validating that every returned path is inside the intended directory. Never evaluate model output as shell code.
fm respond \
--instructions 'Help diagnose this incident. Track confirmed facts separately from hypotheses.' \
--save-transcript ./incident-session.json \
'The API began returning 503 errors at 14:32.'
fm respond \
--resume ./incident-session.json \
--save-transcript ./incident-session.json \
'New evidence: database connections are healthy.'For an interactive session:
fm chat --instructions 'Coach me through this migration one reversible step at a time.'Inside fm chat, /save saves the conversation and /model switches models. Use fm chat --continue to continue the most recent saved session.
fm serve --host 127.0.0.1 --port 8080Bind to 127.0.0.1 unless remote access is intentionally configured and protected. Run fm serve --help for the installed server's connection details and supported options.
fm schema object starts a property with --string, --integer, --double, or --boolean. Modifiers such as --description, --optional, and --array apply to the property immediately before them.
fm schema object \
--name DeploymentReview \
--boolean approved \
--string blockers --array \
--double confidence --optional \
--string owner.name \
> deployment-review.schema.jsonDot notation such as owner.name creates nested objects. Inspect fm schema object --help because the property grammar is easier to understand from the complete built-in help.
- Put stable rules in
--instructions; put the current task and data in the prompt. - Ask the model to use
unknownrather than guess. - Bound large inputs and check them with
fm count-tokens. - Use a schema instead of parsing prose with regular expressions.
- Use
--no-streamwhen capturing a complete response. - Use
--greedywhen repeatability matters, then still test representative cases. - Treat files, webpages, logs, and email as untrusted prompt content; they may contain prompt-injection text.
- Never pass model output to
eval,sh -c, or an unreviewed destructive command.
sw_vers -productVersion
command -v fmThe Apple fm command requires macOS 27 and is normally available as a system command.
fm available --model system
fm available --model pccCheck Apple Intelligence availability for the system model. PCC additionally requires connectivity and available quota:
fm quota-usage --model pccfm count-tokens --quiet < long-prompt.txtShorten the input, remove repeated context, or use PCC when its larger context and privacy boundary are appropriate.
Use all three:
fm respond --no-stream --greedy --schema ./result.schema.json '...'Then validate the result with jq -e and enforce application-level rules.
- Apple Foundation Models documentation
- Apple: Build AI-powered scripts with the fm CLI and Python SDK
- Apple: Managing the context window
- fm manual page mirror
#cheatsheets #macOS #AppleIntelligence #FoundationModels #CLI