Push-to-talk voice dictation for Linux using a Mac-hosted FreeFlow transcription API.
A Linux equivalent of FreeFlow (macOS). Hold a configurable hotkey (default: Right Ctrl) to record your voice — the audio is transcribed by the FreeFlow transcription API, then pasted into whatever app you have focused.
- Hold the hotkey for 1 second (a beep confirms recording has started)
- Speak
- Release the hotkey — the transcript is cleaned up and pasted into the focused window
The 1-second hold threshold prevents accidental triggers.
# Audio (PortAudio runtime)
sudo apt install libportaudio2 pipewire-alsa
# Paste — X11
sudo apt install xdotool xclip
# Paste — Wayland
sudo apt install wl-clipboard wtype # wlroots compositors (Sway, Hyprland, KDE)
sudo apt install ydotool # GNOME Wayland (also needs ydotoold daemon)python3 -m venv .venv
.venv/bin/pip install -r requirements.txtConfigure the Mac-hosted transcription API with environment variables:
export FREEFLOW_TRANSCRIPTION_URL=http://100.115.63.19:8765The Mac transcription API is unauthenticated on the trusted Tailscale bind.
freeflow-linux reads keyboard events directly from /dev/input via evdev. This requires
membership in the input group:
sudo usermod -aG input $USER
# Log out and back in for the group to take effectIf you use GNOME on Wayland, you need ydotool for paste to work:
sudo apt install ydotool
echo 'KERNEL=="uinput", GROUP="input", MODE="0660"' | sudo tee /etc/udev/rules.d/80-uinput.rules
sudo udevadm control --reload-rules
sudo systemctl enable --now ydotool
# Log out and back incd ~/code/freeflow-linux
.venv/bin/python freeflow_linux.py.venv/bin/python freeflow_linux.py --dry-runConfig file: ~/.config/freeflow-linux/config.toml (created automatically on first run)
transcription_url = "http://100.115.63.19:8765" # Or use FREEFLOW_TRANSCRIPTION_URL
hotkey = "KEY_RIGHTCTRL" # Right Ctrl — change to KEY_F9 etc. if preferred
# audio_device = "" # Leave empty to use system default micTo find available hotkey names, run evtest and press the key you want.
mkdir -p ~/.config/systemd/user
cp freeflow-linux.service.example ~/.config/systemd/user/freeflow-linux.service
# Edit the ExecStart path if needed
systemctl --user daemon-reload
systemctl --user enable --now freeflow-linuxExample service file:
[Unit]
Description=FreeFlow Linux voice dictation daemon
After=graphical-session.target
[Service]
ExecStart=/path/to/freeflow-linux/.venv/bin/python /path/to/freeflow-linux/freeflow_linux.py
Restart=on-failure
RestartSec=3
Environment=FREEFLOW_TRANSCRIPTION_URL=http://100.115.63.19:8765
Environment=XDG_SESSION_TYPE=x11
Environment=DISPLAY=:0
[Install]
WantedBy=default.target- Fn key: Does not work — handled by keyboard firmware, never reaches the kernel
- Right Ctrl (default): Reliable, rarely used for other shortcuts
- F9, ScrollLock, media keys: All work well as alternatives
| Feature | X11 | Wayland |
|---|---|---|
| Hotkey capture (evdev) | Yes | Yes |
| Paste | xclip + xdotool | wl-copy + wtype/ydotool |
| Window context | Yes (xdotool) | No |
| Terminal detection (Ctrl+Shift+V) | Yes | No |
Inspired by FreeFlow by Zach Latta. Uses the Mac-hosted FreeFlow transcription API for speech-to-text.