SPB Git

spb/zyquo-mlx Public MIT

The local MLX foundry for your Mac — run, fine-tune, quantize, and ship models. Nothing leaves your machine.

Swift 93.4% Python 3.8% Makefile 2.2% Shell 0.5%

phase1: SPM manifest (pinned MLX deps), app entry + Apple-Silicon gate, Info.plist, Makefile, README

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
simon-pierre boucher committed 11 days ago (Jul 30, 2026) parent 35d453d

Showing 8 changed files with +474 and −1

added Makefile +75 −0
@@ -0,0 +1,75 @@
1 +#
2 +# Makefile
3 +# Zyquo MLX
4 +#
5 +# Author: Simon-Pierre Boucher
6 +# Mail: contact@spboucher.ai
7 +#
8 +# Command-line-only builds (no Xcode IDE, no .xcodeproj) per docs/BUILD.md.
9 +# Requires full Xcode installed as a toolchain + Metal toolchain component:
10 +# sudo xcode-select -s /Applications/Xcode.app
11 +# xcodebuild -downloadComponent metalToolchain
12 +#
13 +
14 +APP_NAME := Zyquo MLX
15 +EXEC_NAME := ZyquoMLX
16 +BUNDLE_ID := com.zyquo.mlx
17 +DIST := dist
18 +APP := $(DIST)/$(APP_NAME).app
19 +CONFIG ?= release
20 +
21 +# Use Xcode's toolchain per-command; the machine default (CLT) is untouched.
22 +XCODE_DEV_DIR := /Applications/Xcode.app/Contents/Developer
23 +DEV := DEVELOPER_DIR=$(XCODE_DEV_DIR)
24 +
25 +# Build backend per docs/BUILD.md §3.1: try SwiftPM first (Swift 6.4 issues
26 +# CompileMetalFile itself); fall back to xcodebuild if metallib is missing.
27 +BUILD_DIR := .build
28 +BIN_DIR = $(BUILD_DIR)/$(CONFIG)
29 +
30 +.PHONY: build build-xcodebuild app dev run icon clean release check-toolchain
31 +
32 +check-toolchain:
33 + @test -d $(XCODE_DEV_DIR) || { echo "error: Xcode toolchain not found at /Applications/Xcode.app — see docs/BUILD.md §2"; exit 1; }
34 +
35 +build: check-toolchain
36 + $(DEV) swift build -c $(CONFIG)
37 +
38 +build-xcodebuild: check-toolchain
39 + $(DEV) xcodebuild build \
40 + -scheme $(EXEC_NAME) \
41 + -destination 'platform=OS X,arch=arm64' \
42 + -configuration Release \
43 + -derivedDataPath $(BUILD_DIR)/xcode \
44 + -skipMacroValidation
45 +
46 +app: build
47 + rm -rf "$(APP)"
48 + mkdir -p "$(APP)/Contents/MacOS" "$(APP)/Contents/Resources"
49 + cp Support/Info.plist "$(APP)/Contents/Info.plist"
50 + cp "$(BIN_DIR)/$(EXEC_NAME)" "$(APP)/Contents/MacOS/$(EXEC_NAME)"
51 + @# Ship every SPM resource bundle — mlx-swift_Cmlx.bundle carries
52 + @# default.metallib; omitting it crashes GPU ops (docs/BUILD.md §3.2).
53 + @for b in "$(BIN_DIR)"/*.bundle; do \
54 + [ -e "$$b" ] && cp -R "$$b" "$(APP)/Contents/Resources/" && echo "bundled $$(basename $$b)"; \
55 + done; true
56 + @if [ -f assets/icon/AppIcon.icns ]; then cp assets/icon/AppIcon.icns "$(APP)/Contents/Resources/AppIcon.icns"; fi
57 + codesign --force --deep --sign - "$(APP)"
58 + @echo "→ $(APP) (ad-hoc signed)"
59 +
60 +dev: app
61 + open "$(APP)"
62 +
63 +run: app
64 + "$(APP)/Contents/MacOS/$(EXEC_NAME)"
65 +
66 +icon:
67 + @# Phase 5: SVG → PNGs → .iconset → .icns (rsvg-convert + iconutil)
68 + bash scripts/make-icon.sh
69 +
70 +release: app
71 + @# Phase 8: Developer ID signing + notarization + stapling (docs/BUILD.md §4)
72 + @echo "release target completed in Phase 8 — currently ad-hoc only"; exit 1
73 +
74 +clean:
75 + rm -rf $(BUILD_DIR) $(DIST)
added Package.resolved +149 −0
@@ -0,0 +1,149 @@
1 +{
2 + "pins" : [
3 + {
4 + "identity" : "eventsource",
5 + "kind" : "remoteSourceControl",
6 + "location" : "https://github.com/mattt/EventSource.git",
7 + "state" : {
8 + "revision" : "a3a85a85214caf642abaa96ae664e4c772a59f6e",
9 + "version" : "1.4.1"
10 + }
11 + },
12 + {
13 + "identity" : "mlx-swift",
14 + "kind" : "remoteSourceControl",
15 + "location" : "https://github.com/ml-explore/mlx-swift",
16 + "state" : {
17 + "revision" : "0bb916c67f4b9e5c682cbe02a42c701c93ab5021",
18 + "version" : "0.31.6"
19 + }
20 + },
21 + {
22 + "identity" : "mlx-swift-lm",
23 + "kind" : "remoteSourceControl",
24 + "location" : "https://github.com/ml-explore/mlx-swift-lm",
25 + "state" : {
26 + "revision" : "bd4b7434e6bdb588c7ef55706ff8904cb7fd4c57",
27 + "version" : "3.31.4"
28 + }
29 + },
30 + {
31 + "identity" : "swift-argument-parser",
32 + "kind" : "remoteSourceControl",
33 + "location" : "https://github.com/apple/swift-argument-parser",
34 + "state" : {
35 + "revision" : "6a52f3251125d74daf04fcbd5e6f08a75d074382",
36 + "version" : "1.8.2"
37 + }
38 + },
39 + {
40 + "identity" : "swift-asn1",
41 + "kind" : "remoteSourceControl",
42 + "location" : "https://github.com/apple/swift-asn1.git",
43 + "state" : {
44 + "revision" : "a9a5efd40eaf558a2bcd48d64b1d1646be686008",
45 + "version" : "1.7.1"
46 + }
47 + },
48 + {
49 + "identity" : "swift-atomics",
50 + "kind" : "remoteSourceControl",
51 + "location" : "https://github.com/apple/swift-atomics.git",
52 + "state" : {
53 + "revision" : "0442cb5a3f98ab802acb777929fdb446bda11a34",
54 + "version" : "1.3.1"
55 + }
56 + },
57 + {
58 + "identity" : "swift-collections",
59 + "kind" : "remoteSourceControl",
60 + "location" : "https://github.com/apple/swift-collections.git",
61 + "state" : {
62 + "revision" : "a0cb0954ecb21e4e31b0070e6ed5674e8556685a",
63 + "version" : "1.6.0"
64 + }
65 + },
66 + {
67 + "identity" : "swift-crypto",
68 + "kind" : "remoteSourceControl",
69 + "location" : "https://github.com/apple/swift-crypto.git",
70 + "state" : {
71 + "revision" : "47d3869a7291f085c1fb9fb1e6d3b97a793f45c6",
72 + "version" : "4.5.1"
73 + }
74 + },
75 + {
76 + "identity" : "swift-huggingface",
77 + "kind" : "remoteSourceControl",
78 + "location" : "https://github.com/huggingface/swift-huggingface",
79 + "state" : {
80 + "revision" : "b721959445b617d0bf03910b2b4aced345fd93bf",
81 + "version" : "0.9.0"
82 + }
83 + },
84 + {
85 + "identity" : "swift-jinja",
86 + "kind" : "remoteSourceControl",
87 + "location" : "https://github.com/huggingface/swift-jinja.git",
88 + "state" : {
89 + "revision" : "7d0b8880ef8e567dd4e0089f8b99fb354129017c",
90 + "version" : "2.4.2"
91 + }
92 + },
93 + {
94 + "identity" : "swift-nio",
95 + "kind" : "remoteSourceControl",
96 + "location" : "https://github.com/apple/swift-nio.git",
97 + "state" : {
98 + "revision" : "0b18836bd8b0162e7e17a995a3fbee20ed8f3b2b",
99 + "version" : "2.101.3"
100 + }
101 + },
102 + {
103 + "identity" : "swift-numerics",
104 + "kind" : "remoteSourceControl",
105 + "location" : "https://github.com/apple/swift-numerics",
106 + "state" : {
107 + "revision" : "0c0290ff6b24942dadb83a929ffaaa1481df04a2",
108 + "version" : "1.1.1"
109 + }
110 + },
111 + {
112 + "identity" : "swift-syntax",
113 + "kind" : "remoteSourceControl",
114 + "location" : "https://github.com/swiftlang/swift-syntax.git",
115 + "state" : {
116 + "revision" : "79e4b74a295b6eb74a8b585e3a39d29e70c1dbd1",
117 + "version" : "603.0.2"
118 + }
119 + },
120 + {
121 + "identity" : "swift-system",
122 + "kind" : "remoteSourceControl",
123 + "location" : "https://github.com/apple/swift-system.git",
124 + "state" : {
125 + "revision" : "50688cacbd41d547e9eb9f7a213542340b7c442b",
126 + "version" : "1.7.5"
127 + }
128 + },
129 + {
130 + "identity" : "swift-transformers",
131 + "kind" : "remoteSourceControl",
132 + "location" : "https://github.com/huggingface/swift-transformers",
133 + "state" : {
134 + "revision" : "2fa33e1f5e7131a7fc64c28e6d161dcec0d24820",
135 + "version" : "1.3.3"
136 + }
137 + },
138 + {
139 + "identity" : "yyjson",
140 + "kind" : "remoteSourceControl",
141 + "location" : "https://github.com/ibireme/yyjson.git",
142 + "state" : {
143 + "revision" : "8b4a38dc994a110abaec8a400615567bd996105f",
144 + "version" : "0.12.0"
145 + }
146 + }
147 + ],
148 + "version" : 2
149 +}
added Package.swift +44 −0
@@ -0,0 +1,44 @@
1 +// swift-tools-version: 5.9
2 +//
3 +// Package.swift
4 +// Zyquo MLX
5 +//
6 +// Author: Simon-Pierre Boucher
7 +// Mail: contact@spboucher.ai
8 +//
9 +
10 +import PackageDescription
11 +
12 +let package = Package(
13 + name: "ZyquoMLX",
14 + platforms: [
15 + .macOS(.v14)
16 + ],
17 + dependencies: [
18 + // Versions pinned per docs/MLX-RESEARCH.md §8 (verified 2026-07-30).
19 + // Released tags only — mlx-swift main requires an experimental toolchain.
20 + .package(url: "https://github.com/ml-explore/mlx-swift", .upToNextMinor(from: "0.31.6")),
21 + .package(url: "https://github.com/ml-explore/mlx-swift-lm", .upToNextMajor(from: "3.31.4")),
22 + .package(url: "https://github.com/huggingface/swift-huggingface", from: "0.9.0"),
23 + .package(url: "https://github.com/huggingface/swift-transformers", from: "1.3.0"),
24 + ],
25 + targets: [
26 + .executableTarget(
27 + name: "ZyquoMLX",
28 + dependencies: [
29 + .product(name: "MLX", package: "mlx-swift"),
30 + .product(name: "MLXNN", package: "mlx-swift"),
31 + .product(name: "MLXOptimizers", package: "mlx-swift"),
32 + .product(name: "MLXRandom", package: "mlx-swift"),
33 + .product(name: "MLXLMCommon", package: "mlx-swift-lm"),
34 + .product(name: "MLXLLM", package: "mlx-swift-lm"),
35 + .product(name: "MLXVLM", package: "mlx-swift-lm"),
36 + .product(name: "MLXEmbedders", package: "mlx-swift-lm"),
37 + .product(name: "MLXHuggingFace", package: "mlx-swift-lm"),
38 + .product(name: "HuggingFace", package: "swift-huggingface"),
39 + .product(name: "Tokenizers", package: "swift-transformers"),
40 + ],
41 + path: "Sources/ZyquoMLX"
42 + )
43 + ]
44 +)
added README.md +55 −0
@@ -0,0 +1,55 @@
1 +<!--
2 + README.md
3 + Zyquo MLX
4 +
5 + Author: Simon-Pierre Boucher
6 + Mail: contact@spboucher.ai
7 +-->
8 +
9 +# Zyquo MLX
10 +
11 +**Zyquo MLX** is the foundry of the Zyquo family: a native macOS workbench for
12 +the full on-device MLX lifecycle on Apple Silicon — inference of every
13 +supported model type, LoRA/QLoRA and full fine-tuning, quantization, format
14 +conversion, dataset preparation, training runs with live metrics, evaluation,
15 +and export. Swift + SwiftUI, built without the Xcode IDE.
16 +
17 +## Requirements
18 +
19 +- Apple Silicon Mac (arm64 only — MLX requires it), macOS 14+
20 +- Full Xcode installed **as a toolchain only** (the IDE is never opened) with
21 + the Metal toolchain component — see `docs/BUILD.md` §2:
22 + ```bash
23 + sudo xcode-select -s /Applications/Xcode.app
24 + sudo xcodebuild -license accept
25 + xcodebuild -downloadComponent metalToolchain
26 + ```
27 +- `uv` (Python-side pipelines are provisioned at first run into
28 + `~/Library/Application Support/ZyquoMLX/py/`)
29 +- For the icon pipeline: `brew install librsvg`
30 +
31 +## Build
32 +
33 +```bash
34 +make app # release build + assemble "Zyquo MLX.app" (ad-hoc signed)
35 +make dev # build + launch
36 +make release # Developer ID signed + notarized (Phase 8)
37 +```
38 +
39 +Everything is driven by the `Makefile` — command-line `swift build` /
40 +`xcodebuild` only; no `.xcodeproj` exists or ever will.
41 +
42 +## Documentation
43 +
44 +- `docs/PLAN.md` — phase-by-phase execution plan and checkpoints
45 +- `docs/MLX-RESEARCH.md` — MLX framework ground truth (verified 2026-07-30)
46 +- `docs/TRAINING-RESEARCH.md` — fine-tuning on MLX, concretely
47 +- `docs/MODELS.md` — Hub API + live-verified curated catalog
48 +- `docs/BUILD.md` — the no-Xcode-IDE build recipe (incl. Metal toolchain)
49 +
50 +## Data locations
51 +
52 +- Models: `~/Library/Application Support/ZyquoMLX/Models/`
53 +- Datasets: `~/Library/Application Support/ZyquoMLX/Datasets/`
54 +- Training runs: `~/Library/Application Support/ZyquoMLX/Runs/`
55 +- Python env: `~/Library/Application Support/ZyquoMLX/py/`
added Sources/ZyquoMLX/App/HardwareGate.swift +45 −0
@@ -0,0 +1,45 @@
1 +//
2 +// HardwareGate.swift
3 +// Zyquo MLX
4 +//
5 +// Author: Simon-Pierre Boucher
6 +// Mail: contact@spboucher.ai
7 +//
8 +
9 +import Foundation
10 +import SwiftUI
11 +
12 +/// MLX requires Apple Silicon. The binary itself is arm64-only, so on an
13 +/// Intel Mac it will not load at all — this runtime check is defense in depth
14 +/// (e.g. exotic translation environments) and drives the polite
15 +/// unsupported-hardware screen required by the project charter.
16 +enum HardwareGate {
17 +
18 + /// True when running natively on Apple Silicon.
19 + static let isAppleSilicon: Bool = {
20 + var value: Int32 = 0
21 + var size = MemoryLayout<Int32>.size
22 + // hw.optional.arm64 is 1 on Apple Silicon, absent/0 elsewhere.
23 + let result = sysctlbyname("hw.optional.arm64", &value, &size, nil, 0)
24 + return result == 0 && value == 1
25 + }()
26 +}
27 +
28 +/// Polite, clear unsupported-hardware screen (charter requirement).
29 +struct UnsupportedHardwareView: View {
30 + var body: some View {
31 + VStack(spacing: 16) {
32 + Image(systemName: "cpu")
33 + .font(.system(size: 48, weight: .light))
34 + .foregroundStyle(.secondary)
35 + Text("Apple Silicon Required")
36 + .font(.title2.weight(.semibold))
37 + Text("Zyquo MLX is built on MLX, Apple's machine-learning framework, which runs exclusively on Apple Silicon (M-series) Macs. This Mac does not support it.")
38 + .multilineTextAlignment(.center)
39 + .foregroundStyle(.secondary)
40 + .frame(maxWidth: 420)
41 + }
42 + .padding(48)
43 + .frame(minWidth: 560, minHeight: 360)
44 + }
45 +}
added Sources/ZyquoMLX/App/ZyquoMLXApp.swift +51 −0
@@ -0,0 +1,51 @@
1 +//
2 +// ZyquoMLXApp.swift
3 +// Zyquo MLX
4 +//
5 +// Author: Simon-Pierre Boucher
6 +// Mail: contact@spboucher.ai
7 +//
8 +
9 +import SwiftUI
10 +
11 +/// Zyquo MLX — the local MLX foundry for the Mac.
12 +///
13 +/// Entry point. Gates on Apple Silicon (MLX requires it), activates the app
14 +/// properly when launched from a terminal, and hosts the main workbench window.
15 +@main
16 +struct ZyquoMLXApp: App {
17 +
18 + init() {
19 + // Launching a bare executable from the terminal does not activate it;
20 + // make sure the window comes to the front like a real Mac app.
21 + DispatchQueue.main.async {
22 + NSApplication.shared.setActivationPolicy(.regular)
23 + NSApplication.shared.activate(ignoringOtherApps: true)
24 + }
25 + }
26 +
27 + var body: some Scene {
28 + WindowGroup {
29 + if HardwareGate.isAppleSilicon {
30 + PlaceholderRootView()
31 + .frame(minWidth: 1080, minHeight: 700)
32 + } else {
33 + UnsupportedHardwareView()
34 + }
35 + }
36 + .defaultSize(width: 1360, height: 880)
37 + }
38 +}
39 +
40 +/// Temporary Phase 1 root; replaced by the workbench in Phase 2/4.
41 +private struct PlaceholderRootView: View {
42 + var body: some View {
43 + VStack(spacing: 8) {
44 + Text("Zyquo MLX")
45 + .font(.largeTitle.weight(.semibold))
46 + Text("Foundry under construction — Phase 1")
47 + .foregroundStyle(.secondary)
48 + }
49 + .frame(maxWidth: .infinity, maxHeight: .infinity)
50 + }
51 +}
added Support/Info.plist +45 −0
@@ -0,0 +1,45 @@
1 +<?xml version="1.0" encoding="UTF-8"?>
2 +<!--
3 + Info.plist
4 + Zyquo MLX
5 +
6 + Author: Simon-Pierre Boucher
7 + Mail: contact@spboucher.ai
8 +-->
9 +<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
10 +<plist version="1.0">
11 +<dict>
12 + <key>CFBundleDevelopmentRegion</key>
13 + <string>en</string>
14 + <key>CFBundleDisplayName</key>
15 + <string>Zyquo MLX</string>
16 + <key>CFBundleName</key>
17 + <string>Zyquo MLX</string>
18 + <key>CFBundleExecutable</key>
19 + <string>ZyquoMLX</string>
20 + <key>CFBundleIdentifier</key>
21 + <string>com.zyquo.mlx</string>
22 + <key>CFBundlePackageType</key>
23 + <string>APPL</string>
24 + <key>CFBundleShortVersionString</key>
25 + <string>0.1.0</string>
26 + <key>CFBundleVersion</key>
27 + <string>1</string>
28 + <key>CFBundleIconFile</key>
29 + <string>AppIcon</string>
30 + <key>LSMinimumSystemVersion</key>
31 + <string>14.0</string>
32 + <key>LSApplicationCategoryType</key>
33 + <string>public.app-category.developer-tools</string>
34 + <key>LSArchitecturePriority</key>
35 + <array>
36 + <string>arm64</string>
37 + </array>
38 + <key>NSHighResolutionCapable</key>
39 + <true/>
40 + <key>NSHumanReadableCopyright</key>
41 + <string>© 2026 Simon-Pierre Boucher</string>
42 + <key>NSPrincipalClass</key>
43 + <string>NSApplication</string>
44 +</dict>
45 +</plist>
modified docs/PLAN.md +10 −1
@@ -65,7 +65,16 @@ Metal kernel compilation → strategy: full Xcode as toolchain, CLI-only builds,
65 65
66 66 ---
67 67
68 ## Phase 1 — Project Setup (not started)
68 +## Phase 1 — Project Setup (in progress)
69 +
70 +- [ ] Xcode toolchain provisioned (CLI-only; Metal toolchain component) — download in progress
71 +- [ ] `Package.swift` — target `ZyquoMLX`, deps per MLX-RESEARCH.md §8
72 +- [ ] `Makefile` — build / app / dev / icon / clean (+ release stub for Phase 8)
73 +- [ ] `Info.plist` — Zyquo MLX, com.zyquo.mlx, macOS 14+, arm64, developer-tools
74 +- [ ] `@main` SwiftUI entry point + Apple-Silicon gate + terminal activation
75 +- [ ] Python bootstrap plan wired (first-run venv per BUILD.md §3.4 — code lands Phase 3)
76 +- [ ] `README.md` (build instructions)
77 +- [ ] Phase checkpoint: `swift build`/`xcodebuild` green, app launches, zero warnings
69 78 ## Phase 2 — Architecture + Inference POC (not started)
70 79 ## Phase 3 — Training, Quantization & Conversion (not started)
71 80 ## Phase 4 — Design System & UI (not started)
72 81