Skip to content

Local AI-powered dictation for macOS using WhisperKit. 100% local processing, no cloud required.

License

Notifications You must be signed in to change notification settings

davidcv5/VoxScript

Repository files navigation

VoxScript

Local AI-powered dictation for macOS using WhisperKit

macOS Apple Silicon Swift License

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                                                                 β”‚
β”‚   🎀 VoxScript - Local Dictation for macOS                     β”‚
β”‚                                                                 β”‚
β”‚   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”       β”‚
β”‚   β”‚   Record    β”‚ -> β”‚  WhisperKit  β”‚ -> β”‚  Insert at  β”‚       β”‚
β”‚   β”‚   Audio     β”‚    β”‚  Transcribe  β”‚    β”‚   Cursor    β”‚       β”‚
β”‚   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜       β”‚
β”‚                             β”‚                                   β”‚
β”‚                             β–Ό                                   β”‚
β”‚                    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”                            β”‚
β”‚                    β”‚   Ollama     β”‚                            β”‚
β”‚                    β”‚  (Optional)  β”‚                            β”‚
β”‚                    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜                            β”‚
β”‚                                                                 β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Features

  • 100% Local Processing - All transcription happens on-device using Apple Silicon
  • Global Hotkeys - Press βŒ˜β‡§Space anywhere to start/stop recording
  • Multiple Recording Modes - Toggle, Push-to-Talk, or Continuous with silence detection
  • Optional Post-Processing - Clean up text with local Ollama LLM
  • Menu Bar App - Runs quietly in the background
  • Works Everywhere - Text insertion works in standard apps AND terminal emulators

Architecture

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                     VoxScript.app                            β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚                                                              β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”‚
β”‚  β”‚                    VoxScriptApp                        β”‚  β”‚
β”‚  β”‚                 (App Entry Point)                      β”‚  β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β”‚
β”‚                           β”‚                                  β”‚
β”‚           β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”                 β”‚
β”‚           β–Ό               β–Ό               β–Ό                 β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”      β”‚
β”‚  β”‚  StatusBar  β”‚ β”‚ FloatingPanelβ”‚ β”‚   HotkeyManager β”‚      β”‚
β”‚  β”‚ Controller  β”‚ β”‚  Controller  β”‚ β”‚                 β”‚      β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜      β”‚
β”‚                                                              β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”‚
β”‚  β”‚                    Core Services                       β”‚  β”‚
β”‚  β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€  β”‚
β”‚  β”‚AudioRecorder β”‚TranscriptionE β”‚    PostProcessor      β”‚  β”‚
β”‚  β”‚ (AVAudioEng) β”‚ (WhisperKit)  β”‚     (Ollama)         β”‚  β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β”‚
β”‚                                                              β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”‚
β”‚  β”‚                      Models                            β”‚  β”‚
β”‚  β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€  β”‚
β”‚  β”‚  AppState   β”‚  Settings   β”‚  TranscriptionResult    β”‚  β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β”‚
β”‚                                                              β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Requirements

  • macOS 14.0+ (Sonoma or later)
  • Apple Silicon (M1/M2/M3/M4)
  • ~1-2GB disk space for Whisper model

Installation

Download Release

Download the latest DMG from the Releases page.

Build from Source

# Clone the repository
git clone https://github.com/davidcv5/VoxScript.git
cd VoxScript

# Open in Xcode
open VoxScript.xcodeproj

# Build and Run (⌘R)

Or build via command line:

xcodebuild -project VoxScript.xcodeproj -scheme VoxScript -configuration Release

Dependencies

Package Version Purpose
WhisperKit 0.15.0+ Speech-to-text engine
KeyboardShortcuts 2.0.0+ Global hotkey handling

Optional

  • Ollama - For post-processing text cleanup (install separately)

Usage

  1. Launch VoxScript - It appears in the menu bar
  2. Press βŒ˜β‡§Space to start recording
  3. Speak your text
  4. Press βŒ˜β‡§Space again to stop and transcribe
  5. Text is automatically inserted at cursor

First Run

On first launch, VoxScript will:

  1. Request Microphone permission
  2. Request Accessibility permission (for global shortcuts)
  3. Download the default Whisper model (~1GB)

Keyboard Shortcuts

Action Shortcut
Toggle Recording βŒ˜β‡§Space
Cancel Recording Escape
Open Settings ⌘,

Recording Modes

Mode Behavior
Toggle Press to start, press again to stop
Push-to-Talk Hold key to record, release to transcribe
Continuous Auto-stops after detecting silence (2s)

Available Models

Model Size Speed Accuracy
large-v3-turbo ~950MB Fast Excellent
large-v3 ~1.5GB Slower Best
small.en ~460MB Very fast Good (English)
base ~140MB Fastest Basic
tiny ~75MB Instant Testing only

