How Hold-to-Record Mode Works with Modifier Keys in OpenSuperWhisper

OpenSuperWhisper enables push-to-talk recording by holding a single modifier key (⌘, ⌥, ⇧, ⌃, or Fn), using a low-level event tap to start transcription immediately on key-down and stop on key-up after a 0.3-second threshold.

OpenSuperWhisper is an open-source macOS dictation application that supports hold-to-record functionality using single modifier keys without complex shortcuts. The implementation relies on a preference-driven architecture that coordinates between user settings, event monitoring, and recording state management. Understanding how hold-to-record mode works with modifier keys requires examining the flow from AppPreferences through ShortcutManager to the low-level ModifierKeyMonitor.

Architecture Overview

The hold-to-record system combines preference storage, trigger selection, and event monitoring to provide seamless voice transcription control.

Preference Configuration

User settings drive the hold-to-record behavior through two key properties in AppPreferences.swift:

  • AppPreferences.shared.holdToRecord: A boolean toggle that enables the feature (defaults to true)
  • AppPreferences.shared.modifierOnlyHotkey: Stores the selected modifier key as an enum value (.none indicates standard shortcut mode should be used instead)

When modifierOnlyHotkey is set to a specific key like .rightOption or .leftCommand, the system switches from standard keyboard shortcuts to modifier-only monitoring.

Trigger Selection Logic

The ShortcutManager.setupRecordingTrigger() method in ShortcutManager.swift determines which input method to activate based on preference hierarchy:

  1. Mouse button hotkey takes precedence if configured
  2. Modifier-only mode activates if modifierOnlyHotkey ≠ .none, which starts a ModifierKeyMonitor instance for the selected key and disables the normal keyboard shortcut
  3. Standard shortcut operates if neither specialized mode is active

This priority system ensures only one trigger mechanism is active at any time to prevent conflicts.

Low-Level Event Monitoring

When modifier-only mode is selected, ModifierKeyMonitor (implemented in ModifierKeyMonitor.swift) creates a Core Graphics event tap that monitors system-wide flagsChanged events. The monitor:

  • Filters for events matching the chosen modifier key's keyCode
  • Invokes onKeyDown when the key is pressed
  • Invokes onKeyUp when the key is released

This low-level access allows the app to detect modifier key states even when OpenSuperWhisper is not the active application.

Recording State Management

Both the standard shortcut and modifier-key monitor forward events to the same callbacks in ShortcutManager:

On key-down (handleKeyDown):

  • Recording starts immediately
  • A DispatchWorkItem is scheduled to execute after the holdThreshold (0.3 seconds)
  • When the work item fires, it sets an internal holdMode flag to true

On key-up (handleKeyUp):

  • The pending DispatchWorkItem is cancelled
  • If holdMode is true (meaning the key was held longer than 0.3 seconds), the recording stops and holdMode resets to false

This timing mechanism distinguishes between a quick tap (which might trigger other actions) and an intentional hold-to-record gesture.

Implementation Examples

Configure the hold-to-record preference and select a modifier key in the settings UI:

// Settings.swift - Toggle for enabling the feature
Toggle("Hold-to-record", isOn: $viewModel.holdToRecord)
// Stores to AppPreferences.shared.holdToRecord

// Picker for selecting a single modifier key
Picker("Modifier", selection: $viewModel.modifierOnlyHotkey) {
    ForEach(ModifierKey.allCases.filter { $0 != .none }) { key in
        Text(key.displayName).tag(key)
    }
}
// Stores to AppPreferences.shared.modifierOnlyHotkey

Programmatically configure the system to use Right Option key with hold-to-record:

// Configure preferences directly
AppPreferences.shared.modifierOnlyHotkey = ModifierKey.rightOption.rawValue
AppPreferences.shared.holdToRecord = true

// ShortcutManager automatically wires the monitor
// No additional code required - the shared instance listens for key-down/up

Alternative configuration using a mouse button instead of a modifier key:

// Enable mouse-button mode (takes precedence over modifier keys)
AppPreferences.shared.mouseButtonHotkey = MouseButton.right.rawValue
// Same hold-to-record logic applies via handleKeyDown/handleKeyUp

Key Source Files

File Role
OpenSuperWhisper/ShortcutManager.swift Central coordinator that decides trigger type, manages the 0.3-second hold threshold via DispatchWorkItem, and interfaces with the recording engine
OpenSuperWhisper/Utils/AppPreferences.swift Persists user settings including holdToRecord boolean and modifierOnlyHotkey enum value
OpenSuperWhisper/ModifierKeyMonitor.swift Implements low-level event tap for flagsChanged events and translates physical key presses into onKeyDown/onKeyUp callbacks
OpenSuperWhisper/Settings.swift SwiftUI interface that exposes the hold-to-record toggle and modifier key picker to users

Summary

  • Preference-driven activation: The feature is controlled by AppPreferences.shared.holdToRecord and modifierOnlyHotkey, allowing users to choose between standard shortcuts and single-key modifiers.
  • Hierarchical trigger selection: ShortcutManager.setupRecordingTrigger() prioritizes mouse buttons, then modifier keys, then standard shortcuts to prevent input conflicts.
  • Low-level event access: ModifierKeyMonitor uses a Core Graphics event tap to detect modifier key states system-wide through flagsChanged events.
  • Timed state transitions: A 0.3-second DispatchWorkItem distinguishes between taps and holds, ensuring recording only commits when the user intentionally holds the key.

Frequently Asked Questions

What modifier keys can be used for hold-to-record?

OpenSuperWhisper supports the standard macOS modifier keys: Command (⌘), Option (⌥), Shift (⇧), Control (⌃), and Function (Fn). Each key can be configured independently for left or right variants (e.g., Left Command vs. Right Command) through the ModifierKey enum in AppPreferences.swift.

How does the app distinguish between a quick tap and a hold?

The system uses a 0.3-second threshold managed by ShortcutManager. When a key is pressed, a DispatchWorkItem is scheduled to run after 0.3 seconds and set holdMode = true. If the key is released before this timer fires, the work item is cancelled and holdMode remains false, preventing the recording from stopping prematurely. Only keys held longer than this threshold trigger the hold-to-record behavior.

Can I use a mouse button instead of a keyboard modifier?

Yes. ShortcutManager.setupRecordingTrigger() checks AppPreferences.shared.mouseButtonHotkey before examining modifierOnlyHotkey. If a mouse button is configured (such as MouseButton.right), the system enables mouse-button mode and uses the same handleKeyDown/handleKeyUp callbacks, applying identical hold-to-record timing logic.

Where are the hold-to-record preferences stored?

Preferences are persisted in AppPreferences.swift using a singleton pattern (AppPreferences.shared). The holdToRecord boolean and modifierOnlyHotkey string are stored in the user's standard preferences domain, allowing settings to persist across application launches and sync with the Settings UI defined in Settings.swift.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →