# How Keyboard Shortcuts Are Managed in OpenSuperWhisper: Inside the ShortcutManager Singleton

> Discover how OpenSuperWhisper manages keyboard shortcuts with the ShortcutManager singleton, utilizing standard hotkeys, modifier keys, and mouse buttons for efficient control. Learn more about this macOS feature.

- Repository: [Starmel/OpenSuperWhisper](https://github.com/Starmel/OpenSuperWhisper)
- Tags: internals
- Published: 2026-07-05

---

**OpenSuperWhisper centralizes all keyboard shortcut handling in a `ShortcutManager` singleton that orchestrates three mutually exclusive trigger modes—standard hotkeys, modifier-only keys, and mouse buttons—using the KeyboardShortcuts Swift package alongside custom macOS event monitors.**

OpenSuperWhisper, the open-source macOS transcription app developed by Starmel, implements a sophisticated keyboard shortcut system that allows users to trigger voice recording from anywhere in the system. The architecture revolves around a single coordinator that manages multiple input modalities while ensuring only one trigger remains active at any given time. Understanding how these keyboard shortcuts are managed reveals a clean Swift implementation that balances flexibility with system-level event handling.

## The ShortcutManager Singleton Architecture

At the core of the system lies **`ShortcutManager`**, a singleton class defined in [`OpenSuperWhisper/ShortcutManager.swift`](https://github.com/Starmel/OpenSuperWhisper/blob/main/OpenSuperWhisper/ShortcutManager.swift) that acts as the central dispatcher for all recording triggers. Rather than scattering hotkey logic across view controllers, the manager encapsulates registration, monitoring, and state management in one location.

The manager leverages the **KeyboardShortcuts** Swift package by Sindre Sorhus to handle standard keyboard combinations. During application launch, it registers the default "toggle-record" hotkey (⌥ `, Option plus backtick) and an escape key listener using `KeyboardShortcuts.enable(.toggleRecord)`. This library abstracts away the complexity of macOS global hotkey registration while providing a native recorder UI for user customization.

## Three Mutually Exclusive Trigger Modes

The `ShortcutManager` supports three distinct input methods, but only one can be active simultaneously. The selection depends on user preferences stored in **`AppPreferences`**, a persisted configuration layer located in [`OpenSuperWhisper/Utils/AppPreferences.swift`](https://github.com/Starmel/OpenSuperWhisper/blob/main/OpenSuperWhisper/Utils/AppPreferences.swift).

### Standard Keyboard Shortcuts via KeyboardShortcuts

By default, the system uses a conventional keyboard shortcut managed by the KeyboardShortcuts package. When this mode is active, the manager calls `KeyboardShortcuts.enable(.toggleRecord)` to register a global hotkey that works across all macOS applications. The default binding uses `KeyboardShortcuts.Name("toggleRecord", default: .init(.backtick, modifiers: .option))`, though users can customize this through the recorder control.

### Modifier-Only Hotkeys with ModifierKeyMonitor

When users enable the modifier-only mode by setting `AppPreferences.shared.modifierOnlyHotkey` to a value like `ModifierKey.leftOption.rawValue`, the manager initializes **`ModifierKeyMonitor`** from [`OpenSuperWhisper/ModifierKeyMonitor.swift`](https://github.com/Starmel/OpenSuperWhisper/blob/main/OpenSuperWhisper/ModifierKeyMonitor.swift). This class creates a global event tap that watches for key-down and key-up events on the specified modifier key (Command, Option, Control, or Shift) without requiring an additional character key. The monitor forwards these events directly to `ShortcutManager` to trigger recording state changes.

### Mouse Button Triggers via MouseButtonMonitor

For users preferring mouse input, setting `AppPreferences.shared.mouseButtonHotkey` to values like `MouseButton.button4.rawValue` activates **`MouseButtonMonitor`** in [`OpenSuperWhisper/MouseButtonMonitor.swift`](https://github.com/Starmel/OpenSuperWhisper/blob/main/OpenSuperWhisper/MouseButtonMonitor.swift). This monitor establishes a global event tap that detects presses on extra mouse buttons (Middle, Button 4, or Button 5) and translates them into recording commands. This implementation allows hardware buttons on advanced mice to control transcription without keyboard interaction.

## Hold-to-Record Implementation

Beyond simple toggling, `ShortcutManager` implements a **hold-to-record** mode controlled by the `AppPreferences.shared.holdToRecord` boolean. When enabled, the manager uses a `DispatchWorkItem` to detect sustained presses exceeding **0.3 seconds** (the `holdThreshold`).

Upon detecting a key-down or button-down event in `handleKeyDown()`, the manager immediately begins recording but schedules a delayed work item. If the user releases the input before the threshold elapses, the recording stops immediately. If the threshold passes, the work item sets `holdMode = true`, and the recording continues until the corresponding key-up event occurs. This logic allows the same physical input to function as either a toggle or a push-to-talk mechanism depending on user preference.

## Dynamic Configuration and NotificationCenter

The system remains responsive to preference changes through **`NotificationCenter`**. When users modify hotkey settings via the UI, the application posts a `.hotkeySettingsChanged` notification. The `ShortcutManager` observes this notification and invokes `setupRecordingTrigger()`, which performs a complete teardown of existing monitors before reinitializing the appropriate trigger type.

This ensures that switching from a keyboard shortcut to a mouse button trigger (or vice versa) happens atomically without leaving orphaned event taps or conflicting registrations. The manager guarantees system stability by validating that only one monitoring mechanism remains active at any given time.

## Code Implementation Examples

The following examples demonstrate how to interact with the keyboard shortcut system programmatically:

**Registering a custom hotkey using the KeyboardShortcuts API:**

```swift
import KeyboardShortcuts

extension KeyboardShortcuts.Name {
    static let toggleRecord = Self("toggleRecord", default: .init(.backtick,
                                                                modifiers: .option))
}

// In your Settings view
KeyboardShortcuts.Recorder(for: .toggleRecord)

```

**Switching trigger modes via AppPreferences:**

```swift
// Enable Option key-only hotkey
AppPreferences.shared.modifierOnlyHotkey = ModifierKey.leftOption.rawValue

// Or enable mouse button 4 (Back button)
AppPreferences.shared.mouseButtonHotkey = MouseButton.button4.rawValue

// Trigger reconfiguration
NotificationCenter.default.post(name: .hotkeySettingsChanged, object: nil)

```

**Handling key-down events with hold-to-record logic:**

```swift
private func handleKeyDown() {
    holdWorkItem?.cancel()
    holdMode = false
    
    let holdEnabled = AppPreferences.shared.holdToRecord
    
    Task { @MainActor in
        if activeVm == nil {
            let vm = IndicatorWindowManager.shared.show(nearPoint: cursorPosition)
            vm.startRecording()
            activeVm = vm
        } else if !holdMode {
            IndicatorWindowManager.shared.stopRecording()
            activeVm = nil
        }
    }
    
    if holdEnabled {
        let workItem = DispatchWorkItem { [weak self] in self?.holdMode = true }
        holdWorkItem = workItem
        DispatchQueue.main.asyncAfter(deadline: .now() + holdThreshold,
                                      execute: workItem)
    }
}

```

## Summary

- **Centralized Control**: All keyboard shortcut logic resides in the `ShortcutManager` singleton located in [`OpenSuperWhisper/ShortcutManager.swift`](https://github.com/Starmel/OpenSuperWhisper/blob/main/OpenSuperWhisper/ShortcutManager.swift).
- **Three Trigger Modes**: The system supports standard hotkeys (KeyboardShortcuts package), modifier-only keys (ModifierKeyMonitor), and mouse buttons (MouseButtonMonitor).
- **Preference-Driven**: `AppPreferences` stores user selections for `modifierOnlyHotkey`, `mouseButtonHotkey`, and `holdToRecord`, persisting across app launches.
- **Dynamic Reconfiguration**: The `.hotkeySettingsChanged` notification triggers atomic teardown and reinitialization of monitors when settings change.
- **Hold-to-Record**: A 0.3-second threshold using `DispatchWorkItem` distinguishes between toggle and push-to-talk behaviors.
- **Global Accessibility**: All monitors use macOS global event taps, allowing recording initiation from any application context.

## Frequently Asked Questions

### What is the default keyboard shortcut in OpenSuperWhisper?

The default keyboard shortcut is **Option + Backtick** (⌥ `). This is registered at launch via the KeyboardShortcuts package using `KeyboardShortcuts.enable(.toggleRecord)` with a default value of `.init(.backtick, modifiers: .option)` in the `toggleRecord` name extension.

### How does the modifier-only hotkey mode work?

When enabled through `AppPreferences.shared.modifierOnlyHotkey`, the `ModifierKeyMonitor` class creates a global event tap that monitors only the specified modifier key (such as Left Option or Right Command) for press and release events. This allows users to trigger recording by pressing and holding a modifier key alone, without combining it with a character key.

### Can I use a mouse button instead of a keyboard shortcut?

Yes. By setting `AppPreferences.shared.mouseButtonHotkey` to values like `MouseButton.button4` or `MouseButton.middle`, you activate `MouseButtonMonitor`, which watches for presses on extra mouse buttons. This is particularly useful for mice with dedicated "back" or "forward" buttons that can be repurposed for voice recording control.

### What happens when I change hotkey settings while the app is running?

When preferences change, the app posts a `.hotkeySettingsChanged` notification. The `ShortcutManager` receives this notification and calls `setupRecordingTrigger()`, which tears down any active monitors (keyboard, modifier, or mouse) and reinitializes the appropriate trigger based on the new preferences. This ensures clean transitions between input methods without system conflicts or duplicate registrations.