Data Flow

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”     β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”     β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ Mic/User │────▢│ AudioRecorder │────▢│ Temp WAV Fileβ”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜     β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜     β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                                              β”‚
                                              β–Ό
                       β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
                       β”‚        TranscriptionEngine           β”‚
                       β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”‚
                       β”‚  β”‚         WhisperKit            β”‚   β”‚
                       β”‚  β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”‚   β”‚
                       β”‚  β”‚  β”‚ Model  β”‚ + β”‚ CoreML/ANEβ”‚  β”‚   β”‚
                       β”‚  β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β”‚   β”‚
                       β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β”‚
                       β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                                              β”‚
                                              β–Ό
                               β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
                               β”‚  TranscriptionResult β”‚
                               β”‚  { text, language }  β”‚
                               β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                                              β”‚
                         β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
                         β”‚                    β”‚                    β”‚
                         β–Ό                    β”‚                    β–Ό
              β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”            β”‚         β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
              β”‚ Post-Processing β”‚β—€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜         β”‚ ClipboardManagerβ”‚
              β”‚    (Optional)   β”‚                      β”‚                 β”‚
              β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚                      β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”‚
              β”‚ β”‚   Ollama    β”‚ β”‚                      β”‚  β”‚  Paste/   β”‚  β”‚
              β”‚ β”‚   llama3.2  β”‚ │─────────────────────▢│  β”‚  Insert   β”‚  β”‚
              β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚                      β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β”‚
              β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜                      β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                                                                β”‚
                                                                β–Ό
                                                       β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
                                                       β”‚ Target App   β”‚
                                                       β”‚ (at cursor)  β”‚
                                                       β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Settings

Access via menu bar icon β†’ Settings (⌘,)

  • General: Launch at login, sounds, floating indicator
  • Transcription: Model selection, language, post-processing
  • Shortcuts: Customize keyboard shortcuts
  • Advanced: Insert directly, trailing newline, silence detection

Privacy

  • All processing happens locally on your device
  • No data is sent to any cloud service
  • Audio is only saved temporarily during transcription
  • No telemetry or usage tracking

Project Structure

VoxScript/
β”œβ”€β”€ Package.swift                    # Swift Package Manager dependencies
β”œβ”€β”€ VoxScript.xcodeproj/
β”œβ”€β”€ VoxScript/
β”‚   β”œβ”€β”€ VoxScriptApp.swift           # Main app entry point
β”‚   β”œβ”€β”€ Info.plist                   # App configuration
β”‚   β”œβ”€β”€ VoxScript.entitlements       # Audio, automation entitlements
β”‚   β”œβ”€β”€ Core/
β”‚   β”‚   β”œβ”€β”€ TranscriptionEngine.swift   # WhisperKit wrapper (singleton)
β”‚   β”‚   β”œβ”€β”€ AudioRecorder.swift         # AVAudioEngine recording
β”‚   β”‚   β”œβ”€β”€ HotkeyManager.swift         # KeyboardShortcuts wrapper
β”‚   β”‚   β”œβ”€β”€ ClipboardManager.swift      # Text insertion with terminal detection
β”‚   β”‚   └── PostProcessor.swift         # Ollama integration
β”‚   β”œβ”€β”€ UI/
β”‚   β”‚   β”œβ”€β”€ FloatingPanel/              # Recording indicator
β”‚   β”‚   β”œβ”€β”€ Settings/                   # Settings tabs
β”‚   β”‚   β”œβ”€β”€ Onboarding/                 # First-run setup
β”‚   β”‚   └── MenuBar/                    # Status bar controller
β”‚   β”œβ”€β”€ Models/
β”‚   β”‚   β”œβ”€β”€ AppState.swift              # Observable app state
β”‚   β”‚   β”œβ”€β”€ Settings.swift              # User preferences
β”‚   β”‚   └── TranscriptionResult.swift   # Result model
β”‚   └── Utilities/
β”‚       β”œβ”€β”€ Permissions.swift           # Permission helpers
β”‚       └── SoundPlayer.swift           # Audio feedback
└── VoxScriptTests/                     # Unit tests

Troubleshooting

Text not inserting in Terminal/iTerm2

VoxScript automatically detects terminal apps and uses a different insertion method. If it's still not working:

  1. Open Settings β†’ Advanced
  2. Disable "Insert directly"
  3. Manually paste with ⌘V after transcription

Model download fails

  1. Check your internet connection
  2. Try a smaller model first (base or tiny)
  3. Check available disk space

Shortcut not working

  1. Ensure Accessibility permission is granted
  2. Check System Settings β†’ Privacy & Security β†’ Accessibility
  3. Toggle VoxScript off and on in the list

Contributing

Contributions are welcome! Please:

  1. Fork the repository
  2. Create a feature branch (git checkout -b feature/amazing-feature)
  3. Commit your changes (git commit -m 'Add amazing feature')
  4. Push to the branch (git push origin feature/amazing-feature)
  5. Open a Pull Request

License

MIT License - see LICENSE for details.

Credits

See Also

  • VoxScript PRD - Full product requirements document with implementation notes

About

Local AI-powered dictation for macOS using WhisperKit. 100% local processing, no cloud required.

Topics

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Contributors 2

  •  
  •