TuxFlow is a free, open-source voice-dictation app for Linux and macOS. Hold a global shortcut, speak naturally, then release it, and TuxFlow transcribes with a local OpenAI Whisper model before pasting into the app you were already using.
No account. No subscription. No paid API key. No uploaded recordings.
TuxFlow is an independent project and is not affiliated with Wispr Flow or OpenAI.
- Hold-to-dictate global shortcut: the XDG Desktop Portal on Linux, a Quartz event tap (hold 🌐 fn by default) on macOS
- Microphone recording through PipeWire, ALSA, or FFmpeg on Linux, and AVFoundation or SoX on macOS
- Local transcription with
tiny,base,small,medium,large-v3, orturboWhisper models - Automatic language detection or a pinned language
- Clipboard and automatic paste on Wayland, X11, and macOS
- Local transcription history with one-click copy
- Personal dictionary replacements
- Voice snippets for signatures, links, addresses, and canned replies
- Optional filler-word cleanup and spoken punctuation
- Optional “press enter” voice command
- A native GTK 4 / Libadwaita control center on both platforms
- A CLI for scripts, mouse bindings, and custom desktop shortcuts
TuxFlow uses faster-whisper, an MIT-licensed CTranslate2 implementation of Whisper. It downloads compatible converted model weights on first use and then runs inference locally. OpenAI releases the original Whisper code and model weights under the MIT license.
Download TuxFlow-*-x86_64.AppImage from the
latest release, make it
executable, and run it:
chmod +x TuxFlow-*-x86_64.AppImage
./TuxFlow-*-x86_64.AppImage doctor
./TuxFlow-*-x86_64.AppImage # opens the control centerIt carries its own Python, GTK 4, libadwaita, and faster-whisper, so nothing has to be installed first. It needs glibc 2.39 or newer — Ubuntu 24.04+, Fedora 40+, Debian 13+.
Three things stay on the host on purpose, because they talk to daemons the
bundle cannot reach from inside: a recorder (pw-record, arecord, or
ffmpeg), a clipboard tool (wl-clipboard or xclip), and ydotool/wtype
for automatic paste. All three are already present on most desktop installs, and
doctor names any that are missing. Automatic paste on Wayland also needs
/dev/uinput access, which only the installer below can set up; without it
TuxFlow copies the transcript and you press Ctrl+V.
The AppImage does not start at login on its own. Run ./TuxFlow-*.AppImage daemon from your session's autostart, or use the installer for a managed
service.
One command, from a clone of this repository:
./scripts/install.shThe installer never touches system Python. It:
- installs the desktop packages with
dnf/apt/pacman/zypperon Linux, or Homebrew on macOS; - creates an isolated Python environment under
~/.local/share/tuxflow/venv; - installs TuxFlow and faster-whisper into it;
- links
~/.local/bin/tuxflow; - adds the launcher entry — a
.desktopfile on Linux,~/Applications/TuxFlow.appon macOS; - starts TuxFlow at login with a systemd user service or a launchd agent; and
- finishes by running
tuxflow doctor.
Useful flags:
./scripts/install.sh --skip-system-packages # dependencies already installed
./scripts/install.sh --no-service # do not start TuxFlow at login
./scripts/install.sh --with-uinput # Linux: enable automatic paste via ydotoolRequirements: Python 3.11 or newer, and a desktop session. Set TUXFLOW_PYTHON
to pin a specific interpreter. Remove everything again with
./scripts/uninstall.sh (add --purge to delete settings, models, and history).
Fedora, Ubuntu/Debian, Arch, and openSUSE are handled directly; other
distributions work with --skip-system-packages once GTK 4, Libadwaita,
PyGObject, a recorder (pw-record, arecord, or ffmpeg), and wl-clipboard
are installed.
The first time the background service starts, your desktop asks you to approve
the global shortcut. The suggested trigger is Ctrl + Super + Space.
Homebrew is required; the installer uses it for ffmpeg and for the GTK stack.
macOS 12 or newer, on Apple silicon or Intel.
Two permissions have to be granted, and macOS only prompts for them in a foreground process — so run the daemon once from Terminal after installing:
tuxflow daemon- Microphone — prompted the first time you dictate.
- Accessibility — needed to watch the hotkey and to send ⌘V. Approve the app that is asking (Terminal, iTerm, or TuxFlow) in System Settings › Privacy & Security › Accessibility, then restart the service.
Finally, set System Settings › Keyboard › “Press 🌐 key to” to Do Nothing.
The event tap is listen-only, so it never swallows the key — without this
setting, holding fn also opens the emoji picker. Prefer a different key? Pick
right_command, right_option, or right_control under Settings in the
control center.
- Put the cursor in any text field.
- Hold the shortcut and speak.
- Release the shortcut.
- TuxFlow transcribes locally, cleans the text, and pastes it.
The first dictation downloads the selected model. The default small model is
a practical CPU balance and is roughly a 500 MB download. Choose base on
slower machines, or turbo when you have capable hardware and want higher
accuracy.
Useful commands:
tuxflow app # open the control center
tuxflow toggle # start or stop dictation
tuxflow cancel # discard the current recording
tuxflow status # inspect service state
tuxflow transcribe audio.wav # transcribe an existing file
tuxflow doctor # check this machine's integration
tuxflow update # check for, and on an AppImage install, a new releaseYou can bind tuxflow toggle to a mouse button or a desktop shortcut if the
built-in hotkey is unavailable.
Once a day, at most, TuxFlow asks GitHub whether a newer release exists. When there is one, a banner appears in the control center.
- AppImage — the banner has an Update button, and
tuxflow updatedoes the same thing from a terminal. TuxFlow downloads the new AppImage, compares its SHA-256 against theSHA256SUMSfile published with the release, and only then replaces itself with an atomic rename. If the checksum file is missing, or the digest does not match, nothing is installed and the old version keeps running. Restart TuxFlow afterwards to pick the new version up. The AppImage also carries standard update information, soAppImageUpdateand similar tools work on it. - Installed from source — the banner links to the release page instead.
Nothing is ever written over an installation that pip, your distribution, or
scripts/install.showns; pull the repository and re-run./scripts/install.sh. - Turning it off — Settings › Updates › Check for updates.
What the check sends: one anonymous HTTPS GET to
https://api.github.com/repos/Robertg761/TuxFlow/releases/latest, carrying
nothing but a user agent naming TuxFlow and its version. There is no account, no
identifier, and no upload of any kind — not your settings, not your history, not
a word of what you dictated. Only the timestamp of the last check is stored, in
~/.cache/tuxflow/update-check.json, so the request is not repeated on every
launch. Draft and prerelease builds are never offered.
TuxFlow has no telemetry or account system. After the selected model has been downloaded, dictation requires no network connection: the only request TuxFlow makes on its own is the daily update check described above, which can be turned off.
| Data | Default location | Default behavior |
|---|---|---|
| Settings | ~/.config/tuxflow/config.json |
Kept locally |
| History | ~/.local/share/tuxflow/history.sqlite3 |
Kept locally |
| Models | ~/.local/share/tuxflow/models/ |
Kept locally |
| Temporary audio | ~/.cache/tuxflow/recordings/ |
Deleted after transcription |
The same XDG paths are used on macOS, so everything TuxFlow stores stays in those three directories on both platforms. Use the Privacy page to clear history or opt into retaining audio.
TuxFlow deliberately uses standard components instead of bundling its own.
| Linux | macOS | |
|---|---|---|
| Hotkey | XDG GlobalShortcuts portal | Quartz CGEventTap (listen-only) |
| Recording | pw-record, arecord, ffmpeg |
ffmpeg (AVFoundation), sox |
| Clipboard | wl-copy, xclip, xsel |
pbcopy |
| Paste | ydotool, wtype, xdotool |
System Events (osascript) |
| Status | Tray icon (StatusNotifierItem) | Notifications |
| Autostart | systemd user service | launchd agent |
Every one of these is optional at import time, so the daemon starts even when a piece is missing and reports the gap instead of crashing.
Start with tuxflow doctor; it names the platform and checks each integration
point individually.
- "Copied, but automatic paste is unavailable" (Linux) — a locked-down
Wayland session will not let any app synthesise keystrokes. Run
./scripts/install.sh --with-uinputand log out and back in, or pressCtrl+Vyourself. - "Copied, but automatic paste is unavailable" (macOS) — Accessibility has not been granted to the process running the daemon.
- The hotkey does nothing on macOS — run
tuxflow daemonin Terminal and watch for the Accessibility prompt; a launchd agent cannot show one. - No microphone recorder found — install
pipewire-utils/pipewire-binon Linux, orbrew install ffmpegon macOS. - A specific microphone is needed — set it under Settings in the control
center; it maps to a
pw-record --target,arecord -D, FFmpeg AVFoundation index, or soxAUDIODEV. gimodule not found on macOS — the environment must be built from the same Homebrew Python thatpygobject3was built for. The installer does this automatically; if you built the venv by hand, delete it and rerun the script.
make dev # create or repair .venv (also fixes one moved to a new path)
make test
make lintOr run the processes directly:
.venv/bin/tuxflow daemon
.venv/bin/tuxflow appThe core modules do not import GTK, dbus-next, or PyObjC, which keeps text
processing, history, and configuration easy to test headlessly. Set
TUXFLOW_PLATFORM=macos or TUXFLOW_PLATFORM=linux to exercise the other
platform's code paths from either machine.
- Flatpak packaging and portal-native clipboard insertion
- A macOS menu-bar status item to match the Linux tray
- Optional local-LLM transforms through Ollama
- Context-aware capitalization without sending text off-device
- Packaging for distro repositories and a Homebrew tap
Contributions are welcome. See CONTRIBUTING.md.
TuxFlow is available under the MIT License.