| name | build-afm |
| description | Build AFM from scratch — submodules, patches, webui, and Swift build. Use when user types /build-afm, asks to build afm, or needs a fresh build from a clean clone. |
| user_invocable | true |
Build AFM
Build the afm binary from scratch, suitable for a fresh clone or a full rebuild.
Usage
/build-afm — release build (default)
/build-afm debug — debug build
/build-afm release — explicit release build
Instructions
Step 0: Validate Prerequisites
Before building, check that all required tools and environment are present. Run these checks and collect results:
uname -m
sw_vers -productVersion
brew --version
xcode-select -p
swift --version
git --version
node --version
npm --version
Present results as a checklist to the user in dependency order (install top-to-bottom). For each item, show pass/fail, reason, and install command (even on pass, for copy-paste on other machines):
| # | Prerequisite | Check | Status | Reason | Install |
|---|
| 1 | Apple Silicon | uname -m = arm64 | pass/fail | MLX framework requires ARM64 GPU | N/A (hardware requirement) |
| 2 | macOS 26+ (Tahoe) | sw_vers >= 26.0 | pass/fail | Foundation Models backend + SDK APIs | System Settings > Software Update |
| 3 | Homebrew | brew --version | pass/fail | Package manager — Git, Node.js depend on it | /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" |
| 4 | Xcode (full) | xcode-select -p points to Xcode.app | pass/fail | mlx-swift uses Metal SDK (not in standalone CLI Tools) | Install from App Store → search "Xcode" |
| 5 | Swift 5.9+ | swift --version | pass/fail | swift-tools-version: 5.9 in Package.swift | Included with Xcode |
| 6 | Git | git --version | pass/fail | Submodule init (mlx-swift-lm, llama.cpp) | brew install git |
| 7 | Node.js 18+ | node --version | pass/fail | llama.cpp webui build (Svelte/Vite) | brew install node |
| 8 | npm | npm --version | pass/fail | npm install + npm run build for webui | Included with Node.js |
Important Xcode notes:
- Standalone CLI Tools (
xcode-select --install) are NOT sufficient — mlx-swift imports the Metal framework which requires the full Xcode SDK
- If
xcode-select -p returns /Library/Developer/CommandLineTools, switch to Xcode: sudo xcode-select -s /Applications/Xcode.app/Contents/Developer
- After installing Xcode, accept the license:
sudo xcodebuild -license accept
If anything is missing, present the failing items with install commands and ask the user to confirm when ready. Alternative Node.js install:
- Node.js + npm (via nvm instead of Homebrew):
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.1/install.sh | bash && nvm install 22
Do NOT proceed with the build until all prerequisites pass.
Step 1: Build
Parse the argument: if the user passes debug, use --debug. Otherwise default to release.
Run the full build script with NO skip flags:
./Scripts/build-from-scratch.sh
./Scripts/build-from-scratch.sh --debug
All direct SwiftPM builds must go through Scripts/swiftpm-reliable.sh rather
than invoking swift build or swift test directly. Xcode 27 can corrupt its
explicit-module scanner cache and report missing CAsyncHTTPClient, CSystem,
CNIO*, or _NumericsShims modules. On Xcode 27 Beta 3 the wrapper selects the
native driver immediately; on other versions it switches only after recognizing
that failure. It preserves checkouts, patches, and normal .build artifact
paths. If native incremental module state is also stale, it cleans products and
retries native once. Logs live in .build-reliable-logs/; persistent driver
identity lives in .build-reliable-state/ outside SwiftPM's cleanable tree. Set
AFM_SWIFTPM_DRIVER=swiftbuild only for default-driver diagnosis.
The wrapper fingerprints vendor/mlx-swift-lm before every invocation. When a
Swift or custom-Metal kernel patch changes that local package, it invalidates
compiled products so Xcode 27 Beta 3 cannot silently reuse a stale binary.
The manifest compiles this vendor directly when initialized; a submodule-free
consumer falls back to the pinned pre-patched URL fork.
Run Scripts/check-mlx-source-selection.sh after dependency changes.
For test, the wrapper permanently stages the canonical committed
Sources/AFMKitMLX/Resources/default.metallib as mlx.metallib beside every
XCTest executable before each build/run attempt. It also exports
MACAFM_MLX_METALLIB for AFMKit's own locator. Do not add one-off metallib
copies or paths to test commands; fix the wrapper if a new test layout ever
needs support.
Scripts/swiftpm-reliable.sh build -c release --product afm
Scripts/swiftpm-reliable.sh test -c release
IMPORTANT: Never add --skip-submodules, --skip-patches, or --skip-webui. The point of this skill is a complete from-scratch build.
Step 2: Monitor
The script already handles:
git submodule update --init --recursive
Scripts/apply-mlx-patches.sh (apply + verify)
- llama.cpp webui build (npm install + build)
- Swift package resolve + clean + build
- Version injection: writes the git commit SHA into
BuildInfo.swift (then restores it after build)
- Strip symbols for release builds
- Metallib bundle verification
- Info.plist embedding verification — fails the build if the
__TEXT,__info_plist section is missing or doesn't contain NSSpeechRecognitionUsageDescription. Required by Sources/MacLocalAPI/Info.plist + Package.swift linker flags (-Xlinker -sectcreate -Xlinker __TEXT -Xlinker __info_plist -Xlinker …). Without this, macOS 26 SIGABRTs any Speech Recognition / microphone / camera call.
Step 3: Report Results
After the build succeeds, report to the user:
- The build configuration (debug or release)
- The full absolute path to the compiled
afm binary (from the script output)
- The version string by running:
<binary-path>/afm --version
Do NOT add example run commands, CLI options, or environment variables. Just report the binary path and version — the user knows how to run it.
Step 4: Handle Failures
If the build fails, show the error output and suggest checking:
- Xcode Command Line Tools are installed (
xcode-select -p)
- Node.js/npm available for webui build
- Submodules initialized properly
- Re-run Step 0 prerequisite checks to catch environment issues
- For Xcode module-scanner failures, confirm the build used
Scripts/swiftpm-reliable.sh; logs are in .build-reliable-logs/