Architecture

Global key listener

A native Rust process captures keystrokes system-wide, matches them against registered shortcuts, and can block matched keys from reaching other apps.

Language

Rust · rdev grab

Transport

JSON lines over stdio

Heartbeat

Every 10 seconds

Why a native process

Electron's globalShortcutcan't express hold-to-talk or reliably block a key from the focused app. VoiceFlow instead spawns a small Rust binary that uses rdev's grab API to intercept the macOS event stream, giving it press/release granularity and the ability to swallow matched keys.

App Nap prevention

On macOS the listener registers a background activity so the OS doesn't throttle it under App Nap — keystroke monitoring has to keep running even when the process looks idle.

The stdio protocol

The main process's shortcut-manager talks to the binary with newline-delimited JSON. It writes a register_hotkeys command listing the key combinations to watch; the binary streams back key events and periodic heartbeats.

main → listener (register)
{ "command": "register_hotkeys",
  "hotkeys": [ { "keys": ["ShiftLeft", "Space"] },
               { "keys": ["BackQuote"] } ] }
listener → main (events)
{ "type": "keydown", "key": "Space", "timestamp": "..." }
{ "type": "keyup",   "key": "Space", "timestamp": "..." }
{ "type": "heartbeat_ping", "id": "7", "timestamp": "..." }

Matching & blocking

The binary tracks the set of currently-pressed keys. On each press it checks whether the pressed set exactly equals any registered combo; if so, it returns None from the grab callback, which blocks the key from reaching other apps. The main process independently tracks pressed tokens to decide when to start and stop recording.

  • Shortcuts are expanded into raw key variants so left/right modifiers both match.
  • A special case blocks the Fn key (reported as Unknown(179)) when an Fn shortcut is registered.
  • Matching requires an exact set — extra held keys mean no match, keeping toggle and hold from overlapping.

Resilience

A key listener that dies or gets stuck would silently break every shortcut, so the manager supervises it aggressively.

Heartbeat watchdog

The binary emits a heartbeat every 10 s. If none arrives within 15 s, the manager restarts the process.

Stuck-key recovery

Keys held longer than 5 s are cleared (unless part of an active hold recording), so a missed key-up event can't jam a shortcut.

Auto-restart

If the process exits unexpectedly, it's respawned after ~1 s and the shortcuts are re-registered.

Editing pause

While you record a new shortcut in Settings, the listener is disabled so your keypresses don't trigger recording.

Where the binary lives

In development the manager runs the Cargo build output for your architecture (e.g. aarch64-apple-darwin). In a packaged build it's bundled as an extra resource under resources/binaries. See Build & releasefor how it's compiled and packaged.