spb/zyquo-local Public MIT
Native macOS AI chat that runs LLMs 100% locally on Apple Silicon with MLX — no cloud, no API keys.
Swift 97.2%
Shell 1.8%
Makefile 1%
1<!--2 PLAN.md3 Zyquo Local45 Author: Simon-Pierre Boucher6 Mail: contact@spboucher.ai7-->89# Zyquo Local — Build Plan1011Machine: Apple M5 Max, 18 cores, 48 GB RAM, macOS 27.0 (beta), Swift 6.4 (Command Line Tools only, no Xcode IDE installed).1213## Phase 0 — Intensive research — ✅ DONE (2026-07-30)1415- [x] Research current mlx-swift packages, versions, SPM coordinates, min macOS16- [x] Research current MLXLLM/MLXLMCommon API surface (load, tokenize, chat template, streaming, params, KV cache, unload)17- [x] Document model directory format (required files)18- [x] Document supported architectures list19- [x] Resolve the no-Xcode build question EMPIRICALLY (scratch SPM package + `swift build` with CLT only)20- [x] Decide swift-transformers vs direct HTTP HubService21- [x] Document memory model + GPU cache limits + RAM estimation22- [x] Write `docs/MLX-RESEARCH.md`23- [x] Research HF Hub HTTP API (search, model info, resolve URLs, LFS, tokens)24- [x] Curate 20–30 Featured models, live-verified on the Hub with sizes25- [x] RAM recommendation table26- [x] Write `docs/MODELS.md`2728**Checkpoint:** Stack pinned: mlx-swift-lm 3.31.4 (MLXLLM/MLXLMCommon/MLXHuggingFace)29+ swift-huggingface 0.9.0 + swift-transformers 1.3.x on mlx-swift 0.31.6.30No-Xcode question resolved empirically: Swift 6.4 `swift build` compiles Metal31kernels when a standalone `Metal.xctoolchain` is on PATH (copied from cluster32node M4M36 → `~/Developer/Metal.xctoolchain`); GPU execution verified. SwiftUI33needs `SDKROOT` pinned to MacOSX26.5.sdk (macro-plugin issue on 27.x SDKs).34Downloads: custom URLSession manager (Range-resume verified 206); tokenization35via swift-transformers. 30-model catalog live-verified with real sizes.3637## Phase 1 — Project setup — ✅ DONE (2026-07-30)3839- [x] Package.swift (tools 6.1, mlx-swift-lm 3.31.4 + swift-huggingface + swift-transformers + swift-markdown)40- [x] Makefile (SDK pin + Metal PATH, bundle assembly incl. *.bundle resources, dev/release targets)41- [x] Support/Info.plist per spec (com.zyquo.local, LSMinimumSystemVersion 14.0, arm64)42- [x] @main entry with CLI dispatch (--poc) + SwiftUI app + Apple Silicon gate43- [x] scripts/check-headers.sh sweep (green)44- [x] `make build` green, zero warnings from our sources (68 s full graph)45- [x] `make bundle-debug` produces an ad-hoc-signed arm64 bundle; CLI dispatch smoke-tested4647**Checkpoint:** Full dependency graph (2 040 tasks incl. Cmlx Metal kernels)48compiles under the pinned recipe. Bundle carries mlx-swift_Cmlx.bundle (metallib),49Hub + Crypto resource bundles. `codesign -dv`: com.zyquo.local, arm64, adhoc.50Executable dispatches --poc and exits 64 as designed.51## Phase 2 — Architecture + inference PoC — ✅ DONE (2026-07-30)5253- [x] Models/: Conversation, Message (+MessageStats), LocalModel, DownloadTask, Persona54- [x] Engine/GenerationParams.swift (Codable app params → GenerateParameters at engine boundary)55- [x] Engine/MemoryAdvisor.swift (verdicts 60 %/75 % of hw.memsize, live MLX.Memory readouts)56- [x] Engine/ChatSession.swift (history → chat template via MLX session, oldest-turn truncation keeping system prompt, KV reuse, per-call params without KV loss)57- [x] Engine/InferenceEngine.swift (actor; unloaded→loading→ready⇄generating; AsyncThrowingStream<GenerationEvent>; cancellation wired via task cancel + onTermination; unload → clearCache)58- [x] PoCRunner: `ZyquoLocal --poc <dir> "<prompt>"`59- [x] PHASE GATE: Qwen3-0.6B-4bit loaded from local dir, streamed to stdout —60 130.4 tok/s, TTFT 1.59 s, 329 tokens, peak 388 MB, stop reason `stop`.6162**Checkpoint:** Zero warnings. Engine layer fully owns inference; stats are63first-class; `<think>` content streams through (reasoning display feeds on it64in Phase 6). Multi-turn KV reuse + cancellation get their formal end-to-end65tests in the Phase 7 harness.66## Phase 3 — Hub browse & download — ✅ DONE (2026-07-30)6768- [x] HubService: live search (scopes featured/mlx-community/all-MLX, config=true arch check), tree file listing with Link-header pagination, Codable structs throughout, HF-token support, human-readable error surfaces (gated/429/…)69- [x] SupportedArchitectures shipping the verified LLMTypeRegistry list70- [x] FileTransfer: delegate-backed chunked transport, Range resume (206), transparent restart (200), 416 handling, cross-host Authorization strip, cancellation71- [x] DownloadManager: queued, 2 concurrent files, pause/resume/cancel per model, transient-drop retry with backoff, atomic .partial → final, size verification, disk pre-check (5 % headroom), manifest persisted across relaunch, speed EMA + ETA72- [x] ModelStore: scan/validate (required-file check), size on disk, delete + reclaim, reveal in Finder, last-used + per-model default params sidecar73- [x] Services: PersistenceService (JSON per conversation + generic docs), ModelCatalog (30 featured entries mirroring docs/MODELS.md, starter picks per RAM)74- [x] PHASE GATE (--hub-poc, isolated temp store): search ✅ listing ✅ download 41 MB/s ✅ pause at 27 % ✅ Range-resume from 100 MB ✅ verify ✅ scan (arch qwen3, 4bit, ctx 40960, Fits) ✅ delete ✅7576**Checkpoint:** Zero warnings. Coherence sweep: headers green, `LocalModel` is77the single term, folder structure matches the Phase 2 tree (DesignSystem/,78ViewModels/, Views/ arrive with Phases 4/6).79## Phase 4 — Design system & UI spec — ✅ DONE (2026-07-30)8081- [x] ZyquoTheme tokens: exact light palette from spec, derived graphite-green dark, semantic status colors82- [x] Typography scale (title 20 sb / body 13.5 / emphasis / caption 11 / code 12.5 mono), 1.45 line-height helper, user-adjustable chat size 12–1883- [x] Spacing 4–32, radii 6/10/14, 760 pt message column, 0.5 pt hairlines, ultra-soft shadow tokens84- [x] AccentChoice (emerald default + graphite/sky/amber/rose) + ThemeStore (mode/accent/font persisted)8586**Checkpoint:** Zero warnings. UI layout contract for Phase 6 is §4.2 of the87project CLAUDE.md (exact spec); the design quality gate (§4.4) runs before88Definition of Done.89## Phase 5 — App icon — ✅ DONE (2026-07-30)9091- [x] Both creative directions rendered and compared at 512/64 px: **Z-core chosen**92 (bold circuit-trace Z, far stronger small-size legibility); Z-chip kept as exploration93- [x] Final zyquo-local.svg: graphite gradient squircle, radial top light (no banding),94 emerald-gradient Z trace with restrained glow, routed-net stubs, node micro-highlights95- [x] Simplified 16/32 px variant (no traces/glow, thicker Z) — verified legible at 16 px96- [x] Monochrome menu bar template (18/36 px PNGs)97- [x] scripts/make-icon.sh: SVG → iconset (simple for ≤32, full for ≥64) → AppIcon.icns via iconutil98- [x] Makefile bundles AppIcon.icns + menubar PNGs into Resources99100**Checkpoint:** AppIcon.icns (652 KB) generated; LOOKed at 512/64/32/16 renders and iterated101(fixed vignette band edge). rsvg-convert installed via Homebrew per the spec's pipeline.102## Phase 6 — Features / full UI — ✅ DONE (2026-07-30)103104- [x] AppModel + ChatController (streaming, live <think> parser robust to split tags, ≤4 Hz tok/s ticker, auto-titling with model + fallback)105- [x] Sidebar: wordmark, search (verified live), New Chat, Library entry with download badge, Pinned/Today/… groups, pin/rename/delete/export context menu, footer settings + loaded-model chip with RAM dot + live memory106- [x] Chat: 52 pt header (editable title, centered model chip → switcher popover with verdicts, perf toggle, export, info popover with system prompt + params + context bar), transcript (user accentSubtle right / assistant surface left, hover timestamps, jump-to-bottom pill, streaming caret), thinking disclosure, per-message stats line, message actions (copy/edit&resend/regenerate/quote/delete)107- [x] Markdown renderer (swift-markdown blocks + AttributedString inline) with syntax-highlighted code blocks + copy108- [x] Input bar: floating card r14, attach text files (picker + drag&drop, fenced injection), prompt-library picker, params popover, ⌘↩ send / stop109- [x] Onboarding hero with starter cards (RAM-fit for THIS Mac, inline download progress)110- [x] Library: Installed (badges, verdicts, load/unload, per-model params, reveal, delete with reclaimed GB) + Discover (Featured curated sections, live search w/ scopes+filters+sort, cards flip to progress with MB/s + ETA + pause/cancel) + downloads drawer111- [x] Settings 6 tabs (General/Models&Storage w/ masked HF token/Inference w/ GPU cache limit/Appearance w/ accents + live font preview/Shortcuts/Advanced w/ export-import)112- [x] Quick Chat panel (⌥Space Carbon global hotkey, Spotlight-style, one-click load hint)113- [x] Compare mode (two engines, RAM-gated, broadcast prompt, independent streams + stats)114- [x] Menu bar extra (state + downloads glance, template icon), shortcuts (⌘N/⌘K/⌘L/⌘F/⌘↩/⇧⌘E/⌥Space), export MD + PDF115- [x] Prompt library: 56 built-in templates ({{input}} variables) + user templates; Personas store with 4 built-ins116117**Checkpoint (verified live on screen):** default model auto-loads on launch;118full chat round-trip through the real UI — user bubble, thinking disclosure,119“⚡ 107.0 tok/s · 467 tokens · 2.0s to first token” stats line, auto-title;120sidebar search filters live; Installed + Discover screens render per spec.121Zero warnings. Dark-mode + full design gate re-run before Definition of Done.122## Phase 7 — Local model verification — ✅ DONE (2026-07-30)123124- [x] `--verify` harness: download via the app's own DownloadManager, validate, load, deterministic gen, multi-turn carry-over, streaming cancellation, unload + memory-release check, tok/s + TTFT recorded125- [x] 6 models across architectures (qwen3/llama/smollm3/gemma3/qwen2-coder/R1-distill): **36/36 checks green**126- [x] Entire Featured catalog (30 repos) dry-verified live: exists + files + sizes within 10 % — **30/30**, zero corrections needed (MODELS.md ↔ ModelCatalog in sync)127- [x] Test models deleted, smallest kept for dev; results table in docs/VERIFICATION.md128129**Checkpoint:** VERIFY: ALL GREEN, exit 0. Best perf: Llama-3.2-1B at 222.8 tok/s;130unloads verified down to KBs of MLX active memory.131## Phase 8 — Signing & notarization — ✅ DONE (2026-07-30)132133- [x] zyquo-term setup inspected and reused: identity `Developer ID Application: Simon-Pierre Boucher (3YM54G49SN)`, notarytool keychain profile `MacLustr-Notarize` (verified live before use)134- [x] Support/entitlements.plist: hardened runtime, NO JIT/unsigned-memory entitlements — verified unnecessary by running MLX inference in the signed build135- [x] scripts/release.sh (`make release`): release build → bundle (incl. Cmlx metallib bundle) → sign nested bundles then app → ditto zip → notarytool submit --wait → staple → spctl → signed+notarized DMG136- [x] First submission **Accepted** (app AND dmg); `xcrun stapler validate` ✅137- [x] `spctl -a -vv`: **accepted, source=Notarized Developer ID**138- [x] Notarized app runs inference: 554.3 tok/s, TTFT 0.03 s (release build), GUI launches139- [x] Final coherence sweep: syntax palette moved into ZyquoTheme, naming fix, headers green140141**Checkpoint:** dist/Zyquo Local.app (signed, notarized, stapled) +142dist/ZyquoLocal.dmg (13 MB, notarized, stapled). `make dev` keeps ad-hoc143signing for iteration.144145---146147## Definition of Done — final review (2026-07-30)148149- [x] `make release` → Developer ID–signed, notarized, stapled app (spctl: Notarized Developer ID)150- [x] In-app HF browsing + one-click resumable downloads (pause/Range-resume verified live); Featured catalog live-verified 30/30151- [x] Chat with downloaded MLX models: streaming, multi-turn with context management, stop, stats (tok/s, TTFT), reasoning display — verified on screen and in the harness152- [x] MemoryAdvisor verdicts accurate for this Mac; load/unload verifiably frees memory (GB → KB)153- [x] Silicon-themed SVG icon (Z-core) at all sizes, .icns embedded + menu bar template; sibling DNA of Zyquo Cloud154- [x] Emerald light theme per Phase 4 token spec; dark theme derived (graphite-green) and verified on screen155- [x] Naming coherent: `Zyquo Local` user-facing, `com.zyquo.local`, `ZyquoLocal` target/data folder156- [x] Phase 7 table fully green; docs/MODELS.md ↔ ModelCatalog in sync157- [x] Mandatory header on every code file (repository-wide sweep green)158- [x] docs/PLAN.md complete with per-phase checkpoints159