INPUT & ROUTING / HOTKEYS

Hotkeys & gestures

voxctrl listens at the evdev layer on Linux for true global hotkeys — no window focus required, no compositor cooperation needed. On Windows, Win32 low-level keyboard hooks are used.

Default bindings

Gesture Keys Action
Hold-to-talk Super + Space Hold while speaking, release to deliver
Toggle-to-talk Ctrl + Super + Space Tap to start, tap again to stop
Double-tap Alt Double-tap and hold Alt to record

All configurable in Settings → Hotkeys or directly in ~/.config/voxctrl/bindings.toml. Each gesture can be disabled without deleting it.

Gesture modes

Hold

Most predictable. Press, speak, release. Mic state is unambiguous — visible in the overlay. The hold_threshold_ms field (default 200ms) sets the minimum hold duration before a recording start is registered, preventing accidental triggers.

Toggle

Hands-free. Tap once to start, tap again to stop. The RMS noise gate also stops recording on silence if configured.

Double-tap

Reuses an existing modifier without colliding with normal usage. Double-tapping Alt never fires when Alt is held as part of Alt+Tab. Default tap window (tap_ms): 250ms.

Double-tap-hold

Double-tap and keep the key held down on the second tap to start recording; release the key to stop. Enforces hold_threshold_ms on the second press to distinguish from a standard double-tap, and has a 2-minute safety timeout.

Chord

Hold one or more base keys (e.g. KEY_LEFTCTRL + KEY_LEFTALT), then press a single subkey trigger (e.g. KEY_SPACE) to start recording. Recording continues as long as the base keys remain held, and stops as soon as any base key is released — releasing the subkey alone does not stop recording. Useful for binding voice actions without colliding with desktop or application shortcuts.

Conflict detection

The Settings UI checks for collisions as you record new keys:

Recording new bindings

Press the Bind button next to a key field. The button turns orange and shows "Recording…". Press your keys. The display updates live as keys are held. Release — binding captured.

For Chord bindings the editor exposes two Bind fields: base keys (held down) and subkey trigger (pressed once the base keys are held).

Configuration

The full schema for ~/.config/voxctrl/bindings.toml with one binding per gesture type:

[[binding]]
id        = "dictate_hold"
label     = "Dictate (Hold)"
keys      = ["KEY_LEFTMETA", "KEY_SPACE"]
gesture   = "hold"
target_ids = ["default"]
hold_threshold_ms = 200

[[binding]]
id        = "agent_command"
label     = "Agent (Double-tap)"
keys      = ["KEY_LEFTCTRL"]
gesture   = "double_tap"
target_ids = ["hermes"]
tap_ms    = 250

[[binding]]
id        = "chord_dictate"
label     = "Chord Dictation"
keys      = ["KEY_LEFTCTRL", "KEY_LEFTMETA"]
subkey    = "KEY_Z"
gesture   = "chord"
target_ids = ["default"]

Other fields: target_id (legacy singular target, resolved when target_ids is empty) and disabled (default false, disables a binding without removing it). LLM rewriting per binding is configured with the openai_enabled, openai_model, openai_mode, openai_prompt, and openai_system_prompt fields — the legacy ollama_* field names are still accepted as aliases.

Supported gesture values

Value Description
hold Record while key is held; stop on release
toggle First press starts; second press stops
double_tap Two presses within tap_ms window to activate
double_tap_hold Double-tap and keep held on the second press to start; release to stop
chord Hold the base keys and press the subkey trigger to start; release any base key to stop