Architecture
How the pieces fit, for contributors and anyone forking Warble.
Warble is a Swift package with two targets: WarbleKit, the library with all the logic and UI, and warble, a thin executable for the CLI and app entry point.
hotkey ─▶ DictationController ─▶ AudioRecorder ─▶ ParakeetTranscriber
│ │
▼ ▼
AppState ◀──────── DictionaryEngine ◀── raw text
┌────────┼─────────┐
▼ ▼ ▼
menu bar pill windows ─▶ HistoryStore, DictionaryStore, SettingsModelModules
AppDelegate.swift
DictationController.swift
ModelLoader.swift
HotkeyController.swift
SoundPlayer.swift
AudioRecorder.swift
ParakeetTranscriber.swift
TextInserter.swift
| Piece | Responsibility |
|---|---|
AppDelegate | Wires everything together and walks launch: settings, permissions, model, hotkey. |
DictationController | Key down to typed text: record, transcribe, apply the dictionary, paste, save to history. |
AppState | Observable single source of truth: dictation phase, model status, waveform levels. |
AudioRecorder | Microphone via AVAudioEngine and system audio via ScreenCaptureKit, written as 16 kHz mono. |
ParakeetTranscriber | FluidAudio's AsrManager with Parakeet TDT v3, loaded once and shared. |
TextInserter | Pastes through the clipboard and restores what was there before. |
RecordingPillController | A click-through NSPanel hosting the SwiftUI pill on every Space. |
WindowCoordinator | Main and setup windows; shows a Dock icon only while one is open. |
Design choices
- One phase enum.
DictationPhasedrives the icon, the pill and the sidebar status, so they cannot disagree. - Plain files. History, dictionary and settings are JSON a user can read, back up or delete.
- No silent data loss. A file that fails to decode is moved aside as
*.corrupt-<time>.jsonbefore anything new is written. - Testable core. Dictionary matching, stats, audio levels and the phase machine are pure and covered by unit tests.