openquack

Architecture

A practical map of where things live and why. For why OpenQuack exists, see VISION.md; for the state of work, see ROADMAP.md.

Layout

local_quack/
├── Package.swift              SPM manifest — one library, three executables
├── Sources/
│   ├── OpenQuackKit/          Library — UI-free brain, used by all three exes
│   │   ├── Audio/             AVAudioEngine capture, 16 kHz mono float32
│   │   ├── Transcription/     WhisperKit engine + model manager
│   │   ├── Hotkey/            KeyboardShortcuts wrapper
│   │   ├── Output/            NSPasteboard + CGEvent ⌘V
│   │   ├── Polish/            Optional LLM cleanup (M2.5, opt-in)
│   │   ├── Metrics/           WER / CER / RTF / TTFT / RSS / host info
│   │   └── Updates/           Sparkle integration
│   ├── OpenQuackApp/          The menu-bar app — pure AppKit shell
│   ├── OpenQuackBench/        `openquack-bench` — characterisation CLI
│   └── OpenQuackCLI/          `openquack-cli` — headless dictation/transcribe
├── Tests/OpenQuackKitTests/   Library unit tests
├── bench/
│   ├── corpus/                Audio + reference text (audio gitignored)
│   ├── engines/               Helper scripts for non-Swift engines
│   └── out/                   Per-host benchmark reports
└── docs/

Why one library, three executables

The library (OpenQuackKit) owns capture, transcription, polish, and metrics. Everything UI-free. Three thin executables consume it:

The split keeps GUI noise out of the bench, lets contributors run characterisation without launching an app, and makes it easy to add future surfaces (a LaunchBar action, a Shortcuts intent) without duplicating the brain.

Why no Xcode project

Pure SPM. swift build, swift test, swift run openquack-bench all work from a clean checkout with just the toolchain — no Xcode required beyond what SwiftPM itself needs (and even that is only because some deps include #Preview blocks). The signed .app is assembled by scripts/wrap_app.sh, which wraps the SPM build product in a minimal bundle. See DEVELOPMENT.md for the full build flow.

Measure-first

The bench was built before the app. Default model, minimum supported Mac, and what shows up in Settings → Speech-to-text are all decided from numbers in BENCHMARKS.md, not assumption. Same discipline applies to M2.5 (LLM polish) and beyond — each new model or engine lands in OpenQuackBench first.