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:
- Exact duplicate — both gestures fire simultaneously
- Superset shadowing — if one binding's keys are a subset of another's (e.g. Super+Space vs Ctrl+Super+Space), only the longer, more specific combo fires
- Double-tap overlap — double-tap key appears in a hold/toggle combo
- Bare single key — non-modifier key alone intercepts every press
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.
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 